前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue-Cli优化编译速度

Vue-Cli优化编译速度

作者头像
码客说
发布2022-09-27 15:51:57
3.4K0
发布2022-09-27 15:51:57
举报
文章被收录于专栏:码客

前言

Vue-Cli中内置了Webpack,但是配置文件和Webpack也不尽相同。

我们可以通过命令查看对应的Webpack配置。

对于优化主要是两个方面

  • 构建速度
  • 打包体积

所以不管是分析问题还是解决问题有围绕这连个方面进行处理。

Vue-Cli自带

  • cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中。 如果你遇到了编译方面的问题,记得先清缓存目录之后再试试看。
  • thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。

查看Vue-Cli中的Webpack配置

介绍

Vue-Cli脚手架会有webpack的很多默认行为,因此我们得知道基于Vue-Cli的项目,当前的webpack都配置了啥,然后才能做针对性的分析与优化。

vue-cli-service 暴露了 inspect 命令用于审查解析好的 webpack 配置。那个全局的 vue 可执行程序同样提供了 inspect 命令,这个命令只是简单的把 vue-cli-service inspect 代理到了你的项目中。

使用方式:

代码语言:javascript
复制
#根据mode,分别生成开发环境、生产环境的配置
vue inspect --mode production > webpack.config.production.js
vue inspect --mode development > webpack.config.development.js

输入命令后,在根目录会生产一个webpack.config.production.js文件

如果vue command not found的错可以全局安装注册一下vue命令

代码语言:javascript
复制
npm install -g vue-cli

分析

查看构建时间

说明:https://www.npmjs.com/package/speed-measure-webpack-plugin

安装

代码语言:javascript
复制
npm install --save-dev speed-measure-webpack-plugin

使用

代码语言:javascript
复制
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
module.exports = {
  chainWebpack: config => {
    config
      .plugin('speed-measure-webpack-plugin')
      .use(SpeedMeasurePlugin)
      .end();
  }
}

或者

代码语言:javascript
复制
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
module.exports = {
  configureWebpack: (config) => {
    config.plugins.push(
      new SpeedMeasurePlugin(),
    );
  },
};

查看构建库大小

VUE CLI内置工具

代码语言:javascript
复制
vue-cli-service build --report

成功后就会在项目目录下找到/dist/report.html

结果如下图所示:

image-20220825103406352
image-20220825103406352

如果报错

node_modules.bin\vue-cli-service.ps1,因为在此系统上禁止运行脚本。

执行之后就能运行上面的命令了

代码语言:javascript
复制
set-ExecutionPolicy RemoteSigned -Scope CurrentUser
#查看执行权限
Get-ExecutionPolicy

webpack-bundle-analyzer

Vue CLi就不用这个工具了,但是也可以配置,配置后运行项目打开项目页面的同时也会打开分析页面。

安装

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

配置

Webpack配置

代码语言:javascript
复制
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

Vue Cli配置

代码语言:javascript
复制
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
  configureWebpack: {
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }
}

优化

构建速度优化

happypack

安装

代码语言:javascript
复制
npm install --save-dev happypack

配置

代码语言:javascript
复制
/*
happypack
*/
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });

module.exports = {
  configureWebpack: config => {
    return {
      /* happypack */
      module: {
        rules: [
          {
            test: /\.js$/,
            loader: 'happypack/loader?id=happyBabel',
            exclude: /node_modules/
          },
        ]
      },
      externals: {
        vue: "Vue",
        "vue-router": "VueRouter",
        vuex: "Vuex",
        echarts: "echarts",
        axios: "axios",
      },
      plugins: [
        new HappyPack({
          id: 'happyBabel',
          loaders: [{
            loader: 'babel-loader?cacheDirectory=true',
          }],
          //共享进程池
          threadPool: happyThreadPool,
          //允许 HappyPack 输出日志
          verbose: true,
        })
      ],
    }

  },
}

实测没啥效果

vue-cli-plugin-dll

代码语言:javascript
复制
npm install --save-dev vue-cli-plugin-dll

接下来就是dll的相关配置,将我们项目中的依赖使用dll插件进行动态链接,这样依赖就不会进行编译,从而极大地提高编译速度,因为这些插件没有编译,在vue.config.js中进行配置,也很简单

