前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >webpack构建优化:bundle体积从3M到400k之路

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

原创
作者头像
RubyLiao廖彩明
修改2018-12-06 10:35:45
3.9K0
修改2018-12-06 10:35:45
举报
文章被收录于专栏:全栈开发全栈开发

在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看看里面分别是啥。

代码语言:javascript
复制
npm install webpack-bundle-analyzer

     在webpack.app.config.js引入webpack-bundle-analyzer

代码语言:javascript
复制
constBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
   output: {
       //省略
   },
   entry: { 
      //省略
   },
   plugins: [
      new BundleAnalyzerPlugin(),
   ],
};

很简单吧,这样我们就配好了webpack-bundle-analyzer

  • 2、优化app.js文件

项目的package.json文件如下:

代码语言:javascript
复制
{
  "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:

代码语言:javascript
复制
module.exports = {
    externals : {
       'vue':'Vue',
       'vue-router':'VueRouter',
       'vue-i18n': 'VueI18n',
}};

b、接着在index.html中:

代码语言:javascript
复制
<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里面添加

代码语言:javascript
复制
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文件如下:

代码语言:javascript
复制
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文件如下:

代码语言:javascript
复制
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

代码语言:javascript
复制
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如下:

代码语言:javascript
复制
<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去掉

代码语言:javascript
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档