对Webpack、Node、Npm、Yarn等技术进行版本的升级,相关技术的版本更新,官网都会做出优化,升级技术可以一定程度的提高打包的性能
合理的使用 exclude / include
可以降低使用 loader 的频率从而提高打包速度,如 exclude: /node_modules/
因为 node_modules
中的代码是已经被转换过的代码,可以不必使用 loader 做二次转换。也即尽可能的让 Loader 的作用范围缩小,代码分析的范围少了,性能也就能得到提升。
插件需要合理的需用,对于没有意义的插件或冗余的插件应去掉。在使用插件时应首选官方推荐或社区认可的插件。例如在开发环境中不使用插件对 CSS 代码进行压缩,仅在正式环境时才使用,因此,在开发时,代码的打包速率在一定程度上会得到提升。在使用插件时尽可能采用webpack官方推荐的插件,因为这些插件官方进行推荐的话是经过一定的测试验证的。个人或第三方插件的性能并不一定能得到保证。
在 resolve 中配置解析的顺序:
webpack.config.js
module.exports = {
entry: {
main: './src/index.js'
},
resolve: {
extensions: ['.js', '.jsx']
}
}
index.js
import child from './child/child'
在上面的引入中,因为配置了 resolve.extensions ,所以在引入时没有写上后缀时,webpack 会在 child 文件夹中首先解析是否存在 child.js 文件,如果不存在则继续寻找是否存在 child.jsx文件,如果都不能存在就会报错。extensions 配置的数组列表中不应配置过多的列表项。
在 resolve 中通过 alias 为文件夹设置别名:
webpack.config.js
module.exports = {
// ...
resolve: {
alias: {
@: path.resolve(__dirname, 'src')
}
}
}
index.js
import child from '@/child/child.js'
因为第三方的库文件等是不会变化的,不必每次打包时都分析,所以对可以对第三方模块只打包一次,生成 dll 文件,引入第三方模块时去使用 dll 文件引入
index.js
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import _ from 'lodash';
class App extends Component {
render() {
return (
{_.join(['This', 'is', 'App'], ' ')}
)
}
}
ReactDom.render( , document.getElementById('root'));
webpack.config.dll.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production',
entry: {
vendors: ['lodash'],
react: ['react', 'react-dom'],
jquery: ['jquery']
},
// 打包成库,通过变量的形式暴露出去
output: {
filename: '[name].dll.js',
path: path.resolve(__dirname, '../dll'),
library: '[name]'
},
// 打包时做一个dll文件分析的映射
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: path.resolve(__dirname, '../dll/[name].manifest.json'),
})
]
}
package.json
{
// ...
"script": {
// ...
"build:dll": "webpack --config ./build/webpack.config.dll.js"
// ...
}
}
运行命令 npm run build:dll
进行打包
安装 add-asset-html-webpack-plugin
插件,用于在 index.html 中增加静态资源
webpack.config.common.js
const path = require('path');
const fs = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
const webpack = require('webpack');
const plugins = [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(['dist'], {
root: path.resolve(__dirname, '../')
})
];
// 引入第三方模块的时候,去使用打包好的 dll 文件进行引入
const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
files.forEach(file => {
// 将打包好的 dll 文件引入使用
if(/.*\.dll.js/.test(file)) {
plugins.push(new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, '../dll', file)
}))
}
// 分析dll中第三方模块的映射关系进行使用
// 如果不配置,打包是第三方模块将依旧从 node_modules 中寻找分析
if(/.*\.manifest.json/.test(file)) {
plugins.push(new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, '../dll', file)
}))
}
})
module.exports = {
entry: {
main: './src/index.js',
},
resolve: {
extensions: ['.js', '.jsx'],
},
module: {
rules: [{
test: /\.jsx?$/,
include: path.resolve(__dirname, '../src'),
use: [{
loader: 'babel-loader'
}]
}, {
test: /\.(jpg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 10240
}
}
}, {
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader'
}
}]
},
plugins,
optimization: {
runtimeChunk: {
name: 'runtime'
},
usedExports: true,
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: 'vendors',
}
}
}
},
performance: false,
output: {
path: path.resolve(__dirname, '../dist')
}
}
在进行打包时应尽可能让包文件小如不引入不必要的模块代码,去除掉冗余代码,对代码进行 splitChunk 代码拆分,或者 tree-shaking 去除不必要的代码。
webpack 默认是通过 node.js 来运行的,是一个单进程的打包过程,可以借助 node 中的多进程提高打包速度。可以借助 thread-loader、happypack利用到 node 中的多进程和多个 CPU 提升打包速度。如果是进行多页应用的打包,还可以借助 parallel-webpack ,对多个页面同时进行打包。
对于 sourceMap,如果越详细,打包的速度就会越慢,因此可以合理利用 sourceMap 的配置提升打包速度。
命令生成打包的 stats.json 进行分析,对相关的可优化项进行优化。
开发环境时使用内存编译,即使用 webpack-dev-server
在开发环境,对于一些无用的插件不使用,如不使用代码压缩的插件等