美文网首页Java
Webpack 2 中一些常见的优化措施

Webpack 2 中一些常见的优化措施

作者: cbw100 | 来源:发表于2020-02-28 10:59 被阅读0次

Webpack 是一款强大的前端构建工具, 社区对其介绍的相关文章已经很多了, 本文不再赘述. 基于 Webpack 2, 本文是对我在搭建团队前端脚手架的过程中, 搜罗的 Webpack 2 常见的优化措施的一个总结.

1. 分离第三方依赖

开发环境下, 通常会采取 HMR 模式来提高开发效率. 但一般情况下, 我们只会更改自身的业务文件, 不会去更改第三方的依赖, 但 webpack 在 rebuild 的时候, 依旧会 build 所有的依赖. 因而, 为减少 rebuild 的时间, 我们可以分离第三方依赖, 在项目启动之前, 将其单独打包和引入.

这要借助 DllPlugin 插件.

我们定义一份生成 dll 的配置文件:

## webpacl.dll.config.js
module.exports = {
    entry: {
        vendor: [
            'vue', 'vuex', 'vue-router', 'vuex-router-sync', 'babel-polyfill', '...'
        ]
    },
    output: {
        path: path.join(__dirname, './public/', 'dist'),
        filename: '[name].dll.js',
        library: '[name]_library'
    },
    plugins: [
        new webpack.DllPlugin({
          path: path.join(__dirname, './public/', 'dist', '[name]-manifest.json'),
          name: '[name]_library'
      })
    ]
}

生成 dll 文件之后, 可以根据环境变量在页面的静态文件中引入:

<script src="//cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
<% if (htmlWebpackPlugin.options.env === 'development') { %>
<script src="/vendor.dll.js"></script>
<% } %>

这样, 在每次 rebuild 的时候, webpack 都不会去重新 build vendor, 能极大减少 rebuild 的时间, 提升开发效率.

注意:仅在开发环境下使用

2. 多进程构建

Webpack的构建过程是单进程的, 利用 HappyPack 可让 loader 对文件进行多进程处理, 其原理图如下:

image.png

在业务文件依赖越多和复杂的情况下, HappyPack 对 Webpack 构建效率的提升会越明显. 下图是我在项目使用 HappyPack 前后的一张构建时间对比图:

image.png

HappyPack 会充分利用系统的资源来提升 Webpack 的构建效率, 所以系统本身的硬件配置会对 HappyPack 的使用有一定的影响.

HappyPack 不限于处理 js 文件, 也可以同时处理 css/vue 等其它类型文件. HappyPack 支持多个实例, 可以创建多个实例来分别处理不同的类型文件:

let HappyPack = require('happypack');
let os = require('os');
let happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });

module.exports = {

    ...
    
    plugins: [
        new HappyPack({
            id: 'vue',
          threadPool: happyThreadPool,
          cache: true,
          verbose: true,
          loaders: ['vue-loader'],
        }),
        
        new HappyPack({
            id: 'js',
          threadPool: happyThreadPool,
          cache: true,
          verbose: true,
          loaders: ['babel-loader'],
        })
        
        # others
    ]
    
    ...

}

此外,HappyPack同时还利用缓存来使得rebuild更快.
注意:开发环境和生产环境下均可使用. 关于其原理分析, 请看 HappyPack 原理解析

3. 提取公共的依赖模块

无论是单页还是多页应用, 在生产环境下, 通常都会利用 CommonsChunkPlugin 插件来提供公共的依赖模块:

new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
    minChunks: ({resource}) => {
        resource && 
        resource.indexOf('node_modules') &&
        resource.match(/\.js$/)
    }
}),

上述的配置会提取 node_modules下的所有模块, 打包出来的结果可能是这样的:

image.png
注意: 打包结果分析图由 webpack-bundle-analyzer 提供
这样提取了公共模块之后, 的确会减少业务包的大小, 但是, 这种方式会导致两个问题:
  • 业务越复杂, 三方依赖会越多, vendor 包会越大
  • 没有隔离业务路由组件, 所有的路由都有可能会去加载 vendor, 但并不是所有的路由组件都依赖 node_modules下的所有模块
    所以, 上述提取公共依赖的方式不可取. 我们应该去分析业务依赖和路由, 尽可能将所有路由组件的公共依赖提取出来:
