Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Node

  • VSCode插件

  • Webpack

    • webpack源码分析一:AST语法
    • webpack源码分析二:模块化语法
    • webpack源码分析三:源码分析
    • webpack 配置[TODO]
    • 如何利用requireContext实现批量导入
      • 前言
      • require.context 语法
      • 批量导入代码
        • javascript 版本
        • typescript 版本
      • 初步分析
      • 导出拦截
      • 参考博客:
  • Redux

  • React源码

  • 组件库

  • React高阶系列

  • UMI插件

  • 前端工程化

  • 单元测试vitest

  • 重点技术
  • Webpack
wangjiasheng
2022-10-02
目录

如何利用requireContext实现批量导入

# 前言

最近在做一个图标组件,需要批量导入图片,如下:

import "./icons/alipay.svg"
import "./icons/qq.svg"
import "./icons/wechat.svg"
1
2
3

webpack 中提供了require.context 可以实现这个自动批量导入功能。

# require.context 语法

require.context(directory,useSubdirectories,regExp)
1
  • directory:表示检索的目录

  • useSubdirectories:表示是否检索子文件夹

  • regExp:匹配文件的正则表达式,一般是文件名

# 批量导入代码

注:以下版本导入时,无返回值。

# javascript 版本

以下代码可以 递归 导入 icons 文件夹下所有的 svg 图片

function importAll(requireContext){
  return requireContext.keys().map(requireContext)
}
1
2
3

使用时:

try {
  importAll(require.context('./icons/', true, /\.svg$/));
  })
} catch (error) {
  // 注释的目的:防止在 test 环境下没有 require.context
  // console.log(error)
}
1
2
3
4
5
6
7

# typescript 版本

步骤如下:

  1. 安装@types/webpack-env

  2. 配置tsconfig.json

    {
        "compilerOptions": {
            ...
            "types": [
                "webpack-env"
            ]
        },
        ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  3. typescript 类型定义如下:

    function importAll(requireContext: __WebpackModuleApi.RequireContext){
      return requireContext.keys().map(requireContext)
    }
    
    1
    2
    3

    使用方法同 js 案例

# 初步分析

其实对这部分原理理解也不是很深,如果想要进一步了解 webpack 运行机制可以看《深入理解webpack的require.context》 (opens new window) 这篇文章。

注:以下为读取 svg 图片,使用 sprite-svg-loader 进行转化。

上述给的 js 版本或是 ts 版本,过于抽象,等价实现如下:

const requireComponents = require.context("./icons", true, /\.svg$/);
  requireComponents.keys().forEach(fileName => {
    console.log("pic:", fileName);
    console.log("module:",requireComponents(fileName));
})
1
2
3
4
5

打印如下:

pic: ./alipay.svg
module: Module {default: BrowserSpriteSymbol, __esModule: true, Symbol(Symbol.toStringTag): 'Module'}

pic: ./qq.svg
module: Module {default: BrowserSpriteSymbol, __esModule: true, Symbol(Symbol.toStringTag): 'Module'}

pic: ./wechat.svg
module: Module {default: BrowserSpriteSymbol, __esModule: true, Symbol(Symbol.toStringTag): 'Module'}
1
2
3
4
5
6
7
8

可以发现 pic 即为导入 svg 相对路径地址,而 module 则为由 webpack 处理过后的 module 。通过 __esModule 可知其为 ESModule 模块,还需通过 .default 进一步取出模块内容。

注:如 svg 是由 file-loader 做处理的话,打印结果如下:

pic: ./alipay.svg
static/alipay.55c59806.svg

pic: ./qq.svg
/static/qq.74ed9feb.svg

pic: ./wechat.svg
/static/wechat.2d422b78.svg
1
2
3
4
5
6
7
8

此时,require.context 导入的实际上是一个路径地址。

上述已经拿到了 module 后,那如何导入这些模块呢?实际上 requireComponents(fileName) 这个语句即等价于导入。它是一个函数两个作用,在导入模块的同时,又将 module 内部信息输出,如下:

验证如下:只打印,让函数无返回值。

const requireComponents = require.context("./icons", true, /\.svg$/);
  requireComponents.keys().forEach(fileName => {
    //注:这里只打印,无需显式写 requireComponents(fileName) 也可以完成模块的导入。
    console.log("module:",requireComponents(fileName));
})
1
2
3
4
5

也即,在 importAll 这个函数,无导出也是可以成立的,如下:

type requireContextType = __WebpackModuleApi.RequireContext;
function importAll(requireContext: requireContextType): void {
  requireContext.keys().forEach(requireContext)
}
1
2
3
4

但是,在使用时只能以 import "./importAll" 的当时导入模块了。

# 导出拦截

导出变量时还需要考虑一个问题就是,导入的模块的语法规范(cjs 还是 ejs),为了支持不同语法规范时,需要对代码做进一步修改:

function importAll(r){
  return r.keys().map(f => r(f).default || r(f))
}
1
2
3

如果想要进一步控制导出的内容也是可以的,只需要魔改上述代码即可,举例:

以下代码为 yy ,感觉可以实现。

function importAll(r){
  let images = {};
  r.keys().forEach(f => {
     // 进一步过滤文件   
     if(/正则语法/g.test(f)){
       let obj = r(f).default || r(f);
       // 比如说将读取到的 svg 里面全部改为 
       images.push({[svgName]:obj});
     }
  })
  return images
}

const images = importAll(require.context('./images', false, '/\.png/'));

// 调用时:
<img src={images["0.png"]}>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 参考博客:

  1. 《深入理解webpack的require.context》 (opens new window)
编辑 (opens new window)
上次更新: 2022/10/07, 11:10:00
webpack 配置[TODO]
redux 源码分析一:常用API介绍

← webpack 配置[TODO] redux 源码分析一:常用API介绍→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式