如何优化你的 vue-cli 项目?(下)

简介: 如何优化你的 vue-cli 项目?

对图片压缩

针对一些对图片像素没有很高要求的图片资源进行压缩,这里可以通过 image-webpack-pluginimage-minimizer-webpack-plugin 进行图片资源的压缩,具体配置可以直接点链接进行查阅.

外部扩展 —— externals & cdn

externals 选项就是用于 防止 将某些 import 的包(package) 打包到 bundle 中,而是在运行时(runtime) 再去从外部获取这些 扩展依赖(external dependencies),具体可见

简单来说就是原本应该要被打包到 bundle 中的 js,现在通过配置 externals 选项,将它做外 bundle 之外的资源,即 cdn 资源,在代码运行时再去请求这个资源。

例如,下面就是在项目关于 externals 的配置:

chainWebpack: (config) => {
    ...
    // 通过 CDN 方式引入资源
      config.externals({
        echarts: 'echarts',
        nprogress: 'NProgress',
      });
 }
复制代码

DllPlugin 插件 —— 优化打包时间

PS: webpack4或以上的版本,vue官方react 官方 都已不推荐使用此插件DllPlugin 插件负责将那些比较稳定(例如 vue/react 全家桶)的库进行打包拆分 bundles,下次在打包时就不需要重复进行打包,因此大幅度提升了构建的速度。

webpack4 版本中,已经集成 DllPlugin 插件,我们只需要进行配置即可,具体可见

  • 创建 dll.js 文件,进行简单配置
const path = require('path');
const webpack = require('webpack');
module.exports = {
  entry: {
    vendor: ['echarts', 'element-ui', 'vue/dist/vue.esm.js', 'vue-router', 'vuex'],
  },
  output: {
    path: path.join(__dirname, 'target'),
    filename: '[name].js',
    library: '[name]_[hash]',
  },
  plugins: [
    new webpack.DllPlugin({
      // DllPlugin的name属性需要和libary保持一致
      name: '[name]_[hash]',
      //指定当前目录
      path: path.join(__dirname, '.', '[name]-manifest.json'),
      // context需要和webpack.config.js保持一致
      context: __dirname,
    }),
  ],
};
复制代码
  • package.json 文件中配置 script 脚本:"dll": "webpack --config ./dll.js"
  • 安装 webpack-cli,因为原本依赖中并没有安装过这个依赖,而运行这个脚本命令需要 webpack-cli
  • 执行脚本命令 npm run dll,生成 vendor-manifest.json 文件,这个文件是用于让 DllReferencePlugin 能够映射到相应的依赖上

image.png

  • vue.config.js 中配置 DllReferencePlugin 插件,链接到已被打包的依赖上
