缩小文件的查找范围
Webpack会按照默认的查找范围从入口文件开始递归查询和处理依赖,当使用import/require等导入语句的时候,Webpack会根据导入语句去导入对应的模块,之后根据导入文件的后缀,在去使用对应的loader去解析文件。当我们的项目变得十分庞大的时候,这种处理是十分耗时的,而这种处理是无法避免的,所以需要从查找范围入手,减少Webpack查找的时间,使得构建加速。
Loader作用范围缩减
开发项目,我们很明确我们要处理的各种文件的位置,同时也知道那种文件需要用Loader进行处理。所以在配置Loader的时候可以适当的使用test,include,exclude三个配置项来精确命中需要被Loader处理的文件。
之前实战中Babel-loader的配置可以修改如下:
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve(__dirname, 'src'),
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
]
}
},
'eslint-loader'
]
}
使用test,告诉Webpack使用Bael-loader只处理JavaScript文件,include和exclude告诉Webpack需要处理哪些位置的文件。有时候我们适当修改项目目录结构,也可以增加Webpack命中处理文件的几率。
第三方模块查找范围缩减
Webpack中查找第三方模块跟Node.js中的模块寻找机制很相似。默认去当前目录下的node_modules中去寻找,没有找到就去上一级目录node_modules中去寻找,以此类推。
当我们明确安装的第三方模块都放在当前目录的node_modules下的时候,那么我们可以直接设置resolve.modules的值,减少一层层的寻找。设置如下:
module.exports = {
resolve: {
modules: [path.resolve(__dirname, 'node_modules')]
}
}
之前介绍过resolve.mainFields用于配置使用第三方模块的哪个入口文件。通常模块只有一个入口文件,但是有些模块为了兼容多个执行环境,会有多个入口文件,具体使用哪个入口文件由开发者自己决定。模块的package.json文件指明模块有哪些入口文件和对应的文件所处的位置,如下所示:
{
"main": "index.js",
"browser": "main.js"
}
在读取模块的入口文件的时候,Webpack会根据mainFields设置的值,去依次查找。假如我们项目所有的第三方模块都采用main字段描述入口文件的位置,为了减少搜索时间,那么我们可以修改配置如下:
module.exports = {
resolve: {
mainFields: ['main']
}
}
注意,当其中一个第三方模块入口文件的描述字段不是main的时候,该配置就会报错。建议在知道所有第三方模块入口文件描述字段后,再合理使用mainFields进行配置。
导入路径映射
在之前实战中,在书写模块引入语句的时候,会加上很长一段的文件路径,比如:import historyDep from “…/…/…/utils/history”;当项目足够大,项目层次逐渐变深的时候,那么我们在里层文件引入外层文件,所要书写的路径就越来越长,十分不优雅,甚至还可能出现引入路径书写的错误。
通过配置resolve.alias可以给对应的文件或者目录位置加上一个映射,当我们使用resolve.alias设置的路径的时候,Webpack会使用自动帮我们找到所导入文件的正确位置。如下所示:
module.exports = {
resolve: {
alias: {
'@utils': path.resolve(__dirname, 'src/utils')
}
}
}
配置以后,就可以像这样引入相关文件:
import historyDepfrom "@utils/history";
某些第三方模块,会有几套代码,比如模块中存在CommonJS规范的代码和一套无任何依赖的完整代码,默认使用的是模块CommonJS规范的代码,那么该文件中会存在依赖其他文件的情况,Webpack就会去处理对应的依赖文件,这是一个十分耗时的情况,我们可以使用resolve.alias指定使用该模块的时候使用那套完整的代码,这样子就没有其他依赖文件的处理了,这种模块还是比较常见的,比如React。当你对一个模块的文件组成很熟悉的时候,可以采用resolve.alias去优化模块的加载。
文件后缀的省略处理
在之前实战中,会经常有省略文件后缀名的引入语句,比如:import historyDep from “@utils/history”;,在这里我们没有指定引入文件的后缀,但是Webpack还是能够正确解析处理,是因为resolve.extensions中规定了哪种类型的文件在被引入的时候可以省略后缀,其默认值是:extensions: [".js", “.json”],在省略文件后缀的时候,Webpack会根据extensions的值依次去匹配,直到找到对应的文件。比如使用vue开发的时候,extensions的配置为extensions: [".vue",".js", “.json”],这样不管是vue文件和js文件都可以省略后缀导入。
但是项目会出现.vue和.js文件大量共存和大量被引入的情况,这个时候省略后缀引入文件,Webpack寻找该文件就会产生一个概率的问题,为了正确寻找到该文件,Webpack避免不了多次执行查找操作。如果你习惯了省略后缀的引入,又想避免Webpack的多次查找,你可以新建一个JavaScript文件,其中的操作就是引入vue组件,然后在导出该Vue组件,不需要任何额外的操作,然后直接使用Extensions的默认值即可,这样一来,构建效率会较之前有所提高。
import Home from 'index.vue';
export default Home;
排除相关模块的解析处理
例如jQuery,Lodash这种大型库,其内部没有import, require, define模块化语句的调用,或任何其他导入机制。使用Webpack对这些模块进行解析和处理是没有必要的,反而会降低构建性能。通过noParse的配置可以告诉Webpack,忽略对哪些文件的解析处理,以此来提高构建性能。如下所示:
module.exports = {
module: {
noParse: /jquery|lodash/
}
}
使用noParse要明确的是,被忽略的文件或者模块内部没有import, require, define等语句的调用,或任何其他导入机制,不然会导致在构建出的代码中包含无法在浏览器环境下执行的模块化语句。
通过合理使用以上所有文件处理范围的方法,Webpack的构建性能会有一定的提升。
|