Vue项目卡顿慢加载?这些优化技巧告诉你!(二)

简介: Vue项目卡顿慢加载?这些优化技巧告诉你!(二)

Vue项目卡顿慢加载?这些优化技巧告诉你!(一):https://developer.aliyun.com/article/1415073

pdf插件优化

项目中有pdf预览的功能,安装了pdfjs-distvue-pdf两个插件,后来跟后端协商,走文件流的方式了, 就没用到这两个, 就卸载了, 如果谁有相关方案,欢迎来提

moment.js的优化

如果时间充裕,建议换成day.js 大小只有6kb, 但是我们项目里面用moment地方太多了,且比较混乱, 就暂时先不更换, 采用剔除其他语言包的方案

方案一

const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
module.exports = {
  configureWebpack: {
    plugins: [
       new MomentLocalesPlugin({
           // 保留一个
            localesToKeep: ['zh-cn'],
        }),
    ]
  }
}
//使用
import moment from 'moment';
// 按需加载需要引入对应的语言包
import 'moment/locale/zh-cn';
moment.locale('zh-cn');

方案二

const webpack = require('webpack');
module.exports = {
  //...
  plugins: [
    // 忽略 moment.js的所有本地文件
    new webpack.IgnorePlugin(/^./locale$/, /moment$/),
  ],
};
// 使用
import moment from 'moment';
// 按需加载需要引入对应的语言包
import 'moment/locale/zh-cn';
moment.locale('zh-cn');

针对lodash库优化

项目中有时会安装lodash,但一般只使用几个方法, 在打包的时候,会发现会将lodash全部打进去, 所以使用下面这两个库

  • babel-plugin-lodash 用来精简Lodash模块的,只保留用到的方法。
  • lodash-webpack-plugin 这个插件经过用noop, identity, 或其余更简单的替代品来替换一些模块的特性,使得打包后的体积更小(翻译)。
    注意:这个插件默认会关闭一些lodash不经常使用的特性,能够给插件传递options来开启某些特性
modules.exports = {
  // 其余配置省略...
  plugins: ['lodash']
}
// vue.config.js
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
module.exports = {
  // ...
  configureWebpack: {
    plugins: [
      new LodashModuleReplacementPlugin()
    ]
  }
}
// 或者chainWebpack 但是我觉得这种写法,有点一言难尽
module.exports = {
  chainWebpack: config => {
    config.plugin("loadshReplace")
     .use(new LodashModuleReplacementPlugin());
   }
}

注意: 这个插件可能带来一些意想不到的坑, 可能会导致使用第三方插件报错出现一些其他问题,具体可以参考下这篇文章 zhuanlan.zhihu.com/p/349260482

开启 Tree Shaking 功能

在前面的依赖视图分析中可以看到sailfish 这个依赖,如下图,它是我们公司以前封装的UI库,它是以源码的方式供项目使用, 没有打包. 老项目里面用了几个组件,打包的时候发现还是全部打进来了

优化方式有以下几个点

  1. 按需加载:在需要使用这个 UI 库的组件时再进行动态加载,不在打包时将整个库全部打入。
  2. 开启 Tree Shaking:如果你使用的是 ES6 模块化的方式引入这个 UI 库,并且使用了相关的工具(如 webpack),则可以开启 Tree Shaking 功能,只将你用到的组件打入打包文件中,未使用的组件将会被去除。
  3. 使用 babel-plugin-import 插件:有些 UI 库将所有的组件都导出为一个模块,对于这种情况,你可以使用 babel-plugin-import 插件,通过按需加载的方式只加载你使用的组件,而不是全部导入。
  4. 自己打包:如果这个 UI 库的源码是开放的,而且你只想使用部分组件,那么你也可以自己将需要的组件单独打包,而不是全部打包。

因为后期规划要替换掉它,所以不想在它上面浪费过多精力

其他的优化

externals

externals配置项用来告诉Webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack在打包时可以忽略它们

一般是将体积较大的第三方包抽离为externals,一般处理element-uivue或者其他的,看自己项目

// vue.config.js
module.exports = {
    configureWebpack: {
        externals: {
        //  安装的包名  --- 暴露的全局变量的值
            "element-ui": "ELEMENT",
            echarts: "echarts",
            vue: "Vue",
        },
    },
}

然后在index.html引入对应的cnd链接, 如果害怕cdn不稳定,可以去下载下来,copy到自己的项目中,手动引入, 也可使用webpack配置注入进去

