webpack提高构建性能方式
- 尽可能少用loader;
- 使用babel-loader时,指定代码转译范围;
include: path.resolve(__dirname,'../src') ,//仅对指定路径下文件进行转译
exclude: /node_modules/ //避免对node_modules中的文件进行转译
- 使用noParse避免对引入的第三方模块(如jquery|bootstrap)解析内部依赖关系,减少打包时间;
- 使用IgnorePlugin,忽略第三方模块内部依赖的其他模块;
- 使用DllPlugin,对几乎不变的第三方模块、框架只进行一次打包,以后仅打包业务代码;
- Happypack、thread-loader 多进程打包(不适合webpack4,已过时,不推荐使用)
noParse
webpack性能的表现之一就是打包速度,打包速度常依赖于项目的规模,如果项目规模本身比较大,如过能提升打包速度就更好了
在引入一些第三方模块时,例如jQuery、bootstrap等,我们知道其内部肯定不会依赖其他模块,因为最终我们用到的只是一个单独的js文件或css文件
所以此时如果webpack再去解析他们的内部依赖关系,其实是非常浪费时间的,我们需要阻止webpack浪费精力去解析这些明知道没有依赖的库,从而减少了打包所需要的时间
可以在webpack配置文件的module
节点下加上noParse
,并配置正则来确定不需要解析依赖关系的模块
webpack.base.js
module.exports = merge(baseWebpackConfig, {
//optimization: { },
module: {
noParse: /jquery|bootstrap/
}
...
}
IgnorePlugin
在引入一些第三方模块时,例如moment,内部会做i18n国际化处理,所以会包含很多语言包,而语言包打包时会比较占用空间,如果我们项目只需要用到中文,或者少数语言,可以忽略掉所有的语言包,然后按需引入语言包
从而使得构建效率更高,打包生成的文件更小
需要忽略第三方模块内部依赖的其他模块,只需要三步:
- 首先要找到moment依赖的语言包是什么
- 使用IgnorePlugin插件忽略其依赖
- 需要使用某些依赖时自行手动引入
具体实现如下:
-
通过查看moment的源码来分析:
function loadLocale(name) { var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node if (!locales[name] && (typeof module !== 'undefined') && module && module.exports) { try { oldLocale = globalLocale._abbr; var aliasedRequire = require; aliasedRequire('./locale/' + name); getSetGlobalLocale(oldLocale); } catch (e) {} } return locales[name]; }
观察上方代码,同时查看moment目录下确实有locale目录,其中放着所有国家的语言包,可以分析得出:locale目录就是moment所依赖的语言包目录
-
使用IgnorePlugin插件来忽略掉moment模块的locale目录
在webpack配置文件中安装插件,并传入配置项
参数1:表示要忽略的资源路径
参数2:要忽略的资源上下文(所在哪个目录)
两个参数都是正则对象
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
-
使用moment时需要手动引入语言包,否则默认使用英文
import moment from 'moment' import 'moment/locale/zh-cn' moment.locale('zh-CN') console.log(moment().subtract(6, 'days').calendar())
DllPlugin
在引入一些第三方模块时,例如vue、react、angular等框架,这些框架的文件一般都是不会修改的,而每次打包都需要去解析它们,也会影响打包速度,哪怕做拆分,也只是提高了上线后用户访问速度,并不会提高构建速度,所以如果需要提高构建速度,应该使用动态链接库的方式,类似于Windows中的dll文件。
借助DllPlugin插件实现将这些框架作为一个个的动态链接库,只构建一次,以后每次构建都只生成自己的业务代码,可以大大提高构建效率!
主要思想在于,将一些不做修改的依赖文件,提前打包,这样我们开发代码发布的时候就不需要再对这部分代码进行打包,从而节省了打包时间。
涉及两个插件:
-
DllPlugin
使用一个单独webpack配置创建一个dll文件。并且它还创建一个manifest.json。DllReferencePlugin使用该json文件来做映射依赖性。(这个文件会告诉我们的哪些文件已经提取打包好了)
配置参数:
- context (可选): manifest文件中请求的上下文,默认为该webpack文件上下文。
- name: 公开的dll函数的名称,和output.library保持一致即可。
- path: manifest.json生成的文件夹及名字
-
DllReferencePlugin
这个插件用于主webpack配置,它引用的dll需要预先构建的依赖关系。
context: manifest文件中请求的上下文。
manifest: DllPlugin插件生成的manifest.json
content(可选): 请求的映射模块id(默认为manifest.content)
name(可选): dll暴露的名称
scope(可选): 前缀用于访问dll的内容
sourceType(可选): dll是如何暴露(libraryTarget)
将Vue项目中的库抽取成Dll
-
准备一份将Vue打包成DLL的webpack配置文件
在build目录下新建一个文件:webpack.vue.js
配置入口:将多个要做成dll的库全放进来
配置出口:一定要设置library属性,将打包好的结果暴露在全局
配置plugin:设置打包后dll文件名和manifest文件所在地
const path = require('path') const webpack = require('webpack') module.exports = { mode: 'development', entry: { vue: [ 'vue/dist/vue.js', 'vue-router' ] }, output: { filename: '[name]_dll.js', path: path.resolve(__dirname, '../dist'), library: '[name]_dll' }, plugins: [ new webpack.DllPlugin({ name: '[name]_dll', path: path.resolve(__dirname, '../dist/manifest.json') }) ] }
-
在webpack.base.js中进行插件的配置
使用DLLReferencePlugin指定manifest文件的位置即可
plugins: [ new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '../dist/manifest.json') }) ]
-
安装add-asset-html-webpack-plugin
npm i add-asset-html-webpack-plugin -D
-
配置插件自动添加script标签到HTML中
new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dist/vue_dll.js') })
将React项目中的库抽取成Dll
-
准备一份将React打包成DLL的webpack配置文件
在build目录下新建一个文件:webpack.vue.js
配置入口:将多个要做成dll的库全放进来
配置出口:一定要设置library属性,将打包好的结果暴露在全局
配置plugin:设置打包后dll文件名和manifest文件所在地
const path = require('path') const webpack = require('webpack') module.exports = { mode: 'development', entry: { react: [ 'react', 'react-dom' ] }, output: { filename: '[name]_dll.js', path: path.resolve(__dirname, '../dist'), library: '[name]_dll' }, plugins: [ new webpack.DllPlugin({ name: '[name]_dll', path: path.resolve(__dirname, '../dist/manifest.json') }) ] }
-
在webpack.base.js中进行插件的配置
使用DLLReferencePlugin指定manifest文件的位置即可
new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '../dist/manifest.json') })
-
安装add-asset-html-webpack-plugin
npm i add-asset-html-webpack-plugin -D
-
配置插件自动添加script标签到HTML中
new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dist/react_dll.js') })