Vue首屏加载优化

这篇具有很好参考价值的文章主要介绍了Vue首屏加载优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

打包优化

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

可视化资源分析工具

开启gzip压缩

公共代码抽离

代码抽离前

代码抽离后

执行抽离模块

配置解析

CDN替换依赖包引入

移除无用文件

路由优化

动态路由懒加载,按需加载

动态添加路由


打包优化

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

vue 脚手架默认开启了 preload prefetch,对于小项目可以提升体验感,但当我们项目很大时,首屏加载就会很慢很慢。

先简单了解一下 preload prefetch

preload prefetch 都是一种资源预加载机制;

preload 是预先加载资源,但并不执行,只有需要时才执行它;

prefetch 是意图预获取一些资源,以备下一个导航/页面使用;

preload 的优先级高于 prefetch

配置文件:vue.config.js

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

可视化资源分析工具

安装:npm install webpack-bundle-analyzer --save-devg

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
 

chainWebpack: config => {
    // 添加资源可视化工具
    config.plugins.push(
        new BundleAnalyzerPlugin()
    )
}

它可以查看资源模块的体积分布,然后可以对应做优化处理。

vite vue首屏优化,Vue优化,vue.js,前端,javascript

开启gzip压缩

安装:npm install compression-webpack-plugin --save-dev

// gzip压缩插件
const CompressionWebpackPlugin = require('compression-webpack-plugin')

chainWebpack: config => {
    // 添加gzip压缩插件
    config.plugins.push(
      new CompressionWebpackPlugin(
        {
          filename: info => {
            return `${info.path}.gz${info.query}`
          },
          algorithm: 'gzip',
          threshold: 5120, // 只有大小大于该值的资源会被处理 10240
          // test: new RegExp('\\.(' + ['js'].join('|') + ')$'),
          test: /\.js$|\.html$|\.json$|\.css/,
          minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
          deleteOriginalAssets: false // 删除原文件
        }
      )
    )
}

开启gzip压缩,需要配置nginx,打开nginx.config文件,写入以下(在http块内或者在单个server块里添加)

#开启gzip
gzip on;#低于1kb的资源不压缩 
gzip_min_length 1k;#压缩级别1-9,越大压缩率越高,同时消耗cpu资源也越多
gzip_comp_level 9;#需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片.
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;#配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_disable "MSIE [1-6]\."; 
#是否添加“Vary: Accept-Encoding”响应头
gzip_vary on;

开启gzip压缩,服务器为tomcat,修改server.xml文件

<Connector 
    port="8080" 
    protocol="HTTP/1.1"
    connectionTimeout="20000"
 
    compression="on"   
    compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,application/javascript"
    useSendfile="false"/>
// compression="on" 打开压缩功能 
// compressableMimeType="text/html,text/xml" 压缩类型
// useSendfile="false" 设置该属性将会压缩所有文件,不限阙值,不然可能按照阙值部分压缩

启用gzip压缩打包之后,会变成下面这样,自动生成gz包。目前大部分主流浏览器客户端都是支持gzip的,就算小部分非主流浏览器不支持也不用担心,不支持gzip格式文件的会默认访问源文件的,所以不要配置清除源文件。

vite vue首屏优化,Vue优化,vue.js,前端,javascript
配置好之后,打开浏览器访问线上,F12查看控制台,如果该文件资源的响应头里显示有Content-Encoding: gzip,表示浏览器支持并且启用了Gzip压缩的资源

vite vue首屏优化,Vue优化,vue.js,前端,javascript
 

