# 性能优化篇(五)
# 性能优化之webpack4
# 深度treeshaking
- webpack-deep-scope-plugin
- cssnano 基于postCss压缩css
- purifycss-webpack
//压缩css 使用cssnano
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const _modeflag = _mode === 'production' ? true : false;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module: {
rules: [
{
test: /\.css$/i,
use: [
'cache-loader',
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({//提取css
filename: _modeflag
? 'styles/[name].[contenthash:5].css'
: 'styles/[name].css',
chunkFilename: _modeflag
? 'styles/[name].[contenthash:5].css'
: 'styles/[name].css',
ignoreOrder: false,
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
canPrint: true,
}),
],
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
js部分在webpack5中已经有集成,css目前还是得自己处理
# webpack多线程
开启多核压缩 happypack 多线程编译webpack 不支持的情况下使用thread-loader(慎用)
{
test: /\.js$/,
include: resolve('src'),
//1.电脑配置强悍
//2.确实是因为loader 分析出来 影响了编译
use: [
{
loader: 'thread-loader',
options: {
workers: 3,
workerParallelJobs: 50,
workerNodeArgs: ['--max-old-space-size=1024'],
poolRespawn: false,
poolTimeout: 2000,
poolParallelJobs: 50,
name: 'my-pool',
},
},
],
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
JavaScript的多核压缩可以开启terser-webpack-plugin (多核压缩uglifyjs-webpack- plugin 官方维护 非官方维护webpack-parallel-uglify-plugin(这块儿对Css没啥用))
//js压缩
const TerserJSPlugin = require('terser-webpack-plugin'); module.exports = {
optimization: {
minimizer: [new TerserJSPlugin({
cache: true, // 是否缓存
paraller: true, // 是否并行打包 目前默认值true
sourceMap: true
})],
}
}
2
3
4
5
6
7
8
9
10
webpack5新增了这部分功能
# webpack打包速度分析和缓存
speed-measure-webpack-plugin
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap(merge(webpackConfig, _mergeConfig));
2
3
cache-loader
分析完事哪个慢缓存哪个
'babel-loader?cacheDirectory=true' exclude: /node_modules/, // 排除不处理的目录 include: path.resolve(__dirname, 'src') // 精确指定 要处理的目录
module: {
rules: [
{
test: /\.css$/i,
use: [
'cache-loader',
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader',
],
},
],
},
2
3
4
5
6
7
8
9
10
11
12
13
对整个工程开启缓存 hard-source-webpack-plugin
webpack5已新增缓存功能----借鉴了hard-source-webpack-plugin
# webpack打包进度展示
progress-bar-webpack-plugin
webpackbar
# webpack外部扩展
防止将某些 import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
例如,从 CDN 引入 jQuery,而不是把它打包:
index.html
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>
2
3
4
5
webpack.config.js
module.exports = {
//...
externals: {
jquery: 'jQuery'
}
};
2
3
4
5
6
这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行:
import $ from 'jquery';
$('.my-element').animate(/* ... */);
2
3
# webpack集群编译
分模块编译,然后集合。需要掌握免密登录,js shell,webpack区分模块
# 压缩图片
image-webpack-loader
# HtmlWebpackPlugins压缩推荐选项
new HtmlWebpackPlugin({
inlineSource: ".css$",
template: path.join(__dirname, `src/${pageName}/index.html`),
filename: `${pageName}.html`, chunks: ["vendors", pageName], inject: true,
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false,
}, });
2
3
4
5
6
7
8
9
10
11
12
13
# inline-manifest-webpack-plugin
inline-manifest-webpack-plugin 把runtime放到html里 html-inline-css-webpack- plugin 把一些核心的CSS放到⻚面内部 html-webpack-inline-source-plugin 内部资源 引入
# 代码求值
prepack-webpack-plugin
# 动态引入
@babel/plugin-syntax-dynamic-import
# 输出依赖关系
webpack-dashboard 增强了 webpack 的输出,包含依赖的大小、进度和其他细节。
webpack-bundle-analyzer 打包结果分析
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') .BundleAnalyzerPlugin; new BundleAnalyzerPlugin(),
1
2
3webpack --profile --json > stats.json 14-1 ht tp://alexkuz.github.io/webpack-chart/ 14-2 http://webpack.github.io/analyse/
# 工程优化与原理篇
将构建配置设计成一个库,比如:hjs-webpack、Neutrino、webpack-blocks
Neutrino:快速构建一个项目
抽成一个工具进行管理,比如:create-react-app, kyt, nwb
更友好的提示错误
friendly-errors-webpack-plugin 配合webpackdevserver使用
devServer: { historyApiFallback: true, contentBase: join(__dirname, '../dist'), proxy: { '/api': '', }, hot: true, quiet: true, }, new FriendlyErrorsWebpackPlugin({ compilationSuccessInfo: { messages: ['You application is running here http://localhost:3000'], notes: [ 'Some additionnal notes to be displayed unpon successful compilation', ], }, onErrors: function (severity, errors) { //安装node-notifier 只想提示错误的话 }, quiet: true, clearConsole: true, }),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22webpack-build-notifier
const WebpackBuildNotifierPlugin = require('webpack-build-notifier'); new WebpackBuildNotifierPlugin({ title: 'cli', logo: './favicon.png', suppressSuccess: true, }),
1
2
3
4
5
6- set-iterm2-badge && node-bash-title 标题和窗口内容修改
function() {
this.hooks.done.tap('done', (stats) => {
if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') == -1)
{
console.log('build error'); process.exit(1);
} })
}
2
3
4
5
6
7
8
9
10
11
splitchunks公用库的代码拆分 去除打包 分离⻚面公用包 html-webpack-externals- plugin
optimization: { runtimeChunk: { name: 'runtime', }, splitChunks: { chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, name: false, cacheGroups: { commons: { chunks: 'initial', minChunks: 2, maxInitialRequests: 5, minSize: 0, name: 'commons', }, }, }, },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22使用动态 polyfill 它会根据你的浏览器 UA 头,判断你是否支持某些特性,从而返回给你一个合适的polyfill。https://cdn.polyfill.io/v3/
集成到CI 监控文件的大小 https://github.com/siddharthkp/bundlesize
set-iterm2-badge && node-bash-title 标题和窗口内容修改
# webpack提示
@type/webpack npm
# SplitChunks插件配置选项
chunks 选项,决定要提取那些模块。
- 默认是 async :只提取异步加载的模块出来打包到一个文件中。
- 异步加载的模块:通过 import('xxx') 或 require(['xxx'],() ="{}) 加载的模块。
- initial :提取同步加载和异步加载模块,如果xxx在项目中异步加载了,也同步 加载了,那么xxx这个模块会被提取两次,分别打包到不同的文件中。
- 同步加载的模块:通过 import xxx 或 require('xxx') 加载的模块。
- all :不管异步加载还是同步加载的模块都提取出来,打包到一个文件中。
- 默认是 async :只提取异步加载的模块出来打包到一个文件中。
minSize 选项:规定被提取的模块在压缩前的大小最小值,单位为字节,默认为 30000,只有超过了30000字节才会被提取。
maxSize 选项:把提取出来的模块打包生成的文件大小不能超过maxSize值,如果超 过了,要对其进行分割并打包生成新的文件。单位为字节,默认为0,表示不限制大 小。
minChunks 选项:表示要被提取的模块最小被引用次数,引用次数超过或等于 minChunks值,才能被提取。
maxAsyncRequests 选项:最大的按需(异步)加载次数,默认为 6。
maxInitialRequests 选项:打包后的入口文件加载时,还能同时加载js文件的数量(包括入口文件),默认为4。
先说一下优先级 maxInitialRequests / maxAsyncRequests< maxSize < minSize 。
automaticNameDelimiter 选项:打包生成的js文件名的分割符,默认为 ~ 。
name 选项:打包生成js文件的名称。
cacheGroups 选项,核心重点,配置提取模块的方案。里面每一项代表一个提取模 块的方案。下面是 cacheGroups 每项中特有的选项,其余选项和外面一致,若cacheGroups 每项中有,就按配置的,没有就使用外面配置的。
test 选项:用来匹配要提取的模块的资源路径或名称。值是正则或函数。
- priority 选项:方案的优先级,值越大表示提取模块时优先采用此方案。默认值 为0。
- reuseExistingChunk 选项: true / false 。为 true 时,如果当前要提取 的模块,在已经在打包生成的js文件中存在,则将重用该模块,而不是把当前要提 取的模块打包生成新的js文件。
- enforce 选项: true / false 。为 true 时,忽 略 minSize , minChunks , maxAsyncRequests 和maxInitialRequests 外面选项