代码语言:javascript
复制
const path = require("path");
module.exports = {
  pluginOptions: {
    dll: {
      //这里放的是你的依赖插件,就是你项目安装的其他的插件,将这些插件的名字依次加在后面,我建议将所有项目依赖插件全部放在后面
      //注意这里不能放webpack,gulp等需要node环境的插件,我尝试将babel等放到这里报错提示没有V8环境
      entry: ["vue", "vue-router", "view-design"],
      //dll 编译后的链接库的地址
      cacheFilePath: path.resolve(__dirname, "./public"),
      // 是否开启 DllReferencePlugin,
      open: true,
      // 在执行 `dev` , `build` 等其他指令时,程序会自动将 `dll` 指令生成的 `*.dll.js` 等文件自动注入到 index.html 中。
      inject: true
    }
  },
}

多入口

代码语言:javascript
复制
const path = require('path')
module.exports = {
  pluginOptions: {
    dll: {
      // 入口配置
      entry: {
        vue: ["vue", "vue-router", "vuex"],
        ui: ["view-design"],
      },
      // 输出目录
      output: {
        path: path.join(__dirname, 'public/dll'),
        filename: '[name].dll.js',
        // vendor.dll.js中暴露出的全局变量名
        // 保持与 webpack.DllPlugin 中名称一致
        library: '[name]_[hash]'
      },
      // 是否开启 DllReferencePlugin,
      open: true,

      // 在执行 `dev` , `build` 等其他指令时,程序会自动将 `dll` 指令生成的 `*.dll.js` 等文件自动注入到 index.html 中。
      inject: true,
    }
  }
}

配置好之后然后运行,进行你上面配置插件动态链接库的编译

代码语言:javascript
复制
npx vue-cli-service dll

dll编译完成后会在上面配置的目录下生成dll文件夹,就可以开始跑项目了,因为这些插件都不需要编译,跑起来很流畅,修改后的热更新速度更是显著提升。我以前修改一行代码热更新编译在30秒以上,使用这个以后基本十秒以内搞定。

代码语言:javascript
复制
npm run serve

多线程优化

Vue-Cli

Vue-Cli已经内置,开启

代码语言:javascript
复制
module.exports = {
  parallel: true,
}

parallel

  • Type: boolean
  • Default: require('os').cpus().length > 1 是否为 Babel 或 TypeScript 使用 thread-loader。 该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
Webpack
代码语言:javascript
复制
npm install --save-dev thread-loader

配置

代码语言:javascript
复制
const path = require("path");
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve('src'),
        use: [
          "thread-loader",
          // 耗时的 loader (例如 babel-loader)
        ],
      },
    ],
  },
};

缓存构建

Webpack 中几种缓存方式:

  • cache-loader
  • hard-source-webpack-plugin

以上这些缓存方式都有首次启动时的开销,即它们会让 “冷启动” 时间会更长,但是二次启动能够节省很多时间.

Vue-Cli 已经内置了 cache-loader 进行以下两个的缓存了

  • babel-loader 的 cacheDirectory 标志
  • vue-loader 的 cacheDirectory 标志

所以

Vue Cli没有必要添加HardSourceWebpackPlugin

HardSourceWebpackPlugin

详细说明

https://www.npmjs.com/package/hard-source-webpack-plugin

在启动项目时会针对项目生成缓存,若是项目无package或其他变化,下次就不用花费时间重新构建,直接复用缓存。

安装

代码语言:javascript
复制
npm install --save-dev hard-source-webpack-plugin

配置vue.config.js

为模块提供中间缓存,缓存路径是:node_modules/.cache/hard-source

代码语言:javascript
复制
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
module.exports = {
  configureWebpack: config => {
    config.plugin.push(
      // 为模块提供中间缓存,缓存路径是:node_modules/.cache/hard-source
      new HardSourceWebpackPlugin({
        root: process.cwd(),
        directories: [],
        environmentHash: {
          root: process.cwd(),
          directories: [],
          files: ['package.json', 'yarn.lock']
        }
      })
      // 配置了files的主要原因是解决配置更新,cache不生效了的问题,配置后有包的变化,plugin会重新构建一部分cache
    )
  }
}

或者

代码语言:javascript
复制
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
module.exports = {
  configureWebpack: {
    plugins:[
      new HardSourceWebpackPlugin({
        root: process.cwd(),
        directories: [],
        environmentHash: {
          root: process.cwd(),
          directories: [],
          files: ['package.json', 'yarn.lock']
        }
      })
    ]
  }
}

