2018/06/11 - 前端项目性能优化之打包工具篇
falm opened this issue · 6 comments
现代前端开发,已经进入工程化阶段,但是基于浏览器的前端项目的在工程化后,往往会遇到一些性能问题,例如中大型前端项目,依赖库和项目本身的资源过大,加载慢,首屏渲染时间长等性能问题,严重影响用户体验,这个时候工程化的项目就需要适当的进行优化,本文分享一下,我们前端项目已经或将要在打包工具这一层级的优化方法。
webpack为目前较为流行的前端项目打包工具,它提供了丰富的扩展功能和插件来让我们对项目有更好的控制,我司前端项目也是使用webpack来作为打包工具,接下来的介绍也是围绕在它来进行。
打包性能分析
要做性能优化,首先要知道优化哪些部分,也就是哪些比较慢,通常情况下,最直观的方向就是,项目整体打包文件的大小的问题,如果资源过大,那么网站性能肯定是上不去的。我们这里使用Webpack Bundle Analyzer 这个工具来分析一下,项目打包后各个模块所占用的资源情况。
首先安装:yarn add webpack-bundle-analyzer —dev
然后在webpack 配置文件中,将webpack-bundle-analyzer 加入到插件上:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
......
plugins: [new BundleAnalyzerPlugin()]
之后我们在production模式下构建项目,NODE_ENV=production yarn build
BundleAnalyzerPlugin就会对资源进行分析,然后会开起一个网页浏览分析结果:
13.f4b485a6e42f8d1022b1.js 14.4 kB 13 [emitted]
0.f4b485a6e42f8d1022b1.js 56.3 kB 0 [emitted]
2.f4b485a6e42f8d1022b1.js 42.9 kB 2 [emitted]
3.f4b485a6e42f8d1022b1.js 39.2 kB 3 [emitted]
4.f4b485a6e42f8d1022b1.js 47.9 kB 4 [emitted]
5.f4b485a6e42f8d1022b1.js 8.96 kB 5 [emitted]
6.f4b485a6e42f8d1022b1.js 4.1 kB 6 [emitted]
7.f4b485a6e42f8d1022b1.js 97 kB 7 [emitted]
8.f4b485a6e42f8d1022b1.js 40.4 kB 8 [emitted]
9.f4b485a6e42f8d1022b1.js 14.8 kB 9 [emitted]
10.f4b485a6e42f8d1022b1.js 15.7 kB 10 [emitted]
11.f4b485a6e42f8d1022b1.js 12.3 kB 11 [emitted]
12.f4b485a6e42f8d1022b1.js 23 kB 12 [emitted]
1.f4b485a6e42f8d1022b1.js 68.4 kB 1 [emitted]
14.f4b485a6e42f8d1022b1.js 12.4 kB 14 [emitted]
15.f4b485a6e42f8d1022b1.js 68.7 kB 15 [emitted]
16.f4b485a6e42f8d1022b1.js 12.4 kB 16 [emitted]
17.f4b485a6e42f8d1022b1.js 12.3 kB 17 [emitted]
18.f4b485a6e42f8d1022b1.js 13.7 kB 18 [emitted]
19.f4b485a6e42f8d1022b1.js 8.46 kB 19 [emitted]
20.f4b485a6e42f8d1022b1.js 5.3 kB 20 [emitted]
21.f4b485a6e42f8d1022b1.js 6.08 kB 21 [emitted]
22.f4b485a6e42f8d1022b1.js 2.13 kB 22 [emitted]
23.f4b485a6e42f8d1022b1.js 3.03 kB 23 [emitted]
24.f4b485a6e42f8d1022b1.js 500 bytes 24 [emitted]
main.f4b485a6e42f8d1022b1.js 533 kB 25 [emitted] [big] main
第三方库CDN
通过分析结果我们可以看到,第三方库如Lodash 占据了资源文件不小空间,这个我们就可以使用webpack本身提供的external功能,通过CDN加速的lodash。
配置如下:
{
externals: {
lodash: '_',
},
}
然后我们在项目的入口html中收到加入CDN link:
<!doctype html>
<html class="no-js" lang="">
<head>
...
</head>
<body>
<div id="container"></div>
<script src="https://cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
<script src="<%= bundle %>"></script>
<script src="<%= vender %>"></script>
</body>
</html>
公共模块提取
优化了上一部分的CDN,其实项目当中有些没有CDN的第三方资源我们也可用通过提取公共模块的方式,把它们单独的打包成一个文件,这样就可以让main.js的体积进一步减小,浏览器也能够并行加载资源。
这里要使用的就是Webpack提供的CommonsChunkPlugin 插件
配置:
{
entry: {
main: './main.js',
vendor: ['react', 'react-dom', 'react-redux']
},
plugins: [new webpack.optimize.CommonsChunkPlugin({
name: 'vendor' // 公共模块的入口
})]
}
配置之后,webpack就会将 react一系列的资源,单独打包成一个vendor.js文件来加快网页加载速度。
CSS拆分
最后一个我们要说的性能优化是CSS,在我们的前端项目中使用了 css modules和react技术,项目中的cs s就会打包在js文件当中,当网页加载好js代码后,再作为内联样式渲染,这里就带来了一个弊端,样式的渲染不能和js代码的加载同时进行,需要等到js加载完后才可以,解决办法就是将项目中的所有css文件,提取出来作为一个外联的css文件,这样网页在加载时就会首先加载样式表文件,然后进行解析渲染,不需要等js加载完成。
那么我们要做的就是使用extract-text-webpack-plugin 插件来做到样式表提取。
安装:yarn add extract-text-webpack-plugin —dev
配置:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
{
module: {
rules: [
{ //提取css文件
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
// use: "css-loader"
use: [
{
loader: 'css-loader',
options: {
// sourceMap: isDebug,
sourceMap: false,
importLoaders: true,
// CSS Modules https://github.com/css-modules/css-modules
modules: true,
minimize: !isDebug,
},
},
],
})
},
{ // 提取scss文件
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
// use: ['css-loader', 'sass-loader']
use: [
{
loader: 'css-loader',
options: {
sourceMap: false,
importLoaders: true,
// CSS Modules https://github.com/css-modules/css-modules
modules: true,
localIdentName: isDebug ? '[name]_[local]_[hash:base64:3]' : '[hash:base64:4]',
// CSS Nano http://cssnano.co/options/
minimize: !isDebug,
},
},
{
loader: 'sass-loader'
}
],
})
},
]
}
plugins: [ // 加载插件,并且指定输出css的文件路径名。
config.plugins.push(new ExtractTextPlugin('[name].css?[hash]'));
]
}
最后的效果就是我们从原来输出一个大的主文件,变成了三个文件,main.js的大小533kb减小到了264kb,少了一倍。
main.40e4cd0b400a3812526a.js 264 kB 25 [emitted] [big] main
vendor.40e4cd0b400a3812526a.js 170 kB 26 [emitted] vendor
main.css?40e4cd0b400a3812526a 28.1 kB 25 [emitted] main
结尾
以上介绍的三种打包工具层面的优化,我们就可以看到 路由和webpack本身已经使用了code split技术将我们的页面拆分成了数字编号的小文件,这就是按需加载。前端性能优化中资源大小的优化属于第一步骤,后续更深入的优化,包括运行时优化,渲染优化,数据加载优化等等,之后我们有机会再来介绍。
广而告之
本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~
点赞👍。一点小小的建议:有一些错别字,特别是CSS拆分那里,导致有些句子不通顺,如果创建Issue前检查一遍,那就更棒了。
uglify,rollup 一个都没提到。。。,性能优化 体积只是其中一小部分,,还有加载,缓存。。
@simbawus 把文章写的深入一些才值得star 和 watch。
vue,router,vuex放到cdn会更好