62

webpack模板之大文件优化

 6 years ago
source link: http://mp.weixin.qq.com/s/YXFtr2DbLkLuf1mQN77yYQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

webpack模板之大文件优化

Original 亚里士朱德 web学习社 2017-12-05 22:56 Posted on

使用过vuejs的开发者一定对vue-cli不陌生,这个命令行工具提供了几个常用的搭建项目的模板,目前官方支持6个模板:

  • webpack

  • webpack-simple

  • browserify

  • browserify-simple

  • simple
    而使用得最多也是Github上start数最多的模板则是webpack这个模板,它包含的内容也非常丰富:语法校验、css预处理、测试框架等,相对于其它模板而言更适合搭建大型项目。
    更为良心的是连npm脚本都写好了,开发的时候直接输入npm run dev,开发完成则输入npm run build生成对应的可部署文件。
    但是当我们真正开始用于大型项目的时候,尤其在引入一些第三方模块之后就会发现一个问题~
    这是我的一个项目使用默认配置编译后生成的文件目录截图。

    Image

    其中有1个vendor.xxxx.js文件显示颜色为黄色,后面给出一个[big]的警告,文件大小达到981kB!
    更可怕的是 app.xxx.js 和 vendor.xxx.js 在首次加载的时候浏览器都会请求,js文件下载完成之后才开始渲染页面。直接后果就是首屏加载时间大大增加,用户浏览网页时需要长时间等待,体验相当糟糕。

    我们来看看这个vendor.xxx.js是怎么形成的。
    全局搜索一下”vendor”即可找到 build 目录下的 webpack.prod.conf.js 文件,看到下面几行:

    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
          path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),

    这里用到了webpack的一个插件CommonsChunkPlugin来提取entry对应文件(所有编写的业务代码)中的公共代码,其中 minChunks 的配置项对应的函数为提取代码块规则,规定将node_modules中的所有依赖模块都打包到一个叫vendor的文件中。

    最终目的是减小文件体积,途径有两个:

  • 减少依赖。

  • 分割文件。

    对于第一种方式通常会随着项目代码量增大而难度增大,而且除非引入了较多的不需要的垃圾模块,否则效果不会很明显。而引入不适用的模块一般在编译时校验规则无法通过就会报错,这种情况几乎不会出现。
    所以考虑第二种方式。我们将首屏需要的第三方模块提取出来优先加载,让页面快速渲染,其它模块延迟加载或懒加载。
    要做到这一点我们首先需要回归打包工具webpack,通过查看官方文档可以找到code splitting的描述和我们所需的场景较为匹配——它可以用来分割成更小的模块和控制资源加载的优先级,如果使用正确的话可以极大地提升加载速度。
    同时文档上提供了3种实现方式:

  • 通过entry配置项手动分割。

  • 通过CommonsChunkPlugin插件提取公用代码。

  • 动态引入模块。
    第一种方式:将首页依赖的模块手动配置成entry并不会奏效,因为CommonsChunkPlugin插件仍然会将部分模块抽取出来,配置形同虚设。
    第二种方式:正是这个插件导致引出的问题…
    第三种方式:使用vuejs的异步组件特性,再加上webpack的import函数实现。但是使用ts转成ES5时会出现报错:不支持模块懒加载。需要引用第三方库,比如require.js或者system.js。最后代码如下:

    // 需要先安装system.js模块:npm i -S systemjs
    const Index = () => System.import(/*webpackChunkName: 'Index'*/ '../components/home/Index.vue')
    ...

    换一种思路

    有没有简单粗暴的方法?有!
    在服务端开启gzip,可以有效地减小文件体积。具体操作需要根据不同服务器进行配置。
    本文使用了nginx作为Web服务器,并开启了最高压缩级别地gzip,上述vendor.xxx.js压缩后体积:

    608kB => 154kB
    体积减少了74.67%,效果相当可观。
    当然实际生产环境不会把压缩级别调到这么高,避免过多消耗CPU资源。

    这些年Web前端的发展越来越变得工程化和专业化,从最初的使用空的种子项目来快速搭建框架,到聚集各类框架模板的脚手架平台yeoman,再到框架使用专有的命令行工具(vue-cli, angular-cli等)。
    不少模板、种子项目虽然都做到了“开箱即用”,但是这个“可用性”更多的是相对于开发测试而言,对于生产部署往往需要开发者花费心思去改进、优化,纯粹的“拿来主义”不可取~

本文可被转发或分享,但必须保留完整图文信息和出处,作者保留追究一切法律责任的权利和手段~

Image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK