「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
resolve 选项用于设置模块如何解析:
- 在开发中我们会有各种各样的模块依赖,这些模块可能来自于自己编写的模块(比如我们当前项目中的
src/js/math.js、src/js/format.js、src/vue/App.vue等文件都是自己编写的模块),也可能来自第三方库(比如我们当前项目中的vue、axios); resolve可以帮助webpack从每个require/import语句中,找到需要引入的模块代码(意思就是resolve会帮我们决定模块到底是从node_modules(存放第三方的模块)目录下去找,还是从自己编写的模块中去找);webpack在打包模块时会使用enhanced-resolve这个库来解析文件路径;
1. 解析路径
webpack 能解析三种文件路径:
-
绝对路径
-
也就是完整的路径。由于已经获得文件的绝对路径,因此不需要再做进一步解析。
-
举例:
import '/home/me/file' import 'C:\\Users\\me\\file'
-
-
相对路径
-
在这种情况下,使用
import或require的资源文件所处的目录,被认为是上下文目录; -
在
import/require中给定的相对路径,会拼接此上下文路径(即当前文件所在的目录),来生成模块的绝对路径; -
举例:
import { sum } from './js/math'; const { formatPrice } = require('./js/format'); import './js/element'; import '../src/file1';
-
-
模块路径
-
在
resolve.modules中指定的所有目录中检索模块:-
默认值是
['node_modules'],所以默认会从node_modules中查找文件(这也是为什么比如我们import { createApp } from 'vue';时,webpack会知道直接去项目目录下的node_modules目录下的vue文件夹中去加载相应模块),也就是说webpack默认给我们做了如下配置:module.exports = { //... resolve: { modules: ['node_modules'] } }当然,你也可以根据实际需求进行修改。
-
-
我们可以通过设置别名的方式(通过
resolve.alias配置选项来设置)来替换初始模块路径;
-
2. 判断是文件还是文件夹
在解析出模块的绝对路径之后,解析器将会检查路径是指向文件还是文件夹。
- 如果是一个文件:
- 如果文件具有文件扩展名,则直接打包该文件;
- 否则,将解析
resolve.extensions选项(该选项会告诉解析器在解析过程中可以接受哪些扩展名,比如.js、.json、.wasm等等)中的内容来作为文件扩展名;resolve.extensions选项的默认值是['.js', '.json', '.wasm'],在没有指定文件后缀名时,会尝试按顺序解析该选项对应的数组中的元素,一旦匹配上了某个后缀名,就不会再对后面的后缀名进行匹配了。
- 如果是一个文件夹:
- 会在文件夹中根据
resolve.mainFiles配置选项中指定的文件顺序查找;resolve.mainFiles的默认值是['index'](我们一般不会修改这个配置选项的默认值);- 再根据
resolve.extensions来解析扩展名;- 正因如此,假如我们项目目录下有一个路径为
src/utils/index.js的文件,当我们想要导入这个文件时,我们可能通常会这样做:import './utils',而并不需要继续写完整:import './utils/index.js'。
- 正因如此,假如我们项目目录下有一个路径为
- 会在文件夹中根据
以上,就是 webpack 中模块的解析规则,也是 enhanced-resolve 这个库的解析规则。知道了这些规则,我们就知道了为什么有时候我们可以不加后缀名,甚至文件夹之后 index.js 文件也可以不加的原因(enhanced-resolve 会自动帮我们加的)。