更多配置

代码语言:javascript
复制
// 缓存 加速二次构建速度
new HardSourceWebpackPlugin({
  cacheDirectory: "../node_modules/.cache/hard-source/[confighash]",
  recordsPath:
  "../node_modules/.cache/hard-source/[confighash]/records.json",
  configHash: function(webpackConfig) {
    return require("node-object-hash")({ sort: false }).hash(
      webpackConfig
    );
  },
  // Either false, a string, an object, or a project hashing function.
  environmentHash: {
    root: process.cwd(),
    directories: [],
    files: ["../package-lock.json", "../yarn.lock"]
  },
  // An object.
  info: {
    // 'none' or 'test'.
    mode: "none",
    // 'debug', 'log', 'info', 'warn', or 'error'.
    level: "debug"
  },
  // Clean up large, old caches automatically.
  cachePrune: {
    // Caches younger than `maxAge` are not considered for deletion. They must
    // be at least this (default: 2 days) old in milliseconds.
    maxAge: 2 * 24 * 60 * 60 * 1000,
    // All caches together must be larger than `sizeThreshold` before any
    // caches will be deleted. Together they must be at least this
    // (default: 50 MB) big in bytes.
    sizeThreshold: 100 * 1024 * 1024
  }
})

缩小文件检索解析范围

为避免无用的检索与递归遍历,可以使用alias指定引用时候的模块,noParse,对不依赖本地代码的第三方依赖不进行解析。

Vue-Cli默认已进行了如下配置

代码语言:javascript
复制
noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/

配置

代码语言:javascript
复制
// 定义getAliasPath方法,把相对路径转换成绝对路径
const getAliasPath = dir => join(__dirname, dir)
module.exports = {
	configureWebpack: config => {
    config.module.noParse = /^(vue|vue-router|vuex|vuex-router-sync|lodash|echarts|axios|view-design)$/
  }
  chainWebpack: config => {
    // 添加别名
    config.resolve.alias
      .set('@', getAliasPath('src'))
      .set('assets', getAliasPath('src/assets'))
      .set('utils', getAliasPath('src/utils'))
      .set('views', getAliasPath('src/views'))
      .set('components', getAliasPath('src/components'))
	}
  // 生产环境禁用eslint
  lintOnSave: !process.env.NODE_ENV !== 'production',
}

或者

代码语言:javascript
复制
// vue.config.js
module.exports = {
   configureWebpack:{
    module: {
      noParse: /^(vue|vue-router|vuex|vuex-router-sync|lodash|echarts|axios|view-design)$/
    }
  }
}

import优化

运用这个插件能在代码使用了import语法的情况下,大大提高代码的编译速度。

安装 babel-plugin-dynamic-import-node

代码语言:javascript
复制
npm install --save-dev babel-plugin-dynamic-import-node

vue-cli3

修改babel.config.js文件

代码语言:javascript
复制
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"],
  env: {
    development: {
      plugins: ["dynamic-import-node"]
    }
  }
};

vue.cli2

.babelrc文件

代码语言:javascript
复制
"env": {
        "test": {
                 "plugins": []
                },
        "development":{
                       "presets": ["env", "stage-2"],
                       "plugins": ["dynamic-import-node"]
                      }
       }

打包体积优化

不生成SourceMap

production环境不生成SourceMap

代码语言:javascript
复制
module.exports = {
  lintOnSave: false,
  productionSourceMap: process.env.NODE_ENV !== "production", //打包不生成map文件
}

图片压缩

image-webpack-plugin

对图片像素要求没很极致的,这个压缩还是可以使用的,压缩率肉眼看起来感觉是没太大区别。 这里注意一下,我没有对svg进行压缩,原因是压缩的svg,再通过构建时被打包成base64时,生成的base64会有问题,无法访问。

代码语言:javascript
复制
module.exports = {
  chainWebpack: config => {
   // 对图片进行压缩
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif)(\?.*)?$/)
      .use('image-webpack-loader')
      .loader('image-webpack-loader')
      .options({ bypassOnDebug: true })
      .end()
	}
}

gzip压缩

使用 gzip 压缩代码,效果显著。

安装

代码语言:javascript
复制
npm install compression-webpack-plugin

配置

代码语言:javascript
复制
const CompressionWebpackPlugin = require('compression-webpack-plugin')