// vue.config.js
module.exports = {
    chainWebpack: config => {
        config.plugin('html').tap(args => {
          args[0].cdn = {
            js: [
              'https://xx.com/CDN/js/index-element-ui@2.13.0.js',
            ],
            css: [
              'https://xx.com/CDN/css/element-ui2.13.0/index.css',
            ],
          };
          return args;
        });
    }
}
// 使用
<!DOCTYPE html>
<html lang="zh">
  <head>
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
    <% } %>
    <!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>" type="text/javascript"></script>
    <% } %>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
</html>

注意

  • externals:声明文件被外部引用不用打包,不参与打包流程,由于直接写死在html里,可以使用cdn等加速
  • externals缺点:直接html内引入的,所以不会有treeshaking,按需引入等,具体看自己取舍

推荐常用的两个cdn服务 BootCDN 与 cdnjs 。

移除 preload(预载) 与 prefetch (预取)

vue 脚手架默认开启了 preload 与 prefetch,当我们项目很大时,会造成首屏加载速度慢的元凶

preload 与 prefetch 都是一种资源预加载机制; preload 是预先加载资源,但并不执行,只有需要时才执行它; prefetch 是意图预获取一些资源,以备下一个导航/页面使用; preload 的优先级高于 prefetch。

// vue.config.js
chainWebpack: config => {
    // 移除 preload(预载) 插件
    config.plugins.delete('preload')
    // 移除 prefetch(预取) 插件
    config.plugins.delete('prefetch')
  }

主要关注首屏速度, 可自行去体验下关闭前后的效果

清除log等调试信息

使用 terser-webpack-plugin 清除 console.log

先安装依赖
npm install terser-webpack-plugin --save-dev
然后配置
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
  configureWebpack: config => {
    // 生产环境下清除 console.log
    if (process.env.NODE_ENV === 'production') {
      return {
        optimization: {
          minimizer: [
            new TerserPlugin({
              sourceMap: false,
              terserOptions: {
                compress: {
                  drop_console: true
                }
              }
            })
          ]
        }
      }
    }
  }
}

分包拆包

一般拆包原则如下

  • 将变动的与不易变动的资源进行分离 —> 有效利用缓存;* 将 node_modules 中的资源拆分出来,如果 node_modules 中的资源不变,就可以有效利用缓存,避免受到业务代码频繁改动的影响;
  • 将大的拆分成若干个小的 chunk —> 缩短单个资源下载时间;
  • 将公共模块抽离出来 —> 避免资源被重复打包,这样也可以在一定程度上减小打包产物总体积;
  • 将被多个 chunk 引用的包拆分成单独的模块;

要根据项目情况灵活配置,我就贴一个我在项目里使用的

// vue.config.js
module.exports = {
    chainWebpack(config) {
      config.when(process.env.NODE_ENV !== 'development',config => {
                    config
                        .optimization.splitChunks({
                            chunks: 'all',
                            cacheGroups: {
                                libs: {
                                    name: 'chunk-libs',
                                    test: /[\/]node_modules[\/]/,
                                    priority: 10,
                                    chunks: 'initial' // only package third parties that are initially dependent
                                },
                                elementUI: {
                                    name: 'chunk-elementUI', // split elementUI into a single package
                                    priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                                    test: /[\/]node_modules[\/]_?element-ui(.*)/ // in order to adapt to cnpm
                                },
                                commons: {
                                    name: 'chunk-commons',
                                    test: resolve('src/components'), // can customize your rules
                                    minChunks: 3, //  minimum common number
                                    priority: 5,
                                    reuseExistingChunk: true
                                }
                            }
                        })
                    // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
                    config.optimization.runtimeChunk('single')
                }
            )
    }
}

压缩图片

项目里面后期肯定会放不少图片进去, 这些图片如果不压缩以下,占的资源就会非常大,社区里面有不少插件可以进行压缩,但我个人还是很喜欢熊猫压缩

推荐大家使用. 可以整个文件夹丢进去

结束语

一般常用的就这些,当然还有很多其他的优化方案, 这里没有绝对的最佳配置,只有最佳实践,大家根据自己的项目实际情况,逐步分析优化.

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库  web前端面试题库 VS java后端面试题库大全

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
相关文章
|
8天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
8天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
8天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
7天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
7天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
|
22天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
8天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
9天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
9天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
14天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发