公共代码抽离

  1. 代码抽离前

    默认只生成两个文件,且vendors文件特别大,因为里面包含了我们所有的依赖包资源
    vite vue首屏优化,Vue优化,vue.js,前端,javascript
     
  2. 代码抽离后

    它会根据定义的模块规则进行代码抽离,可以看出抽离后的文件明显体积变小
    vite vue首屏优化,Vue优化,vue.js,前端,javascript
     
  3. 执行抽离模块

    chainWebpack: config => {
        config
          .when(process.env.NODE_ENV !== 'development',
            config => {
              config
                .plugin('ScriptExtHtmlWebpackPlugin')
                .after('html')
                .use('script-ext-html-webpack-plugin', [{
                // `runtime` must same as runtimeChunk name. default is `runtime`
                  inline: /runtime\..*\.js$/
                }])
                .end()
              config
                .optimization.splitChunks({
                  chunks: 'all',
                  cacheGroups: {
                    libs: {
                      name: 'chunk-libs',
                      test: /[\\/]node_modules[\\/]/,
                      priority: 10,
                      chunks: 'initial' // 当为initial时,只能分离初始化的模块,异步的模块无法分离
                    },
                    elementUI: {
                      name: 'chunk-elementUI', // 将 elementUI 拆分为单个包
                      priority: 20, // 权重需要大于 libs 和 app 否则会被打包到 libs 或 app 中
                      test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // 匹配文件
                    },
                    echarts: {
                      name: 'chunk-echarts', // 将 echarts 拆分为单个包
                      priority: 20, 
                      test: /[\\/]node_modules[\\/]_?echarts(.*)/
                    },
                    commons: {
                      name: 'chunk-commons',
                      test: resolve('src/components'), // 可以自定你的规则
                      minChunks: 3, // 当某个模块满足minChunks引用次数时,才会被打包。
                      priority: 5,
                      reuseExistingChunk: true // 默认为false,关闭表示拆分出复用部分的模块,给双方引用
                    }
                  }
                });
              // 最小化代码
              config.optimization.minimize(true);
              // 如果我们要在一个 HTML 页面上使用多个入口时,还需设置 optimization.runtimeChunk: 'single',否则还会遇到这里所述的麻烦。
              // https://bundlers.tooling.report/code-splitting/multi-entry/
              // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
              config.optimization.runtimeChunk('single')
            }
          );
    }
  4. 配置解析

    chunks:可用值为“all”、“async”、“initial”,默认值是“async”

                all:拆分同步和异步文件

                async:只对异步文件作处理

                initial:只对入口文件进行拆分,不去处理异步文件里的模块

        minSize:控制最小包的大小,大于这个值才会去拆分,
                         如果拆分的公共模块小于这个大小,那就复制成多份,
                         直接打包到引用该模块的包里

        minChunks:模块的重复调用次数大于等于minChunks值时,就会满足这项拆包条件,
                               但只看入口模块导入的,不看动态加载模块中导入的(import(‘…’)),
                               即使设置的chunks为“all”。

        maxInitialRequests:入口文件最大请求的文件数量(import等方式)

                入口文件本身算一个请求

                入口文件动态加载的模块不算在内

                通过runtimeChunk拆分出来的runtime文件不算在内

                只算js,css不算在内

                如果同时有两个模块满足cacheGroups的拆分规则,
                但maxInitialRequests只允许再拆分一个,那么会拆出体积

                更大的那个模块。

        maxAsyncRequests:用于限制异步模块内部的并行最大请求数

                import文件本身算一个请求

                只算js、css不算在内

                如果同时有两个模块满足cacheGroups的规则需要拆分,
                但maxAsyncRequests只允许拆分一个时,那么会拆出体积更大的那个模块。

        name:主要用于分离chunks后的名字,可以是字符串或者函数,
                     相同name会合并成一个chunk

        splitChunks.cacheGroups

                可以继承或者重写splitChunks对象下的属性,但是test、priority和reuseExistingChunk
                只能配置在cacheGroup对象中

                每个添加的对象都有默认配置,如果想禁用此配置,可以将其设置为false

CDN替换依赖包引入

项目打包时会根据依赖关系自动打包压缩依赖文件,当依赖文件过大,会导致首屏加载变慢

使用CDN: 简单来说就是可以使用CDN引入依赖库,减少依赖包体积,释放服务器压力, 它由距离最近的缓存服务器直接响应,提高加载速度

进一步考虑:当我们在开发环境下,使用CDN引入会比我们直接引入依赖要慢,所以配置CDN需要只在生产环境

vite vue首屏优化,Vue优化,vue.js,前端,javascript



 

配置步骤: 

// 环境区分主要为开发环境与其他环境(其他:生产,uat,测试等等)
const isNotDevelopMentEnv = process.env.NODE_ENV !== 'development'
const cdnData = {
    css: [
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.0/theme-chalk/index.css'
    ],
    js: [
        'https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js',
        'https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js',
        'https://cdn.bootcdn.net/ajax/libs/vuex/3.1.0/vuex.min.js',
        'https://cdn.bootcdn.net/ajax/libs/vue-router/3.0.6/vue-router.min.js',
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.0/index.js',
        'https://cdn.bootcdn.net/ajax/libs/jquery/1.12.1/jquery.min.js',
        'https://cdn.bootcdn.net/ajax/libs/vee-validate/2.0.0-rc.21/vee-validate.min.js',
        'https://cdn.bootcdn.net/ajax/libs/vee-validate/2.0.0-rc.21/locale/zh_CN.js'
    ],
    /** 
    * 属性名称 vue, 表示遇到 import xxx from 'vue' 
    * 这类引入 'vue'的,不去 node_modules 中找,而是去找全局变量 Vue
    * 其他的为VueRouter、Vuex、axios、ELEMENT、echarts,注意全局变量是一个确定的值,不能修改为其他值,修改为其他大小写或者其他值会报错
    */
    externals: {
        'vue': 'Vue',
        'vuex': 'Vuex',
        'vue-router': 'VueRouter',
        'element-ui': 'ELEMENT',
        'vuex': 'Vuex',
        'axios': 'axios',
        'vee-validate': 'VeeValidate',
        'jQuery':"jquery",
        'jquery': 'window.$'
    }
}

