一招教会你提高vue-cli3项目的打包和编译速度

一、背景

由于旧项目是用vue-cli3脚手架搭建,随着项目代码不断增加,webpack每次热更新都需要编译很久,同时打包构建所需时间也增加了不少,鉴于升级webpack版本会出现各自意想不到的坑,所以决定通过优化webpack配置来提高项目的编译和构建速度,话不多说,开整!!!!!

二、项目环境

本次优化的项目的环境是:node版本14.17.0 npm版本6.14.13

js 复制代码
package.json 限定了node和npm的版本
"engines": {
    "node": ">=14.17.0",
    "npm": ">=6.14.13"
  },

三、使用Happypack插件

使用该插件的主要目的是因为该插件将任务分解到多个子进程中去并行处理,从而减少总的构建时间。使用配置如下:

js 复制代码
vue.config.js文件
安装happypack npm install happypack -D
const Happypack = require('happypack')
configureWebpack:{
// 该配置可以提高25%左右的速度
 new Happypack({
      loaders: ['babel-loader', 'vue-loader', 'url-loader'],
      cache: true,
      threads: 10 // 线程数取决于你电脑性能的好坏,好的电脑建议开更多线程
    })
}

四、使用文件压缩插件 compression-webpack-plugin

该插件的主要作用是压缩文件,可以降低dist包文件大小,配置如下:

js 复制代码
// 需要压缩的文件
vue.config.js文件
安装compression-webpack-plugin npm install compression-webpack-plugin -D
// 压缩,可以将dist文件由20M压缩到3M
const CompressionPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
configureWebpack:{
 plugins: [
      new CompressionPlugin({
      test: productionGzipExtensions, // 需要压缩的文件正则
      threshold: 10240, // 文件大小大于这个值时启用压缩
      deleteOriginalAssets: true // 压缩后保留原文件
    })
  ]
}

五、使用dll

该插件是用于打包一些版本基本不怎么变的第三方库,然后引入到index.html文件里,它的主要作用是缓存和复用代码,以提高构建速度和效率。使用DLL插件可以避免重复打包和编译那些没有改变的或者变化不大的代码,从而提高构建速度和效率。DLL插件的使用可以显著提高大型项目的构建速度,同时也可以减少打包文件的大小。具体使用方式如下

js 复制代码
安装 npm install --save-dev webpack-dll-plugin
安装 html-include-assets-plugin 
// 开启dll
const dllHelper = require('./dllHelper');
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');
const HtmlIncludeAssetsPlugin = require('html-include-assets-plugin');  
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
configureWebpack:{
 plugins: [
      // 开启dll,构建时间可以减短,比HardSourceWebpackPlugin更快,但是每次都需要执行dll命令
    ...dllHelper.genDllReferences(),
    new HtmlIncludeAssetsPlugin({
     assets: dllHelper.loadDllAssets(), 
    append: false
    })
  ]
}
js 复制代码
新建一个webpack.dll.conf.js文件
安装 clean-webpack-plugin
const path = require('path')
const webpack = require('webpack')
const  CleanWebpackPlugin = require('clean-webpack-plugin')

// dll文件存放的目录
const dllPath = 'public/vendor'

module.exports = {
  entry: {
    // 需要提取的库文件
    vue: ["vue", "vue-router", "vuex"],
    plugin: ['vxe-table','vxe-table-plugin-antd','ali-oss'],
    ui: ['ant-design-vue'],
  },
  output: {
    path: path.join(__dirname, dllPath),
    filename: '[name].dll.js',
    // vendor.dll.js中暴露出的全局变量名
    // 保持与 webpack.DllPlugin 中名称一致
    library: '[name]_[hash]'
  },
  plugins: [
    // 清除之前的dll文件
    new CleanWebpackPlugin(),
    // 设置环境变量
    // new webpack.DefinePlugin({
    //   'process.env': {
    //     NODE_ENV: 'production'
    //   }
    // }),
    // manifest.json 描述动态链接库包含了哪些内容
    new webpack.DllPlugin({
      path: path.join(__dirname, dllPath, '[name]-manifest.json'),
      // 保持与 output.library 中名称一致
      name: '[name]_[hash]',
      context: process.cwd()
    })
  ]
}
js 复制代码
新建dllHelper.js 文件

// config/dllHelper.js
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
const dllConfig = require('./webpack.dll.conf');