entry: {
    app: path.resolve(__dirname, '../src/page/index.js'),
    vendor: [
        'vue', 'vuex', 'vue-router', 'vuex-router-sync', 'babel-polyfill',
        'axios', '....'
    ]
},

new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
    filename: "vendor.js"
}),

前后两种方式打包出来的 vendor 大小对比:


既要去提取公共依赖, 也要避免 vendor 包过于太大.

4. 文件分离

文件分离主要是将图片和 CSS 从 js 中分离. 图片和 CSS 都是 Webpack 需要构建的资源, 通过某种配置, 图片可以以 base64 的方式混淆在 js 文件中, 这会增加最终的 bundle 文件的大小. 在 生产环境下, 应该将图片和 CSS 从 js 中分离:

  • 在生产环境下, 通过自定义插件, 将图片的本地引用替换为 CDN 的链接
  • 在生产环境下, 通过 ExtractTextPlugin 来 提取 CSS.

5. 资源混淆和压缩

Webpack提供的 UglifyJS 插件由于采用单线程压缩, 速度比较慢,可以使用 Parallel 插件进行优化:

let ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
let os = require('os');

new ParallelUglifyPlugin({
    workerCount: os.cpus().length,
    cacheDir: '.cache/',
    uglifyJS: {
        compress: {
            warnings: false,
            drop_debugger: true,
            drop_console: true
        },
        comments: false,
        sourceMap: true,
        mangle: true
    }
})

6. Gzip 压缩

生产环境下, 如果想进一步减小 bundle 文件的大小, 可以使用 Gzip 压缩.

let CompressionPlugin = require("compression-webpack-plugin");

module.exports = {
    plugins: [
        new CompressionPlugin({
            asset: "[path].gz[query]",
            algorithm: "gzip",
            test: /\.(js|html)$/,
            threshold: 10240,
            minRatio: 0.8
        })
    ]
}

Gzip压缩能有效减少bundle的文件大小:

image.png

注意: 部署上线时,服务端也要开启gzip压缩

7. 按需加载

在单页应用中, 一个应用可能会对应很多路由, 每个路由都会对应一个组件; 如果将这些组件全部全部放进一个 bundle, 会导致最终的 bundle 文件比较大(看上图的 app bundle 文件). 因而, 我们需要利用 Webpack 的 Code Splitting 功能, 将代码进行分割, 实现路由的按需加载.

在 Vue 中, 利用 vue-router的懒加载功能, 是比较容易实现按需加载的:

image.png

当访问首页时, 会去加载 Index 组件, 此时并不会加载 Info 组件; 只有当路由切换为 /info 时, Info 组件才会被加载.

暂时有的就是这些。

8. 相关文章

相关文章

  • Webpack 2 中一些常见的优化措施

    Webpack 是一款强大的前端构建工具, 社区对其介绍的相关文章已经很多了, 本文不再赘述. 基于 Webpac...

  • Webpack整理

    【翻译】Webpack——令人困惑的地方 webpack2 终极优化 Webpack 2 入门教程 webpack...

  • 常见的webpack优化

    1,上线的时候取消log

  • 12、大表如何优化?

    大表如何优化? 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 1. 限定...

  • webpack优化

    webpack各种优化 上一章节我们已经掌握了webpack常见的所有配置 这一节我们来看看如何实现webpack...

  • 大表优化的常见手段

    当 MySQL 单表记录数过大时,数据库的 CRUD 性能会明显下降,一些常见的优化措施如下: 限定范围: 务必禁...

  • mysql 问题整理

    SQL 优化 范式 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些...

  • SQL优化

    SQL优化 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有...

  • webpack5

    Webpack 5 中的效率优化点 Persistent CachingCache 基本配置在 Webpack 4...

  • 性能优化+打包构建

    性能优化 webpack-bundle-analyzerwebpack构建优化webpack分包webpack g...

网友评论

    本文标题:Webpack 2 中一些常见的优化措施

    本文链接:https://www.haomeiwen.com/subject/vtggqxtx.html