// 在configureWebpack中添加externals
configureWebpack: {
    externals: isNotDevelopMentEnv ? cdnData.externals : {}
}

// 在chainWepack中添加如下
if (isNotDevelopMentEnv) {
    config.plugin('html')
    .tap(args => {
        args[0].cdn = cdnData
        return args
    })
}

 修改 public/index.html(根据环境,开发环境不使用CDN,生产环境才开放)

<html>
    <head>
        <!-- 样式文件优先加载 -->
        <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
            <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
        <% } %>
    </head>
    <body>
        <div id="app"></div>
        <!-- js加载 -->
        <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
            <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
        <% } %>
    </body>
</html>

采用CDN引入后,不需要删除原有依赖引入,因为在本地还是使用这些依赖进行调试的,打包后因为有CDN所以不会把这些依赖引入所以不用担心,import引入的不需要变更。例如main.js中使用import ElementUI from 'element-ui', 以上的代码已经实现在开发环境会设置不适用CDN,会使用依赖包文件;当发布到生产环境,因为我们已经在vue.config.js的externals中指代了element-ui,所以这个语句也是有效的可以直接使用CDN elementUI

易出错点:
Router is not defined
vite vue首屏优化,Vue优化,vue.js,前端,javascriptvite vue首屏优化,Vue优化,vue.js,前端,javascript
vite vue首屏优化,Vue优化,vue.js,前端,javascript
解决方案: 将Router 改为 'VueRouter'

Uncaught TypeError: Illegal constructor
vite vue首屏优化,Vue优化,vue.js,前端,javascript

 解决方案:修改externals 中‘'element-ui’的value为:ELEMENT

移除无用文件

安装:npm install useless-files-webpack-plugin --save-dev

// 导入插件
const UselessFile = require('useless-files-webpack-plugin')

 
chainWebpack: config => {
    config.plugin('uselessFile')
    .use(
      new UselessFile({
        root: './src', // 项目目录
        out: './fileList.json', // 输出文件列表
        clean: false, // 是否删除文件,
        exclude: [/node_modules/] // 排除文件列表
      })
    )
}

路由优化

动态路由懒加载,按需加载

单页面应用的首屏加载较慢主要是因为单页面应用在首屏时,无论是否需要都会加载所有的模块,可通过按需加载、路由懒加载来优化。

  • 动态加载,通过import来实现路由的动态加载,这个时候对于路由的加载是动态的,用到再加载。

    {、
      path:"/home",
      name:"home",
      component: () => import(/* webpackChunkName: "home" */ "@/views/home.vue"))
    }
  • 按需加载,通过对路由文件的配置,来对相关模块划分区间,如登录界面可以和首页、主页面划分一块,在进入首屏时,只对首屏所在的区块进行加载。通过require.ensure()来将多个相同类的组件打包成一个文件。如示例代码,打包时,将两个组件打包成一个js文件,文件名为home

    {
         path: '/login', //path路径        
         name: 'login', //组件名
         component: r => require.ensure([], () => r(require('../components/login')), 'home') //good类型的组件
    },
    {
         path: '/home', //path路径        
         name: 'home', //组件名
         component: r => require.ensure([], () => r(require('../components/home')), 'home') //good类型的组件
    }

动态添加路由

通常路由权限实现可以通过路由守卫 router.beforeEach,配合使用 router.addRoutes 动态添加路由文章来源地址https://www.toymoban.com/news/detail-797568.html

import router from './router'
import store from './store'

router.beforeEach(async(to, from, next) => {
    const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      next({ path: '/' })
    } else {
      // 判断用户是否通过 getInfo 获取了自己的角色权限
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // 获取用户角色
          const { roles } = await store.dispatch('user/getInfo')

          // 获取用户具有权限的路由
          const accessRoutes = await store.dispatch('permission/getUserMenus', roles)
          // 动态添加可访问的路由
          router.addRoutes(accessRoutes)

          // 确保addRoutes完整的hack方法
          // 设置 replace: true,因此导航不会留下历史记录
          next({ ...to, replace: true })
        } catch (error) {
          // 移除token,进入登录页面重新登录
          await store.dispatch('user/resetToken')
          console.error(error)
          next(`/login?redirect=${to.path}`)
        }
      }
    }
  }
})

