Vue 项目之 Webpack 中 Resolve 的配置(1)

287 阅读3分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

resolve 选项用于设置模块如何解析:

  • 在开发中我们会有各种各样的模块依赖,这些模块可能来自于自己编写的模块(比如我们当前项目中的 src/js/math.jssrc/js/format.jssrc/vue/App.vue 等文件都是自己编写的模块),也可能来自第三方库(比如我们当前项目中的 vueaxios);
  • resolve 可以帮助 webpack 从每个 require/import 语句中,找到需要引入的模块代码(意思就是 resolve 会帮我们决定模块到底是从 node_modules(存放第三方的模块)目录下去找,还是从自己编写的模块中去找);
  • webpack 在打包模块时会使用 enhanced-resolve 这个库来解析文件路径

1. 解析路径

webpack 能解析三种文件路径:

  1. 绝对路径

    • 也就是完整的路径。由于已经获得文件的绝对路径,因此不需要再做进一步解析。

    • 举例:

      import '/home/me/file'
      import 'C:\\Users\\me\\file'
      
  2. 相对路径

    • 在这种情况下,使用 importrequire 的资源文件所处的目录,被认为是上下文目录;

    • import/require 中给定的相对路径,会拼接此上下文路径(即当前文件所在的目录),来生成模块的绝对路径;

    • 举例:

      import { sum } from './js/math';
      const { formatPrice } = require('./js/format');
      import './js/element';
      import '../src/file1';
      
  3. 模块路径

    • 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 会自动帮我们加的)。