Loading...
墨滴

Equicy

2021/07/31  阅读:96  主题:全栈蓝

【实战篇】基于vue-cli4创建的项目进行打包优化

【实战篇】基于vue-cli4创建的项目进行打包优化

前言

阅读完该篇文章大概需要2min。

  • vue-cli的出现,让我们省掉了配置webpack的时间。也就是说,一个不懂webpack的人,也能直接上手开发。比如file-loader, url-loader会提前为我们配置好。

  • 性能方面,vue-cli也默认尽可能多的帮我们做了优化,比如cache-loader会在项目中预先做了配置。我们可以在控制台输入vue inspect > webpack.config.js,即可在webpack.config.js查看cli预先定义好的基础配置。我们今天就在vue-cli搭建好的项目基础上聊一聊可优化的点。

项目源码

准备工作

  • 通过vue-cli创建一个项目,我用的版本是vue-cli@4.5.13
  • 安装几个常用的包: lodash, moment, element-ui, vue-router,vuex

量化指标

build的时间

speed-measure-webpack-plugin插件可以在build的时候看到webpack的loader和plugin所用的时间,配置非常简单。如下:

// vue.config.js
module.exports = {
  chainWebpackconfig => { 
    config.plugin('speed')
    .use(SpeedMeasureWebpackPlugin)
  }
}

看一下效果

build后包的大小以及数量

webpack-bundle-analyzer插件可以帮我们可视化的展示build时的每个包的大小以及依赖。

vue-cli也帮我们做了默认的配置,我只需要在build的后面加一个参数--report即可

// package.json
{
  "name""dll-vue",
  "version""0.1.0",
  "private"true,
  "scripts": {
    "serve""vue-cli-service serve",
    "build""vue-cli-service build",
    "report""vue-cli-service build --report",
  }
}

npm run report 之后,dist目录下就多了一个report.html文件,我们用浏览器打开这个文件看一下 可以清楚的看到基本上都是node_module中的包,只有右上角那个小蓝块是我们的vue代码

开始优化

减少第三包的大小(Moment为例)

moment这个库还是比较常用,但是这个库包含了一个很大的模块就是语言包,其实大部分的场景根本用不到需要适配到多国语言,所以我们只是载入中文包就够了。

webpack.ContextReplacementPlugin这个插件可以帮我们做这件事,配置很简单。

// vue.config.js
module.exports = {
  configureWebpack:{
    plugins: [
      new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/)
    ]
  }
}

运行npm run report 我们来对比一下前后的大小, 小了有50kb。

配合CDN加速(jQuery为例)

一般来说像jQuery这些第三方的包,我们采用CDN的方式来引入,像这样

<-- public/index.html -->
<script src="https://code.jquery.com/jquery-3.6.0.min.> js"></script>

但是在开发的过程中,我们也想要代码提示,则需要在文件内引入,像这样

// App.vue
import $ from 'jquery'

$('.today').text = 'today'

这就造成一个问题,build的时候就会将jquery再打包一次 我们可以配置externals来达到build时忽略掉指定的依赖

// vue.config.js
module.exports = {
  configureWebpack:{
    externals: {
      jquery'jQuery',
    }
  }
}

我们来对比一下前后的大小, 发现jquery消失了。

阶段性效果预览(时间和大小)

拆包: DllPlugin 和 DllReferencePlugin(重点)

对于变化几率很小的一些第三方包,其实没必要build的时候都要打包一次, 可以把这些第三方包单独抽离出来,提前打包好。

webpack本身是要体现出模块间的依赖关系,当我们将一些包抽离出来后,维护之前的依赖关系就需要manifest.json这个文件。让我们从接下来的实战中来学习它。

1. 新建一个配置文件webpack.dll.config.js(命名没有要求)

把第三方包单独抽离,防止一个包太多,我分成了两个,一个是vue相关的,一个是其他的

// webpack.dll.config.js
module.exports = {
  mode'production',
  entry: {
    vue_vendor: ['vue/dist/vue.runtime.esm.js''vuex',  'vue-router''element-ui'],
    other_vendor: ['lodash''moment']
  },
  output: {
    filename'[name].dll.js',
    path: path.resolve(__dirname, './public/dll'),
    library'[name]_[hash]'
  },
  plugins: [
    new webpack.DllPlugin({
      name'[name]_[hash]',
      path: path.resolve(__dirname, '[name].manifest.json')
    })
  ]
}
2. 读取配置,并执行

为了方便,我们将读取该配置文件的命令写到package.json文件中,像这样。(需要安装webpack-cli)

// package.json
{
  .....
  "scripts": {
    .....
    "dll""webpack --config ./webpack.dll.config.js"
  }
  .....
}

执行npm run dll后可以看到生成两个manifest文件,像这样

3. 修改vue.config.js,引入依赖文件,并自动将dll下的文件插入到index.html中
module.exports = {
  chainWebpackconfig => {
    // 多个manifest.json文件就需要写多次
    config.plugin('vendorDll1')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./other_vendor.manifest.json')
      }
    ])

    config.plugin('vendorDll2')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./vue_vendor.manifest.json')
      }
    ])

    // 将dll下的文件自动插入到index.html中
    config.plugin('asset')
    .use(AddAssetHtmlWebpackPlugin, [
      [
        {
          filepath: path.resolve(__dirname, 'public/dll/vue_vendor.dll.js'),
          outputPath'dll',
          publicPath'/dll'
        },
        {
          filepath: path.resolve(__dirname, 'public/dll/other_vendor.dll.js'),
          outputPath'dll',
          publicPath'/dll'
        }
      ]
    ])
  }
}
我们打包一下看一下效果

总结

  • 这次我们主要针对三种情况做了优化,当然如果项目很大,可通过happypack plugin或者thread-loader进行多线程打包。如果感兴趣可在代码仓库看到示例

  • 创作不易,欢迎点赞评论

Equicy

2021/07/31  阅读:96  主题:全栈蓝

作者介绍

Equicy

公众号: 前端小卡