在CQM平台开发时,把demo网站给同事体验,都纷纷反馈第一次打开页面的时候需要等待很久,页面一直在转菊花。作为一个为韩国头部厂商提供优质服务的网站,接到这种反馈,这不是啪啪打脸吗。
代码是在以前的老框架上写的(必须坚定把锅甩出去,手动捂脸)。喝杯咖啡镇定下,找找什么问题。赶紧打开chrome (disable cache):
哇,吓了一跳,这打包出来的JS辣么大:lib.js 2.3M(花了14s 才加载完)、app.js 1.2M(花了9s多加载完),难怪反馈页面响应慢。
webpack-bundle-analyzer是一个基于webpack的插件,能够用zoomable treemap可视化webpack输出文件的大小(
Visualize size of webpack output files with an interactive zoomable treemap)
不慌,喝口白开水,装上webpack-bundle-analyzer
看看里面分别是啥。
npm install webpack-bundle-analyzer
在webpack.app.config.js引入webpack-bundle-analyzer
constBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
output: {
//省略
},
entry: {
//省略
},
plugins: [
new BundleAnalyzerPlugin(),
],
};
很简单吧,这样我们就配好了webpack-bundle-analyzer
项目的package.json文件如下:
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
//开发环境生成 app.js及页面js
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=webpack.app.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
//生成环境打包 app.js及页面js
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=webpack.app.config.js",
//单独打包 lib.js
"build-lib": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=webpack.lib.config.js",
"build-online": "gulp pack --env production"
},
"devDependencies": {
//省略
},
"dependencies": {
//
}
}
运行下npm run watch,Webpack会自动打开浏览器,在127.0.0.1:8888上显示如下:
ps: npm run watch 对应的配置文件webpack.app.config.js,打包的app.js及页面js的各组成的大小(面积越大,表示比重越大)。可以看到,app.js里面大头分别是vue、vue-router、vue-i18n组件(好家伙,这些组件都是在app.js里面import进来的)。我们将他们踢出去:
a、在webpack.app.config.js里面添加externals参数,这样即使我们没将这几个组件打包到app.js中,我们依然能将其import进来并use:
module.exports = {
externals : {
'vue':'Vue',
'vue-router':'VueRouter',
'vue-i18n': 'VueI18n',
}};
b、接着在index.html中:
<scriptsrc="//cdn.bootcss.com/vue/2.3.3/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<scriptsrc="https://unpkg.com/vue-i18n@7.3.2/dist/vue-i18n.js"></script>
为什么要这么做呢?因为vue和vue-router在cdn上都提供了min版的js,已经是压缩精简版的,而vue-i18n.js的官方网站也建议使用cdn方式引入,没必要将都打包到app.js中。
对比优化前的app.js大小1.2M,以及下图单独引入vue.min.js、vue-i18n.js、vue-router.min.js的大小,分别为78K、38K、24K。效果十分明显
c、除了拆分依赖包,另一个重要的优化就是压缩代码,这里使用的是uglifyjs-webpack-plugin,同样在webpack.app.config.js的plugin里面添加
constUglifyJsPlugin= require('uglifyjs-webpack-plugin');
module.exports = {
plugins:[
new UglifyJsPlugin({
uglifyOptions: {
output: {
beautify: false,
comments: false,
},
compress: {
warnings: false,
drop_debugger: true,
drop_console: true,
pure_funcs: ['console.log', '(e = console).log' ]
},
sourceMap: false
}
})
]};
这样之后效果如下,app.js从1.2M缩减到200kb,达到了可观的效果
导致我们页面响应慢另一个大文件是 lib.js(这里介绍下,在我们工程里,对常用的第三方UI组件、绘图组件、编辑组件,项目里将其统一打包到lib.js里面,不用每次构建都重新打包lib.js,这样可以加快构建速度),对应配置文件webp.lib.config.js。同样用webpack-bundle-analyzer,如图所示:里面体积最大的分别是element-ui、vue2-editor、highchart、jquery等
以前的webpack.lib.config.js文件如下:
module.exports = {
output: {
path: path.join(__dirname, './public/js'),
filename: '[name].js',
library: '[name]',
},
entry: {
"lib": ['vue','jquery', 'element-ui', 'vue-highcharts', 'vue2-editor', 'lodash'],
},
};
对比上面的webpack.app.config.js,vue已经引进了,所以不必重复打包。jquery、element-ui可以通过引入cdn文件解决,vue2-editor目前项目中暂时没用到,所以去掉呗。再添加上代码压缩插件,修改后的webpack.lib.config.js文件如下:
module.exports = {
output: {
path: path.join(__dirname, './public/js'),
filename: '[name].js',
library: '[name]',
},
entry: {
"lib": ['vue-highcharts', 'lodash'],
},
newwebpack.optimize.UglifyJsPlugin({
minimize: true
}),
};
但是在app.js中还使用element-ui,所以在webpack.app.config.js中需要在external添加该项element-ui
和
jquery
:
module.exports = {
externals : {
'vue':'Vue',
'vue-router':'VueRouter',
'vue-i18n': 'VueI18n',
'element-ui':'ElementUI',
'jquery': 'jQuery.noConflict()'
}};
在index.html中添加jquery.all.js和element-ui,引入的js如下:
<script src="//cdn.bootcss.com/vue/2.3.3/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="//unpkg.com/element-ui@1.3.6"></script>
<script src="//unpkg.com/element-ui@1.3.6/lib/umd/locale/en.js"></script>
<script>
ELEMENT.locale(ELEMENT.lang.en)
</script>
<script src="https://unpkg.com/vue-i18n@7.3.2/dist/vue-i18n.js"></script>
<script src="/js/lib.js?12124142"></script>
<script src="http://iwaibao.qq.com/js/jquery.all.js?v=" language="javascript" type="text/javascript"></script>
<script src="{{ mix('js/app.js') }}"></script>
这里element-ui通过设置external然后引入cdn的js的时候有个坑,打包后老报错:
索性通过npm uninstall element-ui,将这个组件删除掉,直接通过cdn引入。执行npm run build-lib 生成,lib.js从2.3M减小到274kB,
最终页面的js文件如下:
对比优化前,网站访问流畅了不少(总共花了3s多加载完成)。虽然还不能做到如丝般柔滑,但罗马不是一天建成的(毕竟不能一次优化的太完美,不然后面怎么提升呢),比如打包速度提升(多线程打包)、页面代码分割与混淆等,后面咱们再慢慢优化
webpack基本已经成为前端项目的标配构建工具了,个人感觉大而全,里面有很多插件。比较赞同知乎网友对其的评价:
webpack充斥着大量名字类似 what-the-fuck-is-this-plugin 的插件,以及这个插件附带的一千种配置和一万种副作用,以至于每次出现打包的问题都会产生哲学三问:
这个插件干了什么?
我的配置有错误吗?
这个插件真的没有bug吗?
比如UglifyJsPlugin删除生产环境里console.log的选项drop_console死活不生效,最后只能通过vue-loader中的preLoader预加载选项,利用strip-loader将vue文件中的console去掉
let rules = [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
preLoaders: Mix.inProduction ? {js: 'strip-loader?strip[]=console.log,strip[]=console.warn'}:{},
loaders: //省略
}
]
最后的最后再加一条:这个插件版本对吗?(手动哭脸)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有