首页 前端知识 vue前端项目优化(编译速度、打包体积、性能)

vue前端项目优化(编译速度、打包体积、性能)

2025-03-08 14:03:45 前端知识 前端哥 58 793 我要收藏

一、编译速度优化

1.使用缓存

  • 在webpack3中为了提高构建速度,我们往往会用到 DllPlugin 和 DllReferencePlugin 插件,但是配置复杂,更新文件还需要手动重新生成dll,比较繁琐。还有一种autodll-webpack-plugin插件会好用一些。
  • 在webpack4之后可以使用HardSourceWebpackPlugin插件,它通过在磁盘中设置缓存来提升编译加载速度,第一次正常编译并缓存,第二次有缓存后能减少80%-90%的时间,需要安装插件后使用。
  • webpack5主要使用内置的cache配置。

1.1 autodll-webpack-plugin插件

autodll-webpack-plugin插件可以将项目中的第三方库(如lodash、moment等)单独打包成一个DLL文件,从而减少主文件的体积,提高编译速度。 运行webpack命令进行构建,生成的DLL文件会存放在dist目录下。通过使用autodll-webpack-plugin插件,可以有效地优化Vue项目,提高编译速度和运行效率。

安装

 npm install autodll-webpack-plugin --save-dev

引入

 const AutoDllPlugin = require('autodll-webpack-plugin');

配置

module.exports = {
   // ...其他配置
   plugins: [
     // ...其他插件
     new AutoDllPlugin({
       inject: true, // 自动注入生成的DLL文件到HTML中
       filename: '[name].dll.js', // DLL文件名格式
       entry: {
         vendor: ['vue', 'vue-router', 'vuex'] // 需要单独打包的第三方库
       }
     })
   ]
 };
1.2 HardSourceWebpackPlugin插件

HardSourceWebpackPlugin是一个用于优化Webpack构建速度的插件。它可以为模块代码创建内存缓存,这样在每次构建时,只需要处理发生更改的模块,而不是重新处理所有模块。 为了查看结果,需要使用此插件运行 webpack 两次:第一次构建将花费正常的时间。第二个构建速度将明显加快。

安装

 npm install hard-source-webpack-plugin --save-dev

引入

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

配置

module.exports = {
     // ...
     configureWebpack: smp.wrap({
         plugins: [
           // 为模块提供中间缓存,缓存路径是:node_modules/.cache/hard-source
           new HardSourceWebpackPlugin()
         ]
     })
     // ...
 }
  • 注意:这里有另一个插件 speed-measure-webpack-plugin插件,作用是分析构建时各模块耗时,不能与hard-source-webpack-plugin一起使用

1.3 webpack5配置cache

webpack5 内置了 cache 缓存机制。直接配置即可。cache 会在开发模式下被设置成 type: memory 而且会在生产模式把cache 给禁用掉。

配置

 // webpack.config.js 或 vue.config.js
 const path = require('path')
 ​
 module.exports = {
     transpileDependencies: true,
     configureWebpack: {
         cache: {
             type: 'filesystem', // 设置缓存类型为文件系统
             cacheDirectory: path.resolve(__dirname, '.webpack_cache') // 设置缓存目录(根路径下)
             // cacheDirectory: path.join(__dirname, 'node_modules/.cache/webpack_cache') // 设置缓存目录(node_modules/.cache路径下)
         }
     }
 }

2.多线程打包

2.1 thread-loader

thread-loader 是一个 Webpack 的 loader,它可以将一些开销较大的工作放到 worker 池中,并在 worker 池中执行,以提高构建速度。 注意,thread-loader 并不是适用于所有场景的,它只对一些开销较大的任务有效。如果任务本身就非常快速并且非常简单,则使用 thread-loader 可能会比直接在主线程中执行更慢。因此可以使用上文提到的speed-measure-webpack-plugin插件对构建时各模块的耗时进行分析,对开销较大的模块使用thread-loader以提高构建速度。

安装

 npm install thread-loader --save-dev

