webpack构建优化:bundle体积从3M到400k之路

在CQM平台开发时,把demo网站给同事体验,都纷纷反馈第一次打开页面的时候需要等待很久,页面一直在转菊花。作为一个为韩国头部厂商提供优质服务的网站,接到这种反馈,这不是啪啪打脸吗。

代码是在以前的老框架上写的(必须坚定把锅甩出去,手动捂脸)。喝杯咖啡镇定下,找找什么问题。赶紧打开chrome (disable cache):

哇,吓了一跳,这打包出来的JS辣么大:lib.js 2.3M(花了14s 才加载完)、app.js 1.2M(花了9s多加载完),难怪反馈页面响应慢。

  • 1、祭出神器把Bundle分析利器拿出来:

  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

  • 2、优化app.js文件

项目的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,达到了可观的效果

  • 3、优化lib.js文件

       导致我们页面响应慢另一个大文件是 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-uijquery

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:  //省略
    }
]

最后的最后再加一条:这个插件版本对吗?(手动哭脸)

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏安恒网络空间安全讲武堂

​writeup | 强网杯—Share your mind

0x01 分析题目 拿到题目后,首先先分析一下题目,发现有注册和登录,尝试登录成功后,发现如下几个页面 Overview // 显示当前自己所有发帖 Write...

3546
来自专栏FreeBuf

看我如何窃取Messenger.com用户登录认证随机数并获得15000美元漏洞赏金

www.messenger.com是Facebook旗下即时通讯软件Messenger官网,该网站中添加了基于随机数认证( nonce based login ...

2175
来自专栏玩转JavaEE

SpringBoot+WebSocket实现在线聊天(一)

本文是vhr系列的第十四篇,项目地址:https://github.com/lenve/vhr 在线聊天功能是为了方便HR快速交流,由于HR人数有限,因此这...

3293
来自专栏玄魂工作室

[实战]如何在Kali Linux中进行WIFI钓鱼?

文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! ? 0x00 实验环境 操作系统:Kali 1.0 (VM) FackAP: ea...

4886
来自专栏逸鹏说道

大公司都有哪些开源项目之腾讯

1.WeUI 为微信Web服务量身设计 WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知...

4976
来自专栏技术小讲堂

PHP环境中安装pear、phpunit以及xdebug全攻略1.准备2.安装

首先,本文是基于wamp环境的基础上的,所以,如果您看到这里还没有搭建好wamp环境的话,介意您先把环境搭建好,因为这里都是一些实践性的内容。 1.准备 wam...

4008
来自专栏JackieZheng

AngularJS in Action读书笔记4(实战篇)——创建Statistic模块

  个人感觉《Angularjs in action》这本书写的很好,很流畅,循序渐进,深入浅出,关键是结合了一个托管于Github上的实例讲解的,有代码可查,...

1997
来自专栏美团技术团队

WebView性能、体验分析与优化

在App开发中,内嵌WebView始终占有着一席之地。它能以较低的成本实现Android、iOS和Web的复用,也可以冠冕堂皇的突破苹果对热更新的封锁。 然而便...

97512
来自专栏Crossin的编程教室

Python-Excel 模块哪家强?

0. 前言 从网页爬下来的大量数据需要清洗? 成堆的科学实验数据需要导入 Excel 进行分析? 有成堆的表格等待统计? 作为人生苦短的 Python 程序员,...

5125
来自专栏逸鹏说道

Web前端性能优化教程01:减少Http请求和使用内容分发网络

性能黄金法则 只有10%-20%的最终用户响应时间花在接收请求的HTML文档上,剩下的80%-90%时间花在HTML文档所引用的所有组件(图片,script,c...

4317

扫码关注云+社区

领取腾讯云代金券