到了这里,关于Vue首屏加载优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue首屏优化,12个提速建议

    vue首屏代码优化的概要方案,供参考: 将首屏所需的组件和代码拆分成独立的模块,并使用懒加载技术(如 Vue 的异步组件或路由懒加载)来按需加载它们。这样可以减少初始加载的代码量,提高首屏的加载速度。 代码拆分 创建多个组件文件:将大型的 Vue 组件拆分成多个较

    2024年02月19日
    浏览(30)
  • 【VUE】解决VU2项目图片视频加载缓慢/首屏加载白屏的问题

    前端项目中,有时候会出现图片视频加载缓慢、首屏加载白屏的问题 之前写了一篇在VU3项目中的解决方案, 现在讲一下在 Vue2 项目中的解决方法,方法思路都差不多,在代码示例上会有一些小差别 通常是由以下原因导致的: 图片或视频格式不当 :如果图片或视频格式选择

    2024年02月16日
    浏览(30)
  • 前端2023最全面试题(javaScript、typeScript、vue2、vue3、html、css、uniapp、webpack、vite、react)

    答案:JavaScript中的闭包是一种函数,它有权访问其词法环境的变量和其它函数。这意味着,即使其包含它的函数已经执行完毕,其词法环境仍然存在,因此可以访问其作用域内的变量。 答案:回调函数是在某个特定事件之后执行的函数。在JavaScript中,通常使用回调函数来处

    2024年02月06日
    浏览(44)
  • 前端首屏性能优化

    代码压缩 GZIP 图片压缩 代码拆分 http强缓存 Sevice Worker 本地存储localStorage 合并请求 CDN DNS Prefetch 按需加载 懒加载 预加载 客户端内H5页面可考虑离线等方式 内容直出 js外链放在底部 css外链放在顶部 减少dom数量 使用webworker 长任务分片执行 减少回流重绘 减低css选择器复杂性

    2024年02月16日
    浏览(29)
  • Vue3的vite中图片的动态加载

    vite官网的静态资源引入参考地址 new URL() + import.meta.url 注意:这里只能通过 …/…/ 这种方式去获取路径,无法通过@/assets

    2024年02月16日
    浏览(27)
  • 《Vite 基础知识》使用 Glob 动态加载 .vue 文件

    开发基于 Vite + Vue3 的组件库,多个 .vue 文件需要动态加载! 注意 import.meta.globEager 已经弃用,请使用 import.meta.glob 来代替! 代码第 1 行,注意使用两个 **,匹配当前目录及其嵌套的全部子目录下的文件; 代码第 4 行,异步使用 Promise 加载,所以要在 then 中获取真正的组件对

    2024年01月18日
    浏览(33)
  • docker打包vue vite前端项目

    (如若提供一些帮助,请帮忙点个赞) 1.打包时将测试删除 2.修改配置 3.打包项目 npm run build 显示成功(黄的也不知道是啥) 打包好的前端文件放入 4.配置 default.conf 5.配置dockerfile 6.进入你的文件夹下面 我的是 /root/206/web docker build -t web:v1 . 注意后面的 . 点 7.运行 docker run -it -

    2024年02月07日
    浏览(28)
  • vue3创建项目,vite+js

    之前的时候大哥就让我自己搭架子,但是我拖延症,现在用到了,得自己搭了 我的项目都放到了 VuePorjects这个目录里面, 一、先进入到指定工作目录,(不是你要创建的项目的名称哈) 二、创建vue3项目,安装创建项目  @latest是项目名称,可以自己修改项目名称,然后选择

    2024年02月16日
    浏览(48)
  • vue3 + vite 性能优化,详细代码说明

    对于Vue 3和Vite应用的性能优化,以下是一些常见的技巧和建议: 使用Tree-shaking:Vue 3和Vite支持ES模块的静态分析,因此可以利用Tree-shaking特性,只引入项目中实际使用的模块,减少打包体积。 懒加载路由:使用Vue Router的动态导入功能,将路由按需加载,可以减少初始加载的

    2024年02月02日
    浏览(31)
  • 快速搞定前端JS面试 -- 第十二章 运行环境 (页面加载、性能优化、安全)

    4. Window.onload和DOMContentLoaded 二、性能优化 1、性能优化原则 2、如何入手性能优化 1. 资源合并 2. 缓存 3. CDN 4. SSR 5. 懒加载 6. 缓存DOM查询 7. 尽早开始JS执行 8. 防抖 9. 节流 三、安全 1. XSS跨站请求攻击 2. XSRF跨站请求伪造 问题解答 1. 从输入url到显示出页面的整个过程 2.

    2024年04月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包