vue优化_vue优化方案 - CSDN
精华内容
参与话题
  • Vue 项目性能优化方案

    千次阅读 2019-08-23 10:01:29
    Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。本文是作者通过实际项目的优化实践进行总结而来,希.....

     

    前言

    Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM;但 Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。本文是作者通过实际项目的优化实践进行总结而来,希望读者读完本文,有一定的启发思考,从而对自己的项目进行优化起到帮助。本文内容分为以下三部分组成:

    • Vue 代码层面的优化;

    • webpack 配置层面的优化;

    • 基础的 Web 技术层面的优化。

     

    一、代码层面的优化

    1.1、v-if 和 v-show 区分使用场景

    v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

    v-show 就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。

    所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

    1.2、computed 和 watch  区分使用场景

    computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed  的值;

    watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

    运用场景:

    • 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;

    • 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

    1.3、v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

    (1)v-for 遍历必须为 item 添加 key

    在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。

    (2)v-for 遍历避免同时使用 v-if

    v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。

    推荐:

    <ul>  <li    v-for="user in activeUsers"    :key="user.id">    {{ user.name }}  </li></ul>computed: {  activeUsers: function () {    return this.users.filter(function (user) {   return user.isActive    })  }}

    不推荐:

    <ul>  <li    v-for="user in users"    v-if="user.isActive"    :key="user.id">    {{ user.name }}  </li></ul>

    1.4、长列表性能优化

    Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

    export default {  data: () => ({    users: {}  }),  async created() {    const users = await axios.get("/api/users");    this.users = Object.freeze(users);  }};

    1.5、事件的销毁

    Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。如果在 js 内

    created() {  addEventListener('click', this.click, false)},beforeDestroy() {  removeEventListener('click', this.click, false)}

    1.6、图片资源懒加载

    对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件:

    (1)安装插件

     

    npm install vue-lazyload --save-dev

    (2)在入口文件 man.js 中引入并使用

     

    import VueLazyload from 'vue-lazyload'

    然后再 vue 中直接使用

     

    Vue.use(VueLazyload)

    或者添加自定义选项

    Vue.use(VueLazyload, {preLoad: 1.3,error: 'dist/error.png',loading: 'dist/loading.gif',attempt: 1})

    (3)在 vue 文件中将 img 标签的 src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示:

     

    <img v-lazy="/static/img/1.png">

    以上为 vue-lazyload 插件的简单使用,如果要看插件的更多参数选项,可以查看 vue-lazyload 的 github 地址。

    1.7、路由懒加载

    Vue  是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。

    路由懒加载:

    const Foo = () => import('./Foo.vue')const router = new VueRouter({  routes: [    { path: '/foo', component: Foo }  ]})

    1.8、第三方插件的按需引入

    我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。以下为项目中引入 element-ui 组件库为例:

    (1)首先,安装 babel-plugin-component :

     

    npm install babel-plugin-component -D

    (2)然后,将 .babelrc 修改为:

    {  "presets": [["es2015", { "modules": false }]],  "plugins": [    [      "component",      {        "libraryName": "element-ui",        "styleLibraryName": "theme-chalk"      }    ]  ]}

    (3)在 main.js 中引入部分组件:

    import Vue from 'vue';import { Button, Select } from 'element-ui';
     Vue.use(Button) Vue.use(Select)

    1.9、优化无限列表性能

    如果你的应用存在非常长或者无限滚动的列表,那么需要采用 窗口化 的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。你可以参考以下开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller  来优化这种无限列表的场景的。

    1.10、服务端渲染 SSR or 预渲染

    服务端渲染是指 Vue 在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的 html 片段直接返回给客户端这个过程就叫做服务端渲染。

    (1)服务端渲染的优点:

    • 更好的 SEO:因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;

    • 更快的内容到达时间(首屏加载更快):SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;

    (2)服务端渲染的缺点:

    • 更多的开发条件限制:例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;

    • 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源,因此如果你预料在高流量环境下使用,请准备相应的服务器负载,并明智地采用缓存策略。

    如果你的项目的 SEO 和 首屏渲染是评价项目的关键指标,那么你的项目就需要服务端渲染来帮助你实现最佳的初始加载性能和 SEO,具体的 Vue SSR 如何实现,可以参考作者的另一篇文章《Vue SSR 踩坑之旅》。如果你的 Vue 项目只需改善少数营销页面(例如  /, /about, /contact 等)的 SEO,那么你可能需要预渲染,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点,具体你可以使用 prerender-spa-plugin 就可以轻松地添加预渲染 。

     

    二、Webpack 层面的优化

    2.1、Webpack 对图片进行压缩

    在 vue 项目中除了可以在 webpack.base.conf.js 中 url-loader 中设置 limit 大小来对图片处理,对小于 limit 的图片转化为 base64 格式,其余的不做操作。所以对有些较大的图片资源,在请求资源的时候,加载会很慢,我们可以用 image-webpack-loader来压缩图片:

    (1)首先,安装 image-webpack-loader  :

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

    (2)然后,在 webpack.base.conf.js  中进行配置:

    {  test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,  use:[    {    loader: 'url-loader',    options: {      limit: 10000,      name: utils.assetsPath('img/[name].[hash:7].[ext]')      }    },    {      loader: 'image-webpack-loader',      options: {        bypassOnDebug: true,      }    }  ]}

    2.2、减少 ES6 转为 ES5 的冗余代码

    Babel 插件会在将 ES6 代码转换成 ES5 代码时会注入一些辅助函数,例如下面的 ES6 代码:

    class HelloWebpack extends Component{...}

    这段代码再被转换成能正常运行的 ES5 代码时需要以下两个辅助函数:

     

    babel-runtime/helpers/createClass  // 用于实现 class 语法babel-runtime/helpers/inherits  // 用于实现 extends 语法

    在默认情况下, Babel 会在每个输出文件中内嵌这些依赖的辅助函数代码,如果多个源代码文件都依赖这些辅助函数,那么这些辅助函数的代码将会出现很多次,造成代码冗余。为了不让这些辅助函数的代码重复出现,可以在依赖它们时通过 require('babel-runtime/helpers/createClass') 的方式导入,这样就能做到只让它们出现一次。babel-plugin-transform-runtime 插件就是用来实现这个作用的,将相关辅助函数进行替换成导入语句,从而减小 babel 编译出来的代码的文件大小。

    (1)首先,安装 babel-plugin-transform-runtime :

     

    npm install babel-plugin-transform-runtime --save-dev

    (2)然后,修改 .babelrc  配置文件为:

    "plugins": [    "transform-runtime"]

    如果要看插件的更多详细内容,可以查看babel-plugin-transform-runtime 的 详细介绍。

    2.3、提取公共代码

    如果项目中没有去将每个页面的第三方库和公共模块提取出来,则项目会存在以下问题:

    • 相同的资源被重复加载,浪费用户的流量和服务器的成本。

    • 每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验。

    所以我们需要将多个页面的公共代码抽离成单独的文件,来优化以上问题 。Webpack 内置了专门用于提取多个Chunk 中的公共部分的插件 CommonsChunkPlugin,我们在项目中 CommonsChunkPlugin 的配置如下:

    // 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。new webpack.optimize.CommonsChunkPlugin({  name: 'vendor',  minChunks: function(module, count) {    return (      module.resource &&      /\.js$/.test(module.resource) &&      module.resource.indexOf(        path.join(__dirname, '../node_modules')      ) === 0    );  }}),// 抽取出代码模块的映射关系new webpack.optimize.CommonsChunkPlugin({  name: 'manifest',  chunks: ['vendor']})

    如果要看插件的更多详细内容,可以查看 CommonsChunkPlugin 的 详细介绍。

    2.4、模板预编译

    当使用 DOM 内模板或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。通常情况下这个过程已经足够快了,但对性能敏感的应用还是最好避免这种用法。

    预编译模板最简单的方式就是使用单文件组件——相关的构建设置会自动把预编译处理好,所以构建好的代码已经包含了编译出来的渲染函数而不是原始的模板字符串。

    如果你使用 webpack,并且喜欢分离 JavaScript 和模板文件,你可以使用 vue-template-loader,它也可以在构建过程中把模板文件转换成为 JavaScript 渲染函数。

    2.5、提取组件的 CSS

    当使用单文件组件时,组件内的 CSS 会以 style 标签的方式通过 JavaScript 动态注入。这有一些小小的运行时开销,如果你使用服务端渲染,这会导致一段 “无样式内容闪烁 (fouc) ” 。将所有组件的 CSS 提取到同一个文件可以避免这个问题,也会让 CSS 更好地进行压缩和缓存。

    查阅这个构建工具各自的文档来了解更多:

    • webpack + vue-loader ( vue-cli 的 webpack 模板已经预先配置好)

    • Browserify + vueify

    • Rollup + rollup-plugin-vue

    2.6、优化 SourceMap

    我们在项目进行打包后,会将开发中的多个文件代码打包到一个文件中,并且经过压缩、去掉多余的空格、babel编译化后,最终将编译得到的代码会用于线上环境,那么这样处理后的代码和源代码会有很大的差别,当有 bug的时候,我们只能定位到压缩处理后的代码位置,无法定位到开发环境中的代码,对于开发来说不好调式定位问题,因此 sourceMap 出现了,它就是为了解决不好调式代码问题的。

    SourceMap 的可选值如下(+ 号越多,代表速度越快,- 号越多,代表速度越慢, o 代表中等速度 )

    开发环境推荐:cheap-module-eval-source-map

    生产环境推荐:cheap-module-source-map

    原因如下:

    • cheap:源代码中的列信息是没有任何作用,因此我们打包后的文件不希望包含列相关信息,只有行信息能建立打包前后的依赖关系。因此不管是开发环境或生产环境,我们都希望添加 cheap 的基本类型来忽略打包前后的列信息;

    • module :不管是开发环境还是正式环境,我们都希望能定位到bug的源代码具体的位置,比如说某个 Vue 文件报错了,我们希望能定位到具体的 Vue 文件,因此我们也需要 module 配置;

    • soure-map :source-map 会为每一个打包后的模块生成独立的 soucemap 文件 ,因此我们需要增加source-map 属性;

    • eval-source-map:eval 打包代码的速度非常快,因为它不生成 map 文件,但是可以对 eval 组合使用 eval-source-map 使用会将 map 文件以 DataURL 的形式存在打包后的 js 文件中。在正式环境中不要使用 eval-source-map, 因为它会增加文件的大小,但是在开发环境中,可以试用下,因为他们打包的速度很快。

    2.7、构建结果输出分析

    Webpack 输出的代码可读性非常差而且文件非常大,让我们非常头疼。为了更简单、直观地分析输出结果,社区中出现了许多可视化分析工具。这些工具以图形的方式将结果更直观地展示出来,让我们快速了解问题所在。接下来讲解我们在 Vue 项目中用到的分析工具:webpack-bundle-analyzer 。

    我们在项目中 webpack.prod.conf.js 进行配置:

    if (config.build.bundleAnalyzerReport) {  var BundleAnalyzerPlugin =   require('webpack-bundle-analyzer').BundleAnalyzerPlugin;  webpackConfig.plugins.push(new BundleAnalyzerPlugin());}

    执行  $ npm run build --report  后生成分析报告如下:

    2.8、Vue 项目的编译优化

    如果你的 Vue 项目使用 Webpack 编译,需要你喝一杯咖啡的时间,那么也许你需要对项目的 Webpack 配置进行优化,提高 Webpack 的构建效率。具体如何进行 Vue 项目的 Webpack 构建优化,可以参考作者的另一篇文章《 Vue 项目 Webpack 优化实践》

     

    三、基础的 Web 技术优化

    3.1、开启 gzip 压缩

    gzip 是 GNUzip 的缩写,最早用于 UNIX 系统的文件压缩。HTTP 协议上的 gzip 编码是一种用来改进 web 应用程序性能的技术,web 服务器和客户端(浏览器)必须共同支持 gzip。目前主流的浏览器,Chrome,firefox,IE等都支持该协议。常见的服务器如 Apache,Nginx,IIS 同样支持,gzip 压缩效率非常高,通常可以达到 70% 的压缩率,也就是说,如果你的网页有 30K,压缩之后就变成了 9K 左右

    以下我们以服务端使用我们熟悉的 express 为例,开启 gzip 非常简单,相关步骤如下:

    • 安装:

    npm install compression --save
    • 添加代码逻辑:

    var compression = require('compression');var app = express();app.use(compression())
    • 重启服务,观察网络面板里面的 response header,如果看到如下红圈里的字段则表明 gzip 开启成功 :

       

       

    3.2、浏览器缓存

    为了提高用户加载页面的速度,对静态资源进行缓存是非常必要的,根据是否需要重新向服务器发起请求来分类,将 HTTP 缓存规则分为两大类(强制缓存,对比缓存),如果对缓存机制还不是了解很清楚的,可以参考作者写的关于 HTTP 缓存的文章《深入理解HTTP缓存机制及原理》,这里不再赘述。

    3.3、CDN 的使用

    浏览器从服务器上下载 CSS、js 和图片等文件时都要和服务器连接,而大部分服务器的带宽有限,如果超过限制,网页就半天反应不过来。而 CDN 可以通过不同的域名来加载文件,从而使下载文件的并发连接数大大增加,且CDN 具有更好的可用性,更低的网络延迟和丢包率 。

    3.4、使用 Chrome Performance 查找性能瓶颈

    Chrome 的 Performance 面板可以录制一段时间内的 js 执行细节及时间。使用 Chrome 开发者工具分析页面性能的步骤如下。

    1. 打开 Chrome 开发者工具,切换到 Performance 面板

    2. 点击 Record 开始录制

    3. 刷新页面或展开某个节点

    4. 点击 Stop 停止录制

     

     

     

     

     

    展开全文
  • 史上最全vue优化方案

    2020-06-19 09:43:45
    博主自家公司的vue项目已经上线将近一年了,最近一直在网上找优化方案,发现许多人写的比较笼统,今天特意整理了一些方案,供自己以后方便查看,也方便大家查看。 Vue框架的优点:Vue 框架通过数据双向绑定和虚拟 ...

    博主自家公司的vue项目已经上线将近一年了,最近一直在网上找优化方案,发现许多人写的比较笼统,今天特意整理了一些方案,供自己以后方便查看,也方便大家查看。

    Vue框架的优点:Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM

    Vue框架的不足: Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题,所以我们仍然需要去关注 Vue 项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。

    项目优化主要分为三个大的方面:(一)Vue 代码层面的优化(二)webpack 配置层面的优化(三)基础的 Web 技术层面的优化。

    一、代码层面的优化

    1.1、v-if 和 v-show 区分使用场景
    v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

    v-show 就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。

    所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

    1.2、computed 和 watch 区分使用场景
    computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

    watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

    运用场景:

    当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;

    当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

    1.3、v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
    (1)v-for 遍历必须为 item 添加 key

    在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。

    (2)v-for 遍历避免同时使用 v-if

    v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。

    推荐:

    <ul>
      <li
        v-for="user in activeUsers"
        :key="user.id">
        {{ user.name }}
      </li>
    </ul>
    computed: {
      activeUsers: function () {
        return this.users.filter(function (user) {
       return user.isActive
        })
      }
    }
    

    不推荐:

    <ul>
      <li
        v-for="user in users"
        v-if="user.isActive"
        :key="user.id">
        {{ user.name }}
      </li>
    </ul>
    

    1.4、长列表性能优化
    Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

    export default {
      data: () => ({
        users: {}
      }),
      async created() {
        const users = await axios.get("/api/users");
        this.users = Object.freeze(users);
      }
    };
    

    1.5、事件的销毁
    Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。如果在 js 内

    created() {
      addEventListener('click', this.click, false)
    },
    beforeDestroy() {
      removeEventListener('click', this.click, false)
    }
    

    1.6、图片资源懒加载
    对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件:

    (1)安装插件

    npm install vue-lazyload --save-dev
    

    (2)在入口文件 man.js 中引入并使用

    import VueLazyload from 'vue-lazyload'
    

    然后再 vue 中直接使用

    Vue.use(VueLazyload)
    

    或者添加自定义选项

    Vue.use(VueLazyload, {
    preLoad: 1.3,
    error: 'dist/error.png',
    loading: 'dist/loading.gif',
    attempt: 1
    })
    

    (3)在 vue 文件中将 img 标签的 src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示:

    <img v-lazy="/static/img/1.png">
    

    以上为 vue-lazyload 插件的简单使用,如果要看插件的更多参数选项,可以查看 vue-lazyload 的 github 地址。

    1.7、路由懒加载
    Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。

    路由懒加载:

    const Foo = () => import('./Foo.vue')
    const router = new VueRouter({
      routes: [
        { path: '/foo', component: Foo }
      ]
    })
    

    1.8、第三方插件的按需引入
    我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。以下为项目中引入 element-ui 组件库为例:

    (1)首先,安装 babel-plugin-component :

    npm install babel-plugin-component -D
    

    (2)然后,将 .babelrc 修改为:

    {
      "presets": [["es2015", { "modules": false }]],
      "plugins": [
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    

    (3)在 main.js 中引入部分组件:

    import Vue from 'vue';
    import { Button, Select } from 'element-ui';
    
     Vue.use(Button)
     Vue.use(Select)
    

    1.9、优化无限列表性能
    如果你的应用存在非常长或者无限滚动的列表,那么需要采用 窗口化 的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。你可以参考以下开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller 来优化这种无限列表的场景的。

    1.10、服务端渲染 SSR or 预渲染
    服务端渲染是指 Vue 在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的 html 片段直接返回给客户端这个过程就叫做服务端渲染。

    (1)服务端渲染的优点:

    更好的 SEO:因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;

    更快的内容到达时间(首屏加载更快):SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;

    (2)服务端渲染的缺点:

    更多的开发条件限制:例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;

    更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源,因此如果你预料在高流量环境下使用,请准备相应的服务器负载,并明智地采用缓存策略。

    如果你的项目的 SEO 和 首屏渲染是评价项目的关键指标,那么你的项目就需要服务端渲染来帮助你实现最佳的初始加载性能和 SEO,具体的 Vue SSR 如何实现,可以参考作者的另一篇文章《Vue SSR 踩坑之旅》。如果你的 Vue 项目只需改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点,具体你可以使用 prerender-spa-plugin 就可以轻松地添加预渲染 。

    二、Webpack 层面的优化

    2.1、Webpack 对图片进行压缩
    在 vue 项目中除了可以在 webpack.base.conf.js 中 url-loader 中设置 limit 大小来对图片处理,对小于 limit 的图片转化为 base64 格式,其余的不做操作。所以对有些较大的图片资源,在请求资源的时候,加载会很慢,我们可以用 image-webpack-loader来压缩图片:

    (1)首先,安装 image-webpack-loader :

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

    (2)然后,在 webpack.base.conf.js 中进行配置:

    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      use:[
        {
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
          }
        },
        {
          loader: 'image-webpack-loader',
          options: {
            bypassOnDebug: true,
          }
        }
      ]
    }
    

    2.2、减少 ES6 转为 ES5 的冗余代码
    Babel 插件会在将 ES6 代码转换成 ES5 代码时会注入一些辅助函数,例如下面的 ES6 代码:

    class HelloWebpack extends Component{…}
    这段代码再被转换成能正常运行的 ES5 代码时需要以下两个辅助函数:

    babel-runtime/helpers/createClass  // 用于实现 class 语法
    babel-runtime/helpers/inherits  // 用于实现 extends 语法
    

    在默认情况下, Babel 会在每个输出文件中内嵌这些依赖的辅助函数代码,如果多个源代码文件都依赖这些辅助函数,那么这些辅助函数的代码将会出现很多次,造成代码冗余。为了不让这些辅助函数的代码重复出现,可以在依赖它们时通过 require(‘babel-runtime/helpers/createClass’) 的方式导入,这样就能做到只让它们出现一次。babel-plugin-transform-runtime 插件就是用来实现这个作用的,将相关辅助函数进行替换成导入语句,从而减小 babel 编译出来的代码的文件大小。

    (1)首先,安装 babel-plugin-transform-runtime :

    npm install babel-plugin-transform-runtime --save-dev
    

    (2)然后,修改 .babelrc 配置文件为:

    "plugins": [
        "transform-runtime"
    ]
    

    如果要看插件的更多详细内容,可以查看babel-plugin-transform-runtime 的 详细介绍。

    2.3、提取公共代码
    如果项目中没有去将每个页面的第三方库和公共模块提取出来,则项目会存在以下问题:

    (一)相同的资源被重复加载,浪费用户的流量和服务器的成本。

    (二)每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验。

    所以我们需要将多个页面的公共代码抽离成单独的文件,来优化以上问题 。Webpack 内置了专门用于提取多个Chunk 中的公共部分的插件 CommonsChunkPlugin,我们在项目中 CommonsChunkPlugin 的配置如下:

    // 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function(module, count) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        );
      }
    }),
    // 抽取出代码模块的映射关系
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    })
    

    如果要看插件的更多详细内容,可以查看 CommonsChunkPlugin 的 详细介绍。

    2.4、模板预编译
    当使用 DOM 内模板或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。通常情况下这个过程已经足够快了,但对性能敏感的应用还是最好避免这种用法。

    预编译模板最简单的方式就是使用单文件组件——相关的构建设置会自动把预编译处理好,所以构建好的代码已经包含了编译出来的渲染函数而不是原始的模板字符串。

    如果你使用 webpack,并且喜欢分离 JavaScript 和模板文件,你可以使用 vue-template-loader,它也可以在构建过程中把模板文件转换成为 JavaScript 渲染函数。

    2.5、提取组件的 CSS
    当使用单文件组件时,组件内的 CSS 会以 style 标签的方式通过 JavaScript 动态注入。这有一些小小的运行时开销,如果你使用服务端渲染,这会导致一段 “无样式内容闪烁 (fouc) ” 。将所有组件的 CSS 提取到同一个文件可以避免这个问题,也会让 CSS 更好地进行压缩和缓存。

    查阅这个构建工具各自的文档来了解更多:

    webpack + vue-loader ( vue-cli 的 webpack 模板已经预先配置好)

    Browserify + vueify

    Rollup + rollup-plugin-vue

    2.6、优化 SourceMap
    我们在项目进行打包后,会将开发中的多个文件代码打包到一个文件中,并且经过压缩、去掉多余的空格、babel编译化后,最终将编译得到的代码会用于线上环境,那么这样处理后的代码和源代码会有很大的差别,当有 bug的时候,我们只能定位到压缩处理后的代码位置,无法定位到开发环境中的代码,对于开发来说不好调式定位问题,因此 sourceMap 出现了,它就是为了解决不好调式代码问题的。

    SourceMap 的可选值如下(+ 号越多,代表速度越快,- 号越多,代表速度越慢, o 代表中等速度 )

    开发环境推荐:cheap-module-eval-source-map

    生产环境推荐:cheap-module-source-map

    原因如下:

    cheap:源代码中的列信息是没有任何作用,因此我们打包后的文件不希望包含列相关信息,只有行信息能建立打包前后的依赖关系。因此不管是开发环境或生产环境,我们都希望添加 cheap 的基本类型来忽略打包前后的列信息;

    module :不管是开发环境还是正式环境,我们都希望能定位到bug的源代码具体的位置,比如说某个 Vue 文件报错了,我们希望能定位到具体的 Vue 文件,因此我们也需要 module 配置;

    soure-map :source-map 会为每一个打包后的模块生成独立的 soucemap 文件 ,因此我们需要增加source-map 属性;

    eval-source-map:eval 打包代码的速度非常快,因为它不生成 map 文件,但是可以对 eval 组合使用 eval-source-map 使用会将 map 文件以 DataURL 的形式存在打包后的 js 文件中。在正式环境中不要使用 eval-source-map, 因为它会增加文件的大小,但是在开发环境中,可以试用下,因为他们打包的速度很快。

    2.7、构建结果输出分析
    Webpack 输出的代码可读性非常差而且文件非常大,让我们非常头疼。为了更简单、直观地分析输出结果,社区中出现了许多可视化分析工具。这些工具以图形的方式将结果更直观地展示出来,让我们快速了解问题所在。接下来讲解我们在 Vue 项目中用到的分析工具:webpack-bundle-analyzer 。

    我们在项目中 webpack.prod.conf.js 进行配置:

    if (config.build.bundleAnalyzerReport) {
      var BundleAnalyzerPlugin =   require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
      webpackConfig.plugins.push(new BundleAnalyzerPlugin());
    }
    

    2.8、Vue 项目的编译优化
    如果你的 Vue 项目使用 Webpack 编译,需要你喝一杯咖啡的时间,那么也许你需要对项目的 Webpack 配置进行优化,提高 Webpack 的构建效率。具体如何进行 Vue 项目的 Webpack 构建优化,可以参考作者的另一篇文章《 Vue 项目 Webpack 优化实践》

    三、基础的 Web 技术优化

    3.1、开启 gzip 压缩
    gzip 是 GNUzip 的缩写,最早用于 UNIX 系统的文件压缩。HTTP 协议上的 gzip 编码是一种用来改进 web 应用程序性能的技术,web 服务器和客户端(浏览器)必须共同支持 gzip。目前主流的浏览器,Chrome,firefox,IE等都支持该协议。常见的服务器如 Apache,Nginx,IIS 同样支持,gzip 压缩效率非常高,通常可以达到 70% 的压缩率,也就是说,如果你的网页有 30K,压缩之后就变成了 9K 左右

    以下我们以服务端使用我们熟悉的 express 为例,开启 gzip 非常简单,相关步骤如下:

    安装:

    npm install compression --save
    

    添加代码逻辑:

    var compression = require('compression');
    var app = express();
    app.use(compression())
    

    重启服务,观察网络面板里面的 response header

    3.2、浏览器缓存
    为了提高用户加载页面的速度,对静态资源进行缓存是非常必要的,根据是否需要重新向服务器发起请求来分类,将 HTTP 缓存规则分为两大类(强制缓存,对比缓存),如果对缓存机制还不是了解很清楚的,可以参考作者写的关于 HTTP 缓存的文章《深入理解HTTP缓存机制及原理》,这里不再赘述。

    3.3、CDN 的使用
    浏览器从服务器上下载 CSS、js 和图片等文件时都要和服务器连接,而大部分服务器的带宽有限,如果超过限制,网页就半天反应不过来。而 CDN 可以通过不同的域名来加载文件,从而使下载文件的并发连接数大大增加,且CDN 具有更好的可用性,更低的网络延迟和丢包率 。

    3.4、使用 Chrome Performance 查找性能瓶颈
    Chrome 的 Performance 面板可以录制一段时间内的 js 执行细节及时间。使用 Chrome 开发者工具分析页面性能的步骤如下。

    打开 Chrome 开发者工具,切换到 Performance 面板

    点击 Record 开始录制

    刷新页面或展开某个节点

    展开全文
  • Vue项目前端性能优化

    千次阅读 2019-04-02 19:29:50
    一、vue-router路由懒加载 懒加载是当路由被访问的时候才加载对应组件,而不是在首页就全部加载,以此来提高首页反应速度。 方法和原理 require-ensure 说明: require.ensure在需要的时候才下载依赖的模块,当...

    一、vue-router路由懒加载

    懒加载是当路由被访问的时候才加载对应组件,而不是在首页就全部加载,以此来提高首页反应速度。

    • 方法和原理
    • require-ensure 
    • 说明: require.ensure在需要的时候才下载依赖的模块,当参数指定的模块都下载下来了(下载下来的模块还没执行),便执行参数指定的回调函数。require.ensure会创建一个chunk,且可以指定该chunk的名称,如果这个chunk名已经存在了,则将本次依赖的模块合并到已经存在的chunk中,最后这个chunk在webpack构建的时候会单独生成一个文件。
    • 语法: require.ensure(dependencies: String[], callback: function([require]), [chunkName: String]) 
      • dependencies: 依赖的模块数组
      • callback: 回调函数,该函数调用时会传一个require参数
      • chunkName: 模块名,用于构建时生成文件时命名使用
    • 注意点:require.ensure的模块只会被下载下来,不会被执行,只有在回调函数使用require(模块名)后,这个模块才会被执行。

    示例:

    二、打包优化——工程文件打包的时候不生成.map文件

    npm run build编译之后,我们查看编译生成的文件,发现有很多.map文件,这些文件占了不小的空间。.map文件的作用是帮助编译后的代码调试,但是我们上线的代码已经调试完成,所以上线时可以不生成.map文件。

    修改配置文件如下即可:

    三、切换多入口模式

    在vue项目中,我们一般使用vue-cli脚手架搭建单页面的web工程。生成的项目结构如下图所示:

    main.js是整个单页面应用唯一的入口文件

    在大型项目中,单一入口无法满足项目需要,原因有以下两方面:

    (1)单一入口无法拆分按模块独立部署,不够灵活

    (2)单一入口负载过重,业务模块较多时,点击系统导航菜单频繁切换业务模块,在IE浏览器中,浏览器内存持续上涨,达到             1.5G以上卡顿,浏览器容易崩溃。

    基于以上两点原因,大型项目可以采用多入口的模式,好处有以下两点:

    (1)满足页面需要分开部署的场景

    (2)解决了页面卡顿和内存上涨问题

    配置方式参考我的单独讲解多入口配置的博文

    四、使用字体图标代替切图

    字体图标的优势:

    (1)字体图标任意缩放不会失真

    (2)在项目中导入后,以css样式引用,相较于传统的图片大大减少请求数量,优化性能

    (3)修改方便,如需要切换主题色可由css控制,避免视觉反复切图的工作量

    在线生成工具: https://icomoon.io/app/#/select

    五、使用雪碧图

    雪碧图的优点:

    1. 将多张图片合并到一张图片中,可以减小图片的总大小。
    2. 将多张图片合并成一张图片后,下载全部所需的资源,只需一次请求。可以减小建立连接的消耗。

    六、提取公共样式和方法

         1.复用的样式应当提取到公共的样式表中复用

    2.公共的方法应当提取到公共的js中复用

    3.表单验证的提取

    七、控件销毁

    1.页面切换释放:

    使用的C++控件应当及时销毁

    2. $destroy

    完全销毁一个实例,清理它与其它实例的连接,解绑它的全部指令及事件监听器。

     

    八、定时器销毁

    路由离开及时销毁定时器

     

    九、解绑事件

    路由离开及时解绑事件:

    vm.$off()

    十、vue中使用keep-alive

    vue2.0提供了一个keep-alive组件,用来缓存组件,避免多次加载相应的组件,减少性能消耗,但keep-alive是一把双刃剑,确实需要缓存组件的时候才使用。

    <keep-alive>

    <component>

      <!-- 组件将被缓存 -->

    </component>

    </keep-alive>

    十一、代码层面的优化

    1、v-show,v-if 用哪个?

    (1)只要涉及到权限相关的展示无疑要用 v-if

    (2)在没有权限限制时根据用户点击的频次选择,频繁切换的使用 v-show,不频繁切换的使用 v-if(减少页面中 dom 数量)

    2、不要在模板里面写过多的表达式与判断

      v-if="isShow && isAdmin && (a || b)",这种表达式虽说可以识别,但是不是长久之计,当看着不舒服时,适当的写到 methods 和 computed 里面封装成一个方法,这样的好处是方便我们在多处判断相同的表达式,其他权限相同的元素再判断展示的时候调用同一个方法即可。

    3、循环调用子组件时添加 key

      key 可以唯一标识一个循环个体,可以使用例如 item.id 作为 key,假如数组数据是这样的 ['a' , 'b', 'c', 'a'],使用 :key="item" 显然没有意义,更好的办法就是在循环的时候 (item, index) in arr,然后 :key="index"来确保key 的唯一性。不设置key值时vue会抛出警告。

    4、遵守编码规范

    语义化标签,避免乱嵌套,合理命名属性,使用高效简洁的css选择器等等

    5、合理利用vue生命周期

    减少在created生命周期中做ajax请求,而是放在mounted生命周期中,以不阻塞页面生成dom

    十二、iframe的内存释放

    相关资料称IEiframe元素的回收方面存在着bug,需要手动将其释放以避免内存泄漏

    释放方法:手动将iframe指向置空

     

    展开全文
  • vue项目性能优化方案

    2020-10-17 15:47:38
    优化前准备: 首先我们需要先排查影响性能、导致打包资源文件过大的原因,以及代码的使用率 webpack-bundle-analyzer: npm install webpack-bundle-analyzer // vue.config.js文件(vue cli3根目录下的文件,...

    背景
    项目采用vue cli3搭建,集成前端组件以及地图效果,导致项目打包后资源包文件特别大,打包速度慢,首屏渲染耗时长,甚至出现左右界面图表数据不渲染的问题。

    优化前准备
    首先我们需要先排查影响性能、导致打包资源文件过大的原因,以及代码的使用率

    • webpack-bundle-analyzer:
    npm install webpack-bundle-analyzer
    
    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    
    module.exports = {
        chainWebpack: config => {
            /* 添加分析工具 */
            if (process.env.NODE_ENV === 'production') {
                if (process.env.npm_config_report) {
                    config
                        .plugin('webpack-bundle-analyzer')
                        // eslint-disable-next-line global-require
                        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
                        .end();
                    config.plugins.delete('prefetch');
                }
            }
        },
    };
    

    通过命令 npm run build --report 会在打包完成后本地启动一个服务,自动打开127.0.0.1:8888网页,可以查看打包后各个依赖包占用的资源大小,我们可以针对各个依赖包的相关大小作出体积的优化,如果开源库过大可以考虑按需引入,不要全部引入,如果是自己公司封装的私有组件库、类库,可以排查哪部分占用文件过大,打包进行优化处理,如下图:
    在这里插入图片描述
    在这里插入图片描述

    • coverage:
      通过打开控制台(F12),ctrl+shift+p,搜索coverage,然后选中,然后点击开始录制,之后做一些操作,比如刷新界面,开始录制,查看我们代码的实际使用率,也可以点击文件查看这个文件中具体未使用的那段代码(红色部分)
      在这里插入图片描述
      在这里插入图片描述
      优化方案:
    • gzip压缩:gzip压缩可以特别明显的提高我们的代码加载效果,提升效率5-6倍左右,它会把诸如js、css等文件进行压缩,并且让我们在加载时去请求那些gz文件而提升请求效率,这部分可以参考博主的另一篇文章 gzip压缩方案
    • 路由懒加载:实际来说,我们在首页就不需要加载其他路由的文件以及数据,而当我们执行到某个具体路由,再去加载当前路由的才是最正确的方案,所以路由懒加载是我们必须要做的,使用方法如下:

    这里拿home路由举例,博主每个页面都是分为左、右、中上、中下四个模块的,所以每个路由中都有四个组件,当然,路由懒加载写法是一样的,通过箭头函数返回一个组件,webpackChunkName就是最早的打包后的文件名,同一路由可以写同一个名字,推荐写路由名,方便我们知道是哪个路由下的。

    const MainLeft = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainLeft.vue');
    const MainRight = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainRight.vue');
    const MainCenterTop = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainCenterTop.vue');
    const MainCenterBottom = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainCenterBottom.vue');
    

    而在router.js里就是正常写法:

    routes: [
            {
                path: '/',
                name: 'Home',
                title: '首页',
                components: {
                    routerLeft: Home.MainLeft,
                    routerRight: Home.MainRight,
                    routerCenterTop: Home.MainCenterTop,
                    // routerCenterBottom: Home.MainCenterBottom,
                },
            },
    ]
    

    开启路由懒加载后,vue cli3项目还需要在vue.config.js文件中配置如下

    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    module.exports = {
        chainWebpack: config => {
        	// 移除 prefetch 插件(避免会预先加载模块/路由)
            config.plugins.delete('prefetch');
        },
    };
    

    (注:之前博主遇到个小坑,项目中有个文件夹,里面写了一些全局封装并且全局注册的组件供其他页面使用,而有些组件中使用了require去动态加载图片导致打包后路由懒加载不生效没有生成对应路由的文件,大家留意一下即可,如果遇到此问题,可以找博主提供解决思路)

    • 组件库按需引入:这一点不需要过多赘述了,使用了诸如element ui等组件库的话,官网都有很详细的介绍如何按需加载
    • 图片压缩:安装此插件的时候有可能出现部分依赖安装失败,导致压缩失败,可以先卸载此插件然后用cnpm或淘宝源重新安装
    npm install image-webpack-loader
    
    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    module.exports = {
        chainWebpack: config => {
            // 开启图片压缩
            // config.module
            //     .rule('images')
            //     .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
            //     .use('image-webpack-loader')
            //     .loader('image-webpack-loader')
            //     .options({ bypassOnDebug: true });
        },
    };
    
    • map映射文件:vue打包会保留源文件的map映射,方便我们打包部署后依然可以通过控制台的source查看搜索源文件的代码,方便定位问题,但是多生成map文件会导致打包文件过大,所以仁者见仁智者见智,看各位是否需要打包部署后方便定位问题吧,不需要的话可以考虑不生成map文件
    module.exports = {
        productionSourceMap: true,
    }
    
    • 分包加载:vue打包后会把依赖包都打包到app.js文件里,这样会导致单文件过大,请求耗时,加载缓慢,所以可以考虑把各依赖单独拆分打包,实现多个小文件请求加载的方式,代码如下:
    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    module.exports = {
        configureWebpack: {
            optimization: {
                runtimeChunk: 'single',
                splitChunks: {
                    chunks: 'all',
                    maxInitialRequests: Infinity,
                    minSize: 20000,
                    cacheGroups: {
                        vendor: {
                            test: /[\\/]node_modules[\\/]/,
                            name(module) {
                                // get the name. E.g. node_modules/packageName/not/this/part.js
                                // or node_modules/packageName
                                const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
                                // npm package names are URL-safe, but some servers don't like @ symbols
                                return `npm.${packageName.replace('@', '')}`;
                            },
                        },
                    },
                },
            },
        },
    };
    

    上述代码会把所有的包括异步请求的模块分割,针对大于20000k的文件,最终命名方式是npm.依赖包.js文件,比如npm.echarts.js,命名可以自定义。

    • 重复引用依赖包:封装了一个公共组件库(可通过npm下载),但是临时为了省事项目中也封装了一些组件单独放在一个文件夹中,最终一些相同的依赖就会被重复引用,比如组件库中用了amcharts图表,而项目中又安装使用了这个图表库,会导致此依赖被重复引用,解决方案:把项目中的组件挪到组件库中,这样同一份依赖就只会被使用一次。(不过我记得webpack有配置可以针对同一依赖多次引用的处理,把依赖进行缓存,避免被多次引用,感兴趣的童鞋可以去查阅下相关资料)
    • fps:之前项目中封装了一个方法,针对数据请求多的情况,做了fps处理,如果fps小于30就先不执行数据请求,先等现有数据、界面、地图等渲染完毕,fps稳定后再去执行下一部分数据请求、界面渲染,本身是为了能更好更流畅的渲染,但是如果电脑性能本身就很差,fps本身就很低,会导致一直数据不渲染(哈哈哈,给自己埋了个坑),最终定位问题后发现了这段不合理的处理。大家写代码也要多注意这些情况。

    完整的vue.config.js配置:

    const fs = require('fs');
    const CompressionPlugin = require('compression-webpack-plugin');
    
    let devServer = {};
    if (fs.existsSync('./dev-config.js')) {
        // eslint-disable-next-line global-require
        devServer = require('./dev-config');
    } else {
        console.error('!!!please create the dev-config.js file from dev-config-template.js');
    }
    
    module.exports = {
        lintOnSave: true,
        productionSourceMap: true,
        chainWebpack: config => {
            // 移除 prefetch 插件(避免会预先加载模块/路由)
            config.plugins.delete('prefetch');
            // Loader
            config.module
                .rule('svg')
                .test(/\.(swf|ttf|eot|svg|woff(2))(\?[a-z0-9]+)?$/)
                .use('file-loader')
                .loader('file-loader')
                .end();
            // 开启图片压缩
            // config.module
            //     .rule('images')
            //     .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
            //     .use('image-webpack-loader')
            //     .loader('image-webpack-loader')
            //     .options({ bypassOnDebug: true });
            /* 添加分析工具 */
            if (process.env.NODE_ENV === 'production') {
                if (process.env.npm_config_report) {
                    config
                        .plugin('webpack-bundle-analyzer')
                        // eslint-disable-next-line global-require
                        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
                        .end();
                    config.plugins.delete('prefetch');
                }
            }
        },
        devServer,
        configureWebpack: {
            resolve: {
                alias: {
                    src: '@',
                    components: '@/components',
                    views: '@/views',
                },
            },
            plugins: [
                new CompressionPlugin({
                    algorithm: 'gzip', // 使用gzip压缩
                    test: /\.js$|\.html$|\.css$/, // 匹配文件名
                    filename: '[path].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
                    minRatio: 1, // 压缩率小于1才会压缩
                    threshold: 10240, // 对超过10k的数据压缩
                    deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
                }),
            ],
            optimization: {
                runtimeChunk: 'single',
                splitChunks: {
                    chunks: 'all',
                    maxInitialRequests: Infinity,
                    minSize: 20000,
                    cacheGroups: {
                        vendor: {
                            test: /[\\/]node_modules[\\/]/,
                            name(module) {
                                // get the name. E.g. node_modules/packageName/not/this/part.js
                                // or node_modules/packageName
                                const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
                                // npm package names are URL-safe, but some servers don't like @ symbols
                                return `npm.${packageName.replace('@', '')}`;
                            },
                        },
                    },
                },
            },
        },
    };
    

    好了,以上就是博主自身项目中关于性能优化的一些处理,大家可以参考下。
    如有问题,请指出,接收批评。
    在这里插入图片描述

    个人微信公众号:
    在这里插入图片描述

    展开全文
  • vue项目优化

    2020-10-15 20:27:35
    一、代码优化 1. 使用keep-alive缓存不活动的组件 keep-alive是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 在...
  • 关于vue的seo优化

    千次阅读 热门讨论 2019-06-18 22:02:18
    最近公司的项目中有一个非常重要的功能就是seo的优化,这个东西堵了一段时间,中间还去请教了好些人都没有得到好的解决办法。后来自己通过webpack和prerender-spa-plugin第三方插件这两个工具配合使用来实现曲线就...
  • vue性能优化

    千次阅读 2019-03-30 09:33:35
    标记组件为 functional,这意味它是无状态 (没有响应式数据),无实例 (没有 this 上下文)。
  • 浅谈 Vue 项目优化

    万次阅读 2017-06-20 09:37:08
    好久不写博文了,本文作为我使用半年 vue 框架的经验小结,随便谈谈,且本文只适用于 vue-cli 初始化的项目或依赖于 webpack 打包的项目。 前几天看到大家说 vue 项目越大越难优化,带来很多痛苦,这是避免不了的...
  • Vue性能优化

    千次阅读 2018-08-26 19:55:37
    在最近开发的一个Hybrid APP里,Android Webview初始化一个较重的vue页面竟然用了1200ms ~ 1400ms,这让我开始重视vue的初始化性能,并最终优化到200 ~ 300ms,这篇文章分享我的优化思路。 性能瓶颈在哪里? 先看...
  • vue+webpack实现页面的按需加载 通过vue写的单页应用时,可能会有很多的路由引入。当打包构建的时候,javascript包会变得非常大,影响加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的...
  • vue框架下的滚动条优化插件

    万次阅读 2017-09-05 21:19:53
    https://github.com/GarveyZuo/EasyScroll Vue下的滚动条优化插件EasyScroll使用: 运行: npm isntall --save easyscroll 使用: import EasyScroll from 'easyscroll'; Vue.use(EasyScroll);
  • vue项目中用 cdn 优化

    万次阅读 2017-10-13 15:15:54
    在我们写项目中,优化问题是不容忽视的,尤其是首屏优化更是重中之重,这里介绍两种方法优化方法—-cdn和异步加载,异步请看 http://blog.csdn.net/gang456789/article/details/78224751 1。cdn 首先cdn是什么,...
  • vue如何做Seo优化

    千次阅读 2018-08-07 16:43:26
    vue默认不支持seo优化因为是单页面应用,数据也是用ajax读取,无法友好的让搜索引擎抓取,所以无法获取排名,需要用服务端渲染Nuxt.js来解决,但是这样开发成本太大,建议如果考虑seo的话就不要使用前端框架,用传统...
  • Vue清除定时器setInterval优化方案

    万次阅读 2020-06-05 11:19:25
    Vue清除定时器setInterval优化方案两种方案清除定时器,开发者经常使用方案1,建议使用方案2方案1方案2其他程序化的事件侦听器 两种方案清除定时器,开发者经常使用方案1,建议使用方案2 方案1 首先我在data函数里面...
  • vue】渲染大量数据时性能优化

    千次阅读 2019-08-20 01:30:18
    对应vue渲染大量数据时可以考虑下面几点: 1. 异步渲染组件:因为组件渲染太多,影响页面的渲染时间,所有可以延迟组件渲染,可以考虑v-if处理 2. 可以使用虚拟滚动的组件:参考使用这个插件 vue-virtual-...
  • vuecli做了个spa项目,大概有几十个个路由 直接 npm run build打包出来,有一个 1M的巨大 js文件,导致首页白屏时间过长 分析工具 vuecli 2.x自带了分析工具,只要运行 npm run build --report 如果是 vuecli 3的话...
  • Vue首页加载速度优化

    万次阅读 2018-08-14 16:58:53
    Vue首页加载速度优化 问题描述 最近在搭建自己的博客,前端采用Vue技术,发现首页加载速度非常之慢,常常达到10S左右。虽然作为一个Java开发者,对前端技术不是特别了解,但是也实在无法忍受如此之慢的打开网页...
  • vue项目打包之后js文件过大怎么办?

    万次阅读 2017-08-14 14:51:23
    http://www.cnblogs.com/coolslider/p/7074609.html
  • vue性能优化方面有一个是关于vendor的优化vue其他方面的优化产考https://blog.csdn.net/Chris__wang/article/details/90477555 当项目打包的时候,会将ElementUI,Vue,Vuex,axios,VueRouter等都打包进vendor....
1 2 3 4 5 ... 20
收藏数 41,796
精华内容 16,718
关键字:

vue优化