const { pathResolve } = require('./build/utils.js'); // eslint-disable-line
const devConfig = require('./build/webpack.dev.conf.js'); // eslint-disable-line
const buildConfig = require('./build/webpack.prod.conf.js');
// 分析工具
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// 资源缓存
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
// 抽离稳定的第三方库,避免重复打包
const DllReferencePlugin = require('webpack').DllReferencePlugin;
// 公共函数
const { versionSet } = require('./build/utils'); // eslint-disable-line
// 是否为开发环境
const isDevelopment = process.env.NODE_ENV == 'development';
const vueWebpackConfig = () => {
  let envConfig = {};
  if (isDevelopment) {
    // 开发
    envConfig = devConfig;
  } else {
    // 构建
    versionSet();
    envConfig = buildConfig;
  }
  const vueConfig = {
    // 环境配置
    ...envConfig,
    productionSourceMap: isDevelopment, // 是否在构建生产包时生成sourcdeMap
    // 拓展webpack配置
    chainWebpack: (config) => {
      //  ============ 配置别名 ============
      config.resolve.alias
        .set('@build', pathResolve('../build')) // 构建目录
        .set('@', pathResolve('../src'))
        .set('@api', pathResolve('../src/api'))
        .set('@utils', pathResolve('../src/utils'))
        .set('@views', pathResolve('../src/views'));
      // ============ svg处理 ============
      const svgRule = config.module.rule('svg');
      // 清除已有的所有 loader。
      // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
      svgRule.uses.clear();
      // 添加要替换的 loader
      svgRule.use('svg-sprite-loader').loader('svg-sprite-loader').options({
        symbolId: 'icon-[name]',
      });
      // ============ 压缩图片 ============
      config.module
        .rule('images')
        .use('image-webpack-loader')
        .loader('image-webpack-loader')
        .options({ bypassOnDebug: true })
        .end();
      // ============ 打包分析工具 ============
      if (!isDevelopment) {
        if (process.env.npm_config_report) {
          config.plugin('webpack-bundle-analyzer').use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin).end();
          config.plugins.delete('prefetch');
        }
      }
      // ============ CDN资源引入 ============
      config.externals({
        // echarts: 'echarts',
        nprogress: 'NProgress',
      });
    },
    configureWebpack: (config) => {
      // 尽量保证项目中文件后缀的精确
      config.resolve.extensions = ['.ts', '.js', '.vue', '.json'];
      // 处理 babel-loader
      config.module.rules[12].use.unshift({
        loader: 'thread-loader',
      });
      config.plugins.push(
        // 为模块提供中间缓存,缓存路径是:node_modules/.cache/hard-source
        new HardSourceWebpackPlugin({
          root: process.cwd(),
          directories: [],
          environmentHash: {
            root: process.cwd(),
            directories: [],
            // 配置了files 的主要原因是解决配置更新,cache 不生效了的问题,配置后有包的变化,plugin 会重新构建一部分cache
            files: ['package.json', 'yarn.lock'],
          },
        }),
        // DllReferencePlugin 插件
          new DllReferencePlugin({
            context: __dirname,
            // manifest就是我们第 2 步中打包出来的 json 文件
            manifest: require('./vendor-manifest.json'),
          }),
        // 分析工具
        new SpeedMeasurePlugin(),
        new BundleAnalyzerPlugin(),
      );
    },
  };
  return vueConfig;
};
module.exports = vueWebpackConfig();
复制代码

其他优化

resolve.alias & resolve.extensions

resolve.alias 是用于创建 importrequire 的别名,来确保模块引入变得更简单

例如,下面是项目中定义的一些别名:

chainWebpack: (config) => {
      // 配置别名
      config.resolve.alias
        .set('@build', pathResolve('../build')) // 构建目录
        .set('@', pathResolve('../src'))
        .set('@api', pathResolve('../src/api'))
        .set('@utils', pathResolve('../src/utils'))
        .set('@views', pathResolve('../src/views'));
  }
复制代码

resolve.extensions 指定为对应的文件后缀,保证在查找模块时的无用查找和递归等,即保证这个配置里的文件后缀要尽可能少。

image.png

image.png

减少不必要的解析 —— module.noParse

module.noParse 是防止 webpack 解析那些任何与给定正则表达式相匹配的文件,忽略的文件中 不应该含有import, require, define 的调用,或任何其他导入机制,通过忽略大型的 library 可以提高构建性能。

例如,vue-cli 中关于 module.noParse 的配置如下:

image.png

代码层面优化

webpack-bundle-analyzer 反应的内容,可以发现某些 jscss 模块体积相对来说比较大,这个时候可以找到对应的文件梳理逻辑并进行代码优化,如封装 js 逻辑、抽离 css 样式等,即最基本的优化就是少书写重复的样式和逻辑,这样也能避免一些无效的重复编译.

最后

欢迎关注同名公众号《熊的猫》,文章会同步更新!

以上就是一些基于 vue-cli(基于 webapck) 进行的一些优化,如果你之前没有进行过相应优化,那么你可以试试。

最后来看看优化前后,生产打包构建时间的变化:

image.png

对 webpack 转 vite 感兴趣的可食用基于 webpack 项目接入 vite 你可能需要注意的点


目录
相关文章
|
8月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
461 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
JavaScript 数据可视化
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
这篇文章介绍了如何使用vue-cli 2和3版本来创建Vue项目,并详细说明了两者之间的主要区别。
346 5
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
|
JavaScript 容器
乾坤qiankun框架搭建 主应用为vue3的项目。
乾坤qiankun框架搭建 主应用为vue3的项目。
708 2
|
5月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
248 0
|
9月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
364 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
9月前
|
前端开发 JavaScript Java
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
485 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
|
9月前
|
SQL JavaScript 安全
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
416 11
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
|
9月前
|
人工智能 JavaScript 安全
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
441 13
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
|
8月前
|
资源调度 JavaScript 前端开发
Pinia 如何在 Vue 3 项目中进行安装和配置?
Pinia 如何在 Vue 3 项目中进行安装和配置?
656 4
|
9月前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
593 12