在运用前端主流框架(react,vue,angular)开发过程当中,引入一个模块或文件路径,是如何解析到目标文件的?是按照什么样的规则和顺序查找到的?这个问题乍一看是简单,尤为在小型项目中,模块和文件并很少的状况下。但遇到一些比较复杂的项目,模块和文件路径的引入须要谨慎当心,这就须要深刻地理解一下webpack的代码路径解析规则了。css
首先,综合一下在项目中配置路径的三种形式前端
相对路径是相对于当前目录的路径vue
import {button} from '../component/button'
复制代码
绝对路径直接指明了文件的具体位置,直接能够查找到(不建议使用)node
import {button} from '/home/me/file'
复制代码
直接引入模块名,会查找当前文件目录,父级目录直至根目录下的 node_modules(默认) 文件夹,看是否有对应名称的模块。react
import React from 'react'
import "module/lib/file";
复制代码
注意:默认的node_modules能够根据webpack配置的
resolve.modules
进行更改webpack
注意:查找中会根据webpack配置的
resolve.extensions
自动补全扩展名web
注意:查找中会根据wepack配置的
resolve.alias
替换掉别名json
根据上述规则解析路径后,解析器将路径指向文件或者文件夹(目录)bash
若是是文件,直接加载框架
若是是文件夹,查找里面是否有package.json文件
1)若是有,默认按照里面的main字段的文件名查找文件 (能够经过resolve.mainFields
配置更改)
2)若是没有,默认查找index.js文件(能够经过resolve.mainFiles
配置更改)
了解上述的路径形式和最终的解析规则后,根据个人一些标识,大体上也可以看出webpack路径配置的发挥空间了。
webpack解析代码路径的核心模块是
enhanced-resolve
模块
webpack解析匹配代码路径的配置在
resolve
里面
接下来将着重对resolve中alias,extensions,modules,mainFields,mainFiles属性作单独详细的介绍。
alias,顾名思义,是指路径的别名。简单点说,就是用一个简单的别名来替换一个经常使用的或者复杂的文件路径。
原理:先替换,后解析。在引入模块时,先将模块路径中匹配alias中的key替换成对应的value,再作查找。
注意一下几点:
resolve: {
alias: {
'@': path.resolve(__dirname, 'components'),
// 这里使用 path.resolve 和 __dirname 来获取绝对路径
// import '@/Button.js' 等同于 import '[项目绝对路径]/components/Button.js'
x: './src/components' // 相对路径
}
}
复制代码
2.这里的匹配是模糊匹配,不是精确匹配。即路径中携带别名便可匹配
3.注意精确匹配的用法。在key的末尾带一个$字符
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'x$': 'module/dir'
// Import 'x/file.js' // 这里不能匹配
}
}
复制代码
extensions中指定了webpack能够识别的文件扩展名。
注意一下几点:
resolve: {
extensions: ['js', 'vue', 'json']
}
复制代码
查找声明依赖名的模块,默认搜索node_modules目录。通常咱们不修改这个配置。
resolve: {
modules: ['node_modules']
},
复制代码
在引用模块时,指明使用package.json中哪一个字段指定的文件,默认是“main”
resolve: {
// 配置 target === "web" 或者 target === "webworker" 时 mainFields 默认值是:
mainFields: ['browser', 'module', 'main'],
// target 的值为其余时,mainFields 默认值为:
mainFields: ["module", "main"],
}
复制代码
由于一般状况下,模块的 package 都不会声明 browser 或 module 字段,因此即是使用 main 了。
在目录中没有package.json时,指明使用该目录中哪一个文件,默认是index.js
resolve: {
mainFiles: ['index'], // 能够添加其余默认使用的文件名
}
复制代码
resolve除了上面介绍的几个属性外,还有其余一些属性,有兴趣的筒子们能够再深刻研究一下。但愿我这篇文章对还不太清楚webpack代码路径的童鞋有必定的指引做用~~