// 根据entry生成DllReferencePlugin列表
function genDllReferences() {
  return Object.keys(dllConfig.entry).map(
    name =>
      new webpack.DllReferencePlugin({
        manifest: require(path.join(
          __dirname,
          `./public/vendor/${name}-manifest.json`
        ))
      })
  );

}

// 生成dll文件的静态资源路径
function loadDllAssets() {
  return fs
    .readdirSync(path.resolve(__dirname, 'public/vendor'))
    .filter(filename => filename.match(/.dll.js$/))
    .map(filename => `vendor/${filename}`);
}

module.exports = {
  loadDllAssets,
  genDllReferences
};
构建前,我们需要配置dll命令,执行npm run dll 命令,最终dll文件会插入到index.html文件中
"script":{
 "dll": "webpack -p --progress --config ./webpack.dll.conf.js"
 }

六、使用HardSourceWebpackPlugin,这个插件会比dll要慢一点,主要是设置缓存,提高二次构建的速度

js 复制代码
安装HardSourceWebpackPlugin npm install HardSourceWebpackPlugin -D
// 缓存
const HardSourceWebpackPlugin = 
    require('hard-source-webpack-plugin');
configureWebpack:{
 plugins: [
     // 设置缓存,缺陷在于会占用本地磁盘空间,比dll慢,两个一起用比dll还慢一点点
new HardSourceWebpackPlugin({
  //设置缓存目录的路径
  //相对路径或者绝对路径
  cacheDirectory: 'node_modules/.cache/hard-source/[confighash]',
  //构建不同的缓存目录名称
  //也就是cacheDirectory中的[confighash]值
  configHash: function(webpackConfig) {
    return require('node-object-hash')({sort: false}).hash(webpackConfig);
  },
  //环境hash
  //当loader、plugin或者其他npm依赖改变时进行替换缓存
  environmentHash: {
    root: process.cwd(),
    directories: [],
    files: ['package-lock.json', 'yarn.lock'],
  },
  //自动清除缓存
  cachePrune: {
    //缓存最长时间(默认2天)
    maxAge: 2 * 24 * 60 * 60 * 1000,
    //所有的缓存大小超过size值将会被清除
    //默认50MB
    sizeThreshold: 50 * 1024 * 1024
  },
}),
  ]
}

七、代码分割

js 复制代码
chainWebpack: (config) => {
 //代码分割
    config.optimization.splitChunks({
      //chunks: 'all'
      cacheGroups: {
        vendor: {//第三方库抽离
            chunks: 'all',
            test: /node_modules/,
            name: 'vendor',
            minChunks: 1,//在分割之前,这个代码块最小应该被引用的次数
            maxInitialRequests: 5,
            minSize: 0,//大于0个字节
            priority: 100//权重
        },
        common: {  //公用模块抽离
            chunks: 'all',
            test: /[\\/]src[\\/]js[\\/]/,
            name: 'common',
            minChunks: 2,//在分割之前,这个代码块最小应该被引用的次数
            maxInitialRequests: 5,
            minSize: 0,//大于0个字节
            priority: 60
        },
        styles: { //样式抽离
            name: 'styles',
            test: /\.(sa|sc|c)ss$/,
            chunks: 'all',
            enforce: true
        },
        runtimeChunk: {
            name: 'manifest'
        }
    }

    })
 }

八、配置一些loader配置

js 复制代码
configureWebpack:{
module: {
//如果一些第三方模块没有AMD/CommonJS规范版本,可以使用 noParse 来标识这个模块,
//这样 Webpack 会引入这些模块,但是不进行转化和解析,从而提升 Webpack 的构建性能 ,例如:jquery 、lodash。
      noParse: /^(lodash|moment|xe-utils|xlsx|ali-oss)$/,
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
          // 开启缓存
           cacheDirectory: true
          }
        },
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env']
            }
          }
        },
        
      ]
   }
}

九、开启文件变化监听,速度提升不算很大,在大型项目比较有用

js 复制代码
  chainWebpack: (config) => {
 if (process.env.NODE_ENV !== 'production') {  
        config.watch(true)
        config.watchOptions(  
          {  
            // 排除监听文件
              ignored: /node_modules/,
            // 在监听到文件变化后等待一段时间再执行编译
             aggregateTimeout: 300, // 300ms 
            // 开启轮询
            poll: 100
          } 
        )
      }
      }

总结:以上配置可以按需选择,并不一定所有配置都需要用上,选择你觉得对你项目效果比较明显的即可。

相关推荐
mldong6 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi10 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端