文章开头第一句加入:本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
可以用webpack-bundle-analyzer插件来分析各个模块的体积占比,再针对性优化。
1.图片的压缩与优化
url-loader转化为base64
对于较小的图片可以转化为base64格式,可以减少http请求。
module: {
rules: [
{
test: /.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
},
],
},
image-webpack-loader
通常一个项目我们会引入很多各种格式的图片,多张图片被打包以后,如果不做压缩的话,体积还是相当大的。我们可以使用image-webpack-loader进行图片压缩
2.js压缩
使用terser-webpack-plugin ,也可用 uglifyjs-webpack-plugin 进行js压缩;后者已不再维护
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true
})
]
}
}
3.css压缩
CssMinimizerPlugin进行css插件
optimization: {
minimizer: [
new CssMinimizerPlugin()
]
}
4.treeShake
用来清除代码中无用代码,tree-shaking 在mode为production中自动生效
Babel的preset默认会将任何模块类型都转译成CommonJS类型,这样会导致tree-shaking失效;需在配置中加上modules: false;
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', { modules: false }]
}
},
exclude: /(node_modules)/
}
]
}
5.polyfill按需引用
项目中会使用babel来将很多es6中的API进行转换成es5,但是还是有很多新特性没法进行完全转换,比如promise、async await、map、set等语法,那么我们就需要通过额外的polyfill(垫片)来实现语法编译上的支持。但我们并不是所有的es6语法都用到;故需按需引入
{
"presets": [
"@babel/preset-env",
{
"useBuildIns": "useage"
}
]
}
6.代码分割
拆分代码(code Spliting)减少main.js包的体积
optimization: {
splitChunks: {
chunks: 'all',
minSize: 10000,
}
}
7.Scope Hoisting (作用域提升)
让打包出来的文件体积更小,运行更快。
只有被引用了一次的模块才会被合并,其余的会被抽离作为公共模块。
通过设置optimization.concatenate = true则开启。
8.GZip压缩
开启Gzip后,大大提高用户的页面加载速度,需要后端的配合,使用 compression-webpack-plugin
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
threshold: 10240,
minRatio: 0.8
})
]
9.擦除没有用到的css
purgecss-webpack-plugin识别用到的css class
const PATHS = {
src: path.join(__dirname, 'src'),
};
plugins: [
new PurgecssPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
}),
]
10.懒加载
使用懒加载或者按需加载,在一些代码块中完成某些操作后,引用另一些新的代码块。这样可以加快应用的初始加载速度,减轻了它的整体体积,因为某些代码块可能永远不会被加载。
import 加载js文件,会返回一个promise
懒加载js
function creatEle() {
return import (/*webpackChunkName: 'lodash'*/'lodash').then(({default: _})=>{
//do something
})
}
路由懒加载
const HelloWorld = ()=>import("@/components/HelloWorld")
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component:HelloWorld
}
]
})