使用示例(具体配置写法根据项目不同写法各异)

 // webpack.config.js
 module.exports = {
   module: {
     rules: [
       {
         test: /.js$/,
         include: path.resolve('src'),
         exclude: /node_modules/,
         use: [
           'thread-loader', // 将后续 loader 放在 worker 池中执行耗时的 loader (例如 babel-loader)
           'babel-loader'
         ]
       }
     ]
   }
 }
 ​
 // vue.config.js
 module.exports = {
   // ...
   configureWebpack: {
     module: {
       rules: [
         {
           test: /.js$/,
           include: path.resolve('src'),
           exclude: /node_modules/,
           use: [
             'thread-loader', // 将后续 loader 放在 worker 池中执行耗时的 loader (例如 babel-loader)
             'babel-loader'
           ]
         }
       ]
     }
   }
 }
2.2 HappyPack

HappyPack 是一个用于将 Webpack 进行多线程编译的工具,它能够将一个复杂的 Loader 或者 Plugin 任务分解成多个子进程并行执行,以此来加快构建速度。

安装

npm install happypack --save-dev

配置

 const HappyPack = require('happypack');
 ​
 module.exports = {
   // ...
   module: {
     rules: [
       {
         test: /.js$/,
         exclude: /node_modules/,
         use: 'happypack/loader?id=js'
       }
     ]
   },
   plugins: [
     new HappyPack({
       id: 'js',
       threads: 4,
       loaders: ['babel-loader']
     })
   ],
   // ...
 };

3.开启热更新/热重载

  • 热更新(Hot Update):在代码文件被修改后,自动编译出新的代码,并将新代码注入到浏览器运行的 JavaScript 中。热更新并没有重新加载页面,而是更新了部分改动的内容,保留了页面的状态信息,因此可以保持用户的操作状态。
  • 热重载(Hot Reload):在代码文件被修改后,以最快的速度重新编译、打包,并刷新浏览器窗口。相比于热更新,热重载不仅更新了 JavaScript 代码,还重新渲染了整个页面,因此会有一短暂的闪屏,更适用于 UI 相关的修改。
  • 模块热替换(Hot Module Replacement):类似于热更新,但是只替换变化的部分,不会重载整个模块或者应用程序,因此速度更快,体验更好。模块热替换不仅适用于 JavaScript 模块,还可以用于 CSS、图片等资源的替换。
3.1 HotModuleReplacementPlugin 插件

HotModuleReplacementPlugin 是 Webpack 提供的一个插件,用于启用模块热替换(HMR)功能。HMR 是一种开发模式,它可以在不刷新整个页面的情况下,只更新修改过的部分,提高开发效率。 通过上述配置,就可以开启 Webpack 的模块热替换功能,使得在开发过程中能够实时预览修改的效果,提高开发效率。需要注意的是,HMR 功能只适用于开发环境,在生产环境中不应该使用。

const webpack = require('webpack');
 ​
 module.exports = {
   // ...
   mode: 'development',
   devtool: 'eval-source-map', // 使用 source-map 方便调试
   devServer: {
     port: 8080,
     hot: true, // 开启 HMR 功能
     open: true // 自动打开浏览器
   },
   plugins: [
     new webpack.HotModuleReplacementPlugin() // 启用 HMR 功能
   ]
 }
3.2 babel-plugin-dynamic-import-node 插件

babel-plugin-dynamic-import-node 是一个 Babel 插件,用于在开发环境中动态导入模块,从而帮助 Hot Module Replacement (HMR) 更快地处理模块的更新。要使用这个插件,你需要按照以下步骤操作:

1.安装插件: 首先,通过 npm 安装 babel-plugin-dynamic-import-node 插件:

 npm install --save-dev babel-plugin-dynamic-import-node

2.配置 Babel: 在你的项目根目录下找到或者创建一个 Babel 配置文件(通常是 .babelrc 或 babel.config.js 文件),然后在 "plugins" 部分添加 'dynamic-import-node'

 {
   "plugins": ["dynamic-import-node"]
 }

