webpack从entry
开始递归解析所有依赖的模块,而怎么找到这些模块对应的文件,怎么更准确更快地找到这些模块所在文件,这就是resolve
擅长的了。我们来了解下。
resolve.modules
默认值是["node_modules"]
, 意思是,webpack默认先去 当前目录的node_modules
里找模块,要是没找着,就往上一级目录的node_modules
找,还没找着,就继续往上,直到找到为止。
要是到头了还是没找着,那说明根本没这模块。
举例
webpack
找模块的机制和Node
找模块一样,毕竟webpack
是基于nodejs
写的嘛。
所以,我们来看Node
是怎样解析模块的。
比如,我们可能会这样启动webpack
调试,node --inspect-brk node_modules\webpack\bin\webpack.js
webpack.js
里需要require.resolve('webpack-cli')
,即解析webpack-cli
这个模块的绝对路径。
解析过程是这样的:
项目根目录\node_modules\webpack\bin\node_modules
里找,没找到,往上项目根目录\node_modules\webpack\node_modules"
里找,没找到,继续往上项目根目录\node_modules
里找,找到了和webpack-cli
有关的目录:项目根目录\node_modules\webpack-cli
接下来就是要从项目根目录\node_modules\webpack-cli
这个目录找到webpack-cli
模块的入口文件。
怎么找?
Node
解析模块时会根据文件扩展名[".js", ".json",".node", ".mjs"]
去一 一查找。
-
项目根目录\node_modules
有没有webpack-cli.js
,没有 -
项目根目录\node_modules
有没有webpack-cli.json
,没有 -
项目根目录\node_modules
有没有webpack-cli.node
,没有 -
项目根目录\node_modules
有没有webpack-cli.mjs
,没有
怎么办?
项目根目录\node_modules\webpack-cli
里有没有package.json
,有!- 读取
package.json
内容,获取main
属性值:./bin/cli.js
所以模块webpack-cli
的入口文件所在绝对路径,即require.resolve('webpack-cli')
的结果 就是项目根目录\node_modules\webpack-cli\bin\cli.js
。
实践
实际使用的第三方模块,比如react
,vue
都是默认放在项目根目录的node_modules
里,所以可以指明路径,减少查找。
const path = require('path');
module.exports = {
resolve:{
modules:[path.resolve(__dirname,'node_modules')]
}
}
另外,如果我们自己开发的模块有经常被引用,也可以放到resolve.modules
里。
resolve.extensions
默认值是[".wasm",".mjs",".js",".json"]
。
如果导入的模块没有扩展名,webpack
会根据resolve.extensions
指定的扩展名一 一查找,谁在前就先查找谁,就像刚刚Node
解析webpack-cli
模块那样。
显然,如果我们导入模块时就带上文件扩展名,webpack
就不用费劲巴拉地找了,
如果我们提供的扩展名们准确,即使要找,webpack
也能更快地找到 。
所以,
import utils from './utils';import data from './data;'
不如import utils from './utils.js';import data from './data.json'
[".wasm",".mjs",".js",".json"]
比不上[".js",".json"]
resolve.alias
给文件路径取个别名,这样每次导入模块时就不用写一长串了。
const path = require('path');
module.exports = {
resolve:{
alias:{
'button':path.resolve(__dirname,'src/components/button.js')
//'button$':path.resolve(__dirname,'src/components/button.js')
}
}
}
所以不论哪个文件需要用到Button
,直接 import Button from 'button'
就好。
'button$':path.resolve(__dirname,'src/components/button.js')
用于精准匹配,button$
命中以button
结尾的文件。
再比如,vue$
命中vue.runtime.ems.js
或者vue.esm.js
等以vue
为结尾的文件。
resolve.mainFiles
默认值是["index"]
,意思是解析目录时,入口文件名是index
。