module.exports = {
  configureWebpack: config => {
    // 生产环境下生效
    if (process.env.NODE_ENV === 'production') {
      // 配置 gzip 压缩
      config.plugins.push(
        new CompressionWebpackPlugin({
          test: /\.js$|\.html$|\.css$/,
          threshold: 4096 // 超过4kb压缩
        })
      )
    }
  }
}

配置CDN

老实说,我不用这个功能的,线上使用 cdn 总让我有一种不安全感,除非公司有自己的 cdn 库,不过这确实也是一种优化方案,效果也还不错。它的配置也很简单,在 externals 中配置,例子:

代码语言:javascript
复制
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // 配置 cdn,这里将 vue,vue-router 和 axios 三个包配置成 cdn 引入
      // 其中 Vue,VueRouter 等名称是该库暴露在全局中的变量名
      config.externals = {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        axios: 'axios'
      }
    }
  }
}

然后在 public/index.html 模板文件中引入 cdn 地址:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title></title>
    <!-- 引入 cdn 地址 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.10/vue.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.0.1/vue-router.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.18.0/axios.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

我这里使用的是 bootcdn 的地址,需要注意版本问题。

也可以借助 HtmlWebpackPlugin 插件来方便插入 cdn 的引入。

使用 cdn 引入的方式虽然能极大改善网页加载速度,但我还是不会用这个功能,项目还不需要非得这样的优化,也怕 cdn 不稳定。

当然

也可以不用CDN,直接把JS复制到项目下,用相对路径引用即可。

借助 HtmlWebpackPlugin 插件来方便插入 cdn 的引入

代码语言:javascript
复制
//生产环境标记
const IS_PRODUCTION = process.env.NODE_ENV === "production";
const path = require("path");
// 生产配置
const cdn_production = {
  js: ["/librarys/vue@2.6.11/vue.min.js"]
};
// 开发配置
const cdn_development = {
  js: ["/librarys/vue@2.6.11/vue.js"]
};

module.exports = {
  configureWebpack: {
    externals: {
      vue: "Vue",
    },
  },
  chainWebpack: config => {
    config.plugin("html").tap(args => {
      args[0].cdn = IS_PRODUCTION ? cdn_production : cdn_development;
      return args;
    });
  }
};

index.html中添加

代码语言:javascript
复制
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
  <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>

Vue Cli配置说明

https://cli.vuejs.org/zh/guide/webpack.html

简单的配置方式

调整 webpack 配置最简单的方式就是在 vue.config.js 中的 configureWebpack 选项提供一个对象:

代码语言:javascript
复制
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      new MyAwesomeWebpackPlugin()
    ]
  }
}

该对象将会被 webpack-merge 合并入最终的 webpack 配置。

链式操作 (高级)

Vue CLI 内部的 webpack 配置是通过 webpack-chain 维护的。这个库提供了一个 webpack 原始配置的上层抽象,使其可以定义具名的 loader 规则和具名插件,并有机会在后期进入这些规则并对它们的选项进行修改。

它允许我们更细粒度的控制其内部配置。接下来有一些常见的在 vue.config.js 中的 chainWebpack 修改的例子。

提示

当你打算链式访问特定的 loader 时,vue inspect 会非常有帮助。

修改 Loader 选项

代码语言:javascript
复制
// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(
      options => {
        // 修改它的选项...
        return options
      })
  }
}

提示

对于 CSS 相关 loader 来说,我们推荐使用 css.loaderOptions 而不是直接链式指定 loader。这是因为每种 CSS 文件类型都有多个规则,而 css.loaderOptions 可以确保你通过一个地方影响所有的规则。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 查看Vue-Cli中的Webpack配置
  • 分析
    • 查看构建时间
      • 查看构建库大小
        • VUE CLI内置工具
        • webpack-bundle-analyzer
    • 优化
      • 构建速度优化
        • happypack
        • vue-cli-plugin-dll
        • 多线程优化
        • 缓存构建
        • 缩小文件检索解析范围
        • import优化
      • 打包体积优化
        • 不生成SourceMap
        • 图片压缩
        • gzip压缩
        • 配置CDN
    • Vue Cli配置说明
      • 简单的配置方式
        • 链式操作 (高级)
          • 修改 Loader 选项
      相关产品与服务
      内容分发网络 CDN
      内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档