如果你使用的是 babel.config.js,则配置如下:

 module.exports = {
   plugins: ['dynamic-import-node'],
 }   

3.在代码中使用: 在你的代码中,你可以使用 ES2020 的动态 import() 语法来导入模块。例如:

if (condition) {
   import('./module.js').then((module) => {
     // 使用 module
   });
 }

4.Webpack 配置: 确保你的 Webpack 配置中已经启用了 HMR。具体配置参考3.1所述。

4.exclude & include

在 Vue 项目中使用 exclude 和 include 可以帮助提升编译速度,这是因为它们可以减少不必要的文件检查和编译。

exclude 和 include 是通过 webpack 的 module.rules 配置项来设置的。其中,exclude 表示排除某些目录或文件不被编译,而 include 表示包含某些目录或文件进行编译。

下面以 Vue 项目的 Babel 编译为例,介绍如何使用 exclude 和 include。

安装依赖:其中,babel-loader 是用于编译 JavaScript 代码的工具,@babel/core 是 Babel 核心库,@babel/preset-env 是一种预设包,可以根据目标环境自动选择转换插件。

 npm install --save-dev babel-loader @babel/core @babel/preset-env

配置 webpack.config.js:

以下配置中,exclude: /node_modules/ 表示排除 node_modules 目录下的 JavaScript 文件不被编译,以提高编译速度。

module.exports = {
   // ...其他配置
   module: {
     rules: [
       {
         test: /.js$/,
         exclude: /node_modules/,
         use: {
           loader: 'babel-loader',
           options: {
             presets: ['@babel/preset-env']
           }
         }
       }
     ]
   }
 }

有时候,如果我们只需要编译项目中某个目录下的 JavaScript 文件,可以使用 include 来指定相应的目录。例如,我们只需要编译 src/components 目录下的 JavaScript 文件,可以将配置改为:

module.exports = {
   // ...其他配置
   module: {
     rules: [
       {
         test: /.js$/,
         include: path.resolve(__dirname, 'src/components'),//表示只包含 src/components 目录下的 JavaScript 文件进行编译
         use: {
           loader: 'babel-loader',
           options: {
             presets: ['@babel/preset-env']
           }
         }
       }
     ]
   }
 }

5.提高 webpack版本

升级 Webpack 版本是提高构建速度的一个重要方式,每个新版本都会带来新的优化和性能改进。

更新 Webpack 到最新版本: 首先需要确定当前使用的 Webpack 版本并检查是否需要更新,可以通过 npm 命令安装最新版本的 Webpack:

  • 检查 Webpack 相关的插件和 loader 的版本: 升级 Webpack 时,应该同时检查相关的插件和 loader 是否需要更新,需要确保其与 Webpack 的版本兼容。
  • 移除废弃的插件和 loader: 升级可能有些插件和loader 已经随着升级废弃了,因此需要移除对应的插件和 loader。

三、打包体积优化

1.分析打包结果

webpack-bundle-analyzer 是一个 Webpack 插件和命令行工具,用于分析 Webpack 的打包文件。在 Vue CLI 项目中使用它,可以帮助你理解并优化你的应用程序包的大小。

要在 Vue CLI 项目中使用 webpack-bundle-analyzer,你需要按照以下步骤操作:

1.安装: 首先,你需要在你的 Vue CLI 项目中安装 webpack-bundle-analyzer 插件。你可以通过运行以下命令来安装:

 npm install --save-dev webpack-bundle-analyzer 

2.配置: 接下来,你需要在你的 Webpack 配置文件中添加 webpack-bundle-analyzer 插件。对于 Vue CLI 3 项目,你可以在 vue.config.js 文件中进行配置。如果文件不存在,你需要创建它。在 vue.config.js 文件中,你可以添加以下内容:

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

对于 Vue CLI 4 及更高版本的项目,你需要在 vue.config.js 文件中稍微修改配置:

