resolve.alias
resolve.alias
用于给模块路径指定别名。
为什么要给模块路径取别名呢?
假设在我们的源码中有如下 import
语句:
import BaseModel from '../../../../common/BaseModel';
export default class ProductModel extends BaseModel {
// some code here
}
那么每次引入 BaseModel
的时候,很可能都会面临着写很长一堆 ../../../../
的问题,而且如果没有编辑器的智能提示,很容易少写(或者多写)一层 ../
。
此时就可以在 webpack 配置中为 BaseModel
指定一个别名:
{
// some other configs
resolve: {
alias: {
common: require('path').resolve(__dirname, '../src/common')
}
}
// some other configs
}
这样一来,引入 BaseModel
的代码就变成下面这样了:
import BaseModel from 'common/BaseModel';
另外一种场景,就是去掉路径中的无意义的一层(站在使用者角度来说无意义)。比如安装了 vue
模块之后,如果不做任何配置,引入 vue
的代码看起来是这样的:
import Vue from 'vue/dist/vue.esm.js';
看起来多多少少会觉得别扭,而且还不好调整成不同的版本(开发时用 vue.esm.js
,发布的时候用 vue.runtime.js
)。
此时在 webpack 中加上不同环境的别名:
{
// some other configs
resolve: {
alias: {
vue$: process.env.NODE_ENV === 'production'
? 'vue/dist/vue.runtime.js' : 'vue/dist/vue.esm.js'
}
}
// some other configs
}
看起来就优雅很多了。
那么 alias
的原理是怎么样的呢?
配置了 alias
之后,在 webpack 解析引入(通过 import 或者 require )的模块的时候,会先将源码中的模块路径中匹配 alias 里 key 的部分替换成 value 部分,再做查找。
比如源码中有如下引入语句:
import Test1 from 'xyz/file';
alias
中有如下配置:
{
// some other configs
resolve: {
alias: {
xyz: './dir'
}
}
// some other configs
}
在解析路径的时候,会先将 xyz
替换成 ./dir
,那么之前的 import
语句就相当于:
import Test1 from './dir/file.js';
然后 webpack 再基于 ./dir/file.js
去查找需要引入的模块。
当然,也可以配置绝对路径:
{
// some other configs
resolve: {
alias: {
xyz: require('path').resolve(__dirname, '../dir')
}
}
// some other configs
}
依然按照之前先替换后解析的流程执行。
另外,alias
还有一种特殊的语法:key 的末尾带一个 $ 字符,表示精确匹配。
假设有下面 alias
配置:
{
// some other configs
resolve: {
alias: {
xyz$: 'xyz/dir'
}
}
// some other configs
}
对于:
import 'xyz/file.js';
这种 import
语句,就无法匹配上这条 alias
规则。
而:
import 'xyz';
才能匹配上。
更多 alias
的匹配示例,参考官网文档。
resolveLoader.modules
可以通过 resolveLoader.modules
配置在哪些目录下查找 loader
,默认是在 node_modules
目录下查找。
那么问题就来了,这个默认的 node_modules
指的是哪里的 node_modules
目录呢?换句话说,这里的 node_modules
目录对应的绝对路径是怎么构造的?
webpack 会以当前进程目录( process.cwd()
)开始,逐层往上查找 node_modules
目录,如果查到根目录,还没找到,就抛出错误。这与 Node 查找 node_modules
目录的行为是一致的,只不过 Node 是从当前模块所在目录开始查找的。
对于其他的相对目录配置,查找逻辑与默认的 node_modules
一样
对于绝对路径,就直接找这个路径对应的目录了。
权威说明,可参考官网文档。
找到 resolveLoader.modules
的具体目录之后,就按照配置的顺序去查找 loader
了。
假设有如下配置:
{
// some other configs
resolveLoader: {
modules: ['loaders1', 'loaders2']
}
// some other configs
}
如果当前进程目录是 /a/b/c
,现在要查找 babel-loader
,就会按照如下顺序查找:
/a/b/c/loaders1/babel-loader/...
/a/b/c/loaders2/babel-loader/...
/a/b/loaders1/babel-loader/...
/a/b/loaders2/babel-loader/...
/a/loaders1/babel-loader/...
/a/loaders2/babel-loader/...
/loaders1/babel-loader/...
/loaders2/babel-loader/...
注:上述示例省略号后面的内容根据其他配置确定,具体参看官网文档,此处不赘述。
Rule.include 、 Rule.exclude 等路径配置
Rule
中的 test
、 include
、 exclude
的值都是 Condition
实例。
Condition
实例可以使下面的某一种值:
- 一个字符串:输入值必须以该字符串开始。
- 一个正则表达式。
- 一个由
Condition
实例组成的数组。 - 一个对象:必须匹配所有属性,每一个属性的行为都是预先定义好的(属性 key 只能是
and
、or
或者not
)。
对于 Rule.test
,值只能是一个正则表达式或者一个正则表达式数组。
对于 Rule.include
,值只能是一个字符串或者一个字符串数组。
Rule.exclude
的值和 Rule.include
一样。
更详细的描述,参考官网文档。
所以,Rule.include
和 Rule.exclude
配置都会使用绝对路径。
entry
entry 中配置的相对路径,是相对于 process.cwd()
去查找的。
output.path
必须配置成一个绝对路径。
babelrc 中的 plugins
和 presets
路径
babelrc 中 plugins
和 presets
配置的相对路径是相对于待转换文件解析的。
比如在转换 /a/b/c/d.js
模块的时候,查找 babel-plugin-veui
的顺序是:
/a/b/c/node_modules/babel-plugin-veui/...
/a/b/node_modules/babel-plugin-veui/...
/a/node_modules/babel-plugin-veui/...
/node_modules/babel-plugin-veui/...
presets
的解析逻辑与 plugins
一致。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。