// javascript复制代码运行
 const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
 ​
 module.exports = {
   configureWebpack: {
     plugins: [
       new BundleAnalyzerPlugin()
     ]
   }
 };
  • 构建: 现在,当你运行 Vue CLI 项目的构建命令时,webpack-bundle-analyzer 将会被触发。它将分析你的打包文件,并自动打开一个网页,显示各个包的大小和组成。

  • 查看报告: Webpack Bundle Analyzer 会生成一个交互式的可视化报告,你可以在浏览器中查看。报告将展示每个包的内容,以及它们的大小。这有助于识别可以优化的地方,例如未使用的代码或过大的依赖项。

  • 优化: 根据报告的结果,你可以采取相应的优化措施,例如移除不必要的依赖、按需导入组件或模块、使用 Tree-shaking 和 Code Splitting 等 Webpack 功能。

2.第三方库按需引入

如:element-ui按需引用,echart按需引用, lodash按需引用。

3.生产环境去掉onsole.log

3.1 babel-plugin-transform-remove-console插件

这是一个Babel插件,可以在构建期间删除所有console.*语句

安装

npm install --save-dev babel-plugin-transform-remove-console

配置: babel.config.js.babelrc文件中添加以下代码

const plugins = [];
 // remove console.* in production
 if (process.env.NODE_ENV === 'production') {
   plugins.push('transform-remove-console');
   // plugins.push(['transform-remove-console', { 'exclude': ['error', 'warn'] }]);
 }
 module.exports = {
   // ...
   plugins: plugins,
 };
3.2 main.js里面通过方法实现
// main.js
 function isProduction() {
   return process.env.NODE_ENV === 'production';
 }
 ​
 if (isProduction()) {
   console.log = function () {};
 }
 ​
 // 在需要的地方调用console.log
 console.log("这是一个测试信息"); // 如果当前环境是生产环境,则不会输出任何内容

4.合理使用source-map

productionSourceMap的作用在于定位问题,打包时会生成.map文件,在生产环境就可以在浏览器查看到输出的信息具体是在哪一行,但相应的包的体积也会变大,也会影响构建速度,将其设置为false则不生成.map文件,既可以减少包大小,也可以加密源码。

 module.exports = {
     productionSourceMap: false
 }

5.压缩css、js、图片资源,删除无用代码

5.1 css/js压缩

安装插件

npm install css-minimizer-webpack-plugin terser-webpack-plugin --save-dev

配置

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
 const TerserPlugin = require('terser-webpack-plugin');
 
 module.exports = {
   configureWebpack: {
     optimization: {
       minimizer: [
         new CssMinimizerPlugin(),
         new TerserPlugin()
       ]
     }
   },
   css: {
     extract: true, //将 CSS 提取到单独的文件中
     minimize: true, //启用 CSS 压缩
     sourceMap: false, //禁用 CSS source map
     loaderOptions: { //特定的加载器(如 Sass 或 Less)提供额外的配置
       sass: {
         prependData: `@import "~bootstrap/scss/functions"; @import "~bootstrap/scss/variables";`, //
       },
     },
   },
 };
5.2 图片资源压缩

安装loader

 npm install --save-dev image-webpack-loader

配置

module.exports = {
     ...
     // 配置别名
     chainWebpack: config => {
         // 图片压缩
         config.module
             .rule('images')
             .exclude.add(resolve('src/assets/icons')) // 排除icons目录,这些图标已用 svg-sprite-loader 处理,打包成 svg-sprite 了
             .end()
             .use('url-loader')
             .tap(options => ({
                 limit: 10240, // 稍微改大了点
                 fallback: {
                     loader: require.resolve('file-loader'),
                     options: {
                         // 在这里修改file-loader的配置
                         // 直接把outputPath的目录加上,虽然语义没分开清晰但比较简洁
                         name: 'static/img/[name].[hash:8].[ext]',
                         esModule: false, //低版本默认为false,高版本默认为true 这里为6.2.0为高本版本所以要手动设置为false
                     }
                 }
             }))
             .end()
             .use('image-webpack-loader')
             .loader('image-webpack-loader')
             .options({
                 mozjpeg: { progressive: true, quality: 50 }, // 压缩JPEG图像
                 optipng: { enabled: true }, // 压缩PNG图像
                 pngquant: { quality: [0.5, 0.65], speed: 4 }, // 压缩PNG图像
                 gifsicle: { interlaced: false } // 压缩GIF图像
             })
             .end()
             .enforce('post') // 表示先执行配置在下面那个loader,即image-webpack-loader
     },
 }

四、性能优化

1.路由懒加载

路由懒加载是指在需要的时候才加载对应的路由模块,而不是在项目初始化时就加载所有的路由模块。这样可以减少初始加载时间和资源消耗,提高页面加载速度和用户体验。在 Vue 项目中,可以使用动态导入的方式来实现路由懒加载。

在路由配置文件(如 router.js)中定义路由时,使用 import 函数懒加载路由组件

 import Vue from 'vue'
 import Router from 'vue-router'
 ​
 Vue.use(Router)
 ​
 const Home = () => import('./views/Home.vue')
 ​
 export default new Router({
   mode: 'history',
   base: process.env.BASE_URL,
   routes: [
     {
       path: '/',
       name: 'home',
       component: Home
     },
   ]
 })

2.合理使用watch & conputed

1.优化 watch 的性能

  • 尽量避免在 watch 中进行异步操作,因为异步操作通常会阻塞 JS 线程,影响页面性能。如果必须进行异步操作,可以使用 vm.$nextTickPromise.then 方法,将异步操作推迟到下一次 DOM 更新时执行。
  • 在监听数组或对象等复杂数据类型时,尽量使用 deep 选项来监听其子属性的变化,而不是使用 immediate 选项来立即执行回调函数。因为 immediate 会立即执行回调函数,导致监听的数据被多次计算和渲染,影响页面性能。
  • 避免在 watch 中执行过多的计算和渲染操作,尽量将这些操作放在 computed 属性中进行处理。

2.优化 computed 的性能

  • 避免在 computed 中引用其他 computed,因为这样会导致多余的计算和渲染,降低页面性能。
  • 对于数据量较大或计算量较大的 computed,可以使用 lazy 选项,将其设置为惰性计算,只有在需要计算时才会重新计算。
  • 对于一些频繁变化的响应式数据,可以考虑使用 watch 来监听其变化,而不是使用 computed 来计算。

3.合理使用防抖、节流函数

函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象,是应对频繁触发事件的优化方案。

4.合理使用v-if、v-show

1.v-if

  • 作用:根据绑定的表达式的真假值来决定是否渲染 DOM 元素。当绑定的表达式为真值时,该元素会被渲染到页面中;当绑定的表达式为假值时,该元素不会被渲染到页面中,相当于从 DOM 树中移除该元素及其子元素。
  • 优点:在条件不成立时,可以减少不必要的 DOM 元素的渲染和加载,从而提高页面的加载速度和性能表现。
  • 缺点:每次切换条件,都会重新创建和销毁对应的组件或元素,因此在程序运行时可能会比 v-show 慢。

2.v-show

  • 作用:根据绑定的表达式的真假值来控制元素的显示和隐藏。与 v-if 不同,v-show 并不会从 DOM 树中移除元素,而是通过修改其 CSS 样式来控制元素的显示和隐藏。
  • 优点:在条件不成立时,并不会从 DOM 树中移除该元素及其子元素,因此在切换条件时,可以保留该元素的状态和属性,提高页面切换的平滑度和体验。
  • 缺点:在条件不成立时,该元素仍会被加载到页面中,因此可能会增加页面的渲染和加载时间。所以,对于需要频繁切换的元素或组件,建议使用 v-show
转载请注明出处或者链接地址:https://www.qianduange.cn//article/22923.html
标签
评论
发布的文章

Lua与Unity交互

2025-03-08 14:03:36

Pygame介绍与游戏开发

2025-03-08 14:03:36

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!