Vue首屏加载出现白屏问题的优化实战

 更新时间:2025年05月08日 09:34:37   作者:非鱼牛马社  
在实际开发中,Vue 应用首次加载时经常出现白屏问题,这严重影响了用户体验,本文将从多个角度出发,提供全面的解决方案,大家可以根据需要进行选择

一、背景

在实际开发中,Vue 应用首次加载时经常出现白屏问题,这严重影响了用户体验。本文将从多个角度出发,提供全面的解决方案。

二、问题分析

2.1 白屏原因

  • JavaScript 资源体积过大
  • 首屏渲染机制的特点
  • 资源加载顺序不合理
  • 服务端配置问题
  • 浏览器缓存策略

三、解决方案

3.1 路由懒加载优化

// 修改前
import UserDetails from './views/UserDetails.vue'

// 修改后 - 方案1:简单懒加载
const UserDetails = () => import('./views/UserDetails.vue')

// 方案2:分组懒加载
const UserDetails = () => import(/* webpackChunkName: "user" */ './views/UserDetails.vue')
const UserProfile = () => import(/* webpackChunkName: "user" */ './views/UserProfile.vue')

3.2 骨架屏方案

手动实现

<!-- SkeletonComponent.vue -->
<template>
  <div class="skeleton">
    <div class="skeleton-header"></div>
    <div class="skeleton-content">
      <div class="skeleton-item"></div>
      <div class="skeleton-item"></div>
    </div>
  </div>
</template>

<style scoped>
.skeleton {
  padding: 15px;
}
.skeleton-header {
  height: 20px;
  background: #f2f2f2;
  margin-bottom: 15px;
  animation: skeleton-loading 1s infinite alternate;
}
.skeleton-item {
  height: 60px;
  background: #f2f2f2;
  margin-bottom: 10px;
  animation: skeleton-loading 1s infinite alternate;
}
@keyframes skeleton-loading {
  from { opacity: 0.6; }
  to { opacity: 1; }
}
</style>

自动化方案

推荐使用 vue-skeleton-webpack-plugin 插件:

npm install vue-skeleton-webpack-plugin -D

配置示例:

// vue.config.js
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin')

module.exports = {
  configureWebpack: {
    plugins: [
      new SkeletonWebpackPlugin({
        webpackConfig: {
          entry: {
            app: path.join(__dirname, './src/skeleton.js'),
          },
        },
        minimize: true,
        quiet: true,
        router: {
          mode: 'hash',
          routes: [
            { path: '/', skeletonId: 'skeleton1' },
            { path: '/about', skeletonId: 'skeleton2' }
          ]
        }
      })
    ]
  }
}

3.3 资源预加载优化

基础配置

<!-- index.html -->
<head>
  <!-- DNS预解析 -->
  <link rel="dns-prefetch" href="//api.example.com">
  
  <!-- 预加载关键资源 -->
  <link rel="preload" href="/fonts/important.woff2" as="font" crossorigin>
  
  <!-- 预加载组件 -->
  <link rel="prefetch" href="/js/non-critical.js">
</head>

预渲染方案

对于静态内容较多的页面,推荐使用 prerender-spa-plugin:

npm install prerender-spa-plugin -D

配置示例:

// vue.config.js
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
  configureWebpack: {
    plugins: [
      new PrerenderSPAPlugin({
        staticDir: path.join(__dirname, 'dist'),
        routes: ['/', '/about', '/contact'],
        renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
          renderAfterDocumentEvent: 'render-event'
        })
      })
    ]
  }
}

3.4 Webpack 构建优化

体积分析与优化

推荐使用 webpack-bundle-analyzer 分析打包体积:

npm install webpack-bundle-analyzer -D
// vue.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  configureWebpack: {
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }
}

构建速度优化

使用 hard-source-webpack-plugin 提升构建速度:

npm install hard-source-webpack-plugin -D
// vue.config.js
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')

module.exports = {
  configureWebpack: {
    plugins: [
      new HardSourceWebpackPlugin()
    ]
  }
}

Gzip 压缩

使用 compression-webpack-plugin 实现:

npm install compression-webpack-plugin -D
// vue.config.js
const CompressionWebpackPlugin = require('compression-webpack-plugin')

module.exports = {
  configureWebpack: {
    plugins: [
      new CompressionWebpackPlugin({
        test: /\.(js|css|html|svg)$/,
        threshold: 10240
      })
    ]
  }
}

构建分析

使用 speed-measure-webpack-plugin 分析构建过程:

npm install speed-measure-webpack-plugin -D
// vue.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
const smp = new SpeedMeasurePlugin()

module.exports = {
  configureWebpack: smp.wrap({
    // ... 其他配置
  })
}

3.5 开发调试优化

Vue DevTools

  • 安装:通过 Chrome 插件商店安装
  • 功能:
    • 组件树分析
    • 性能分析
    • 状态管理
    • 路由调试

性能分析工具

Chrome Lighthouse

  • 内置于 Chrome DevTools
  • 提供性能评分
  • 给出优化建议
  • 生成详细报告

webpack-dashboard

npm install webpack-dashboard -D
// vue.config.js
const DashboardPlugin = require('webpack-dashboard/plugin')

module.exports = {
  configureWebpack: {
    plugins: [
      new DashboardPlugin()
    ]
  }
}

3.6 服务端渲染 (SSR)

// entry-server.js
import { createApp } from './app'

export default context => {
  return new Promise((resolve, reject) => {
    const { app, router, store } = createApp()

    router.push(context.url)

    router.onReady(() => {
      const matchedComponents = router.getMatchedComponents()
      
      if (!matchedComponents.length) {
        return reject({ code: 404 })
      }

      Promise.all(matchedComponents.map(Component => {
        if (Component.asyncData) {
          return Component.asyncData({
            store,
            route: router.currentRoute
          })
        }
      })).then(() => {
        context.state = store.state
        resolve(app)
      }).catch(reject)
    }, reject)
  })
}

3.7 静态资源 CDN 加速

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.externals({
      'vue': 'Vue',
      'vuex': 'Vuex',
      'vue-router': 'VueRouter',
      'axios': 'axios'
    })
  }
}
<!-- index.html -->
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.15.7/lib/theme-chalk/index.css">
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuex@3.6.2"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue-router@3.5.3"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios@0.24.0"></script>
</head>

3.8 浏览器缓存优化

# nginx.conf
location / {
    add_header Cache-Control "public, max-age=31536000";
    
    # 配置协商缓存
    etag on;
    if_modified_since exact;
    
    # 开启gzip
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

四、推荐插件和工具

4.1 性能优化插件

vue-skeleton-webpack-plugin

npm install vue-skeleton-webpack-plugin -D

用于自动生成骨架屏,支持多路由页面的骨架屏配置。

prerender-spa-plugin

npm install prerender-spa-plugin -D

预渲染插件,适用于静态内容较多的页面。

compression-webpack-plugin

npm install compression-webpack-plugin -D

用于 Gzip 压缩,大幅减小文件体积。

webpack-bundle-analyzer

npm install webpack-bundle-analyzer -D

分析打包体积,找出大文件并优化。

hard-source-webpack-plugin

npm install hard-source-webpack-plugin -D

为模块提供中间缓存,大幅提升二次构建速度。

speed-measure-webpack-plugin

npm install speed-measure-webpack-plugin -D

分析 webpack 打包速度,找出耗时步骤。

4.2 开发调试工具

vue-devtools

  • Chrome 插件商店安装
  • 用于组件调试和性能分析

Lighthouse

  • Chrome 开发者工具内置
  • 提供全面的性能评分和优化建议

webpack-dashboard

npm install webpack-dashboard -D

优化 webpack 开发输出界面,提供更直观的信息。

五、性能检测与监控

5.1 性能指标

  • First Paint (FP)
  • First Contentful Paint (FCP)
  • Time to Interactive (TTI)
  • Total Blocking Time (TBT)

5.2 检测工具

  • Vue DevTools
  • Chrome Lighthouse
  • webpack-bundle-analyzer
  • Performance API
// 性能监控示例
window.performance.mark('vue-init-start')

// Vue 初始化完成后
window.performance.mark('vue-init-end')
window.performance.measure(
  'vue-init',
  'vue-init-start',
  'vue-init-end'
)

六、最佳实践建议

  • 合理使用路由懒加载,避免一次性加载过多组件
  • 使用骨架屏提升用户体验
  • 关键资源预加载,非关键资源延迟加载
  • webpack 配置优化,合理分包
  • 考虑引入服务端渲染
  • 利用浏览器缓存机制
  • 持续监控性能指标

七、总结

Vue 首屏白屏问题是一个复杂的性能优化课题,需要从多个层面进行优化:

  • 代码层面:路由懒加载、组件按需加载
  • 构建层面:webpack 优化、资源压缩
  • 架构层面:SSR、骨架屏
  • 网络层面:CDN、缓存策略

选择合适的解决方案需要根据具体项目的情况来决定,建议从最容易实现且收益最大的方案开始着手优化。

到此这篇关于Vue首屏加载出现白屏问题的优化实战的文章就介绍到这了,更多相关Vue首屏优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue之Axios的异步通信详解

    Vue之Axios的异步通信详解

    这篇文章主要为大家详细介绍了Vue之Axios的异步通信,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 使用vuex存储用户信息到localStorage的实例

    使用vuex存储用户信息到localStorage的实例

    今天小编就为大家分享一篇使用vuex存储用户信息到localStorage的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue2使用思维导图jsmind的详细代码

    vue2使用思维导图jsmind的详细代码

    jsMind是一个基于Js的思维导图库,jsMind是一个纯JavaScript类库,用于创建、展示和操作思维导图,这篇文章主要给大家介绍了关于vue2使用思维导图jsmind的详细代码,需要的朋友可以参考下
    2024-06-06
  • Vue3.0中Ref与Reactive的区别示例详析

    Vue3.0中Ref与Reactive的区别示例详析

    在vue3中对响应式数据的声明官方给出了ref()和reactive()这两种方式,这篇文章主要给大家介绍了关于Vue3.0中Ref与Reactive区别的相关资料,需要的朋友可以参考下
    2021-07-07
  • vue使用计算属性完成动态滑竿条制作

    vue使用计算属性完成动态滑竿条制作

    这篇文章主要介绍了vue使用计算属性完成动态滑竿条制作,文章围绕计vue算属制作动态滑竿条的相关代码完成内容,需要的朋友可以参考一下
    2021-12-12
  • Vue中Vue.use()的原理及基本使用

    Vue中Vue.use()的原理及基本使用

    相信很多人在用Vue使用别人的组件时,会用到 Vue.use() ,例如:Vue.use(VueRouter)、Vue.use(MintUI),这篇文章主要给大家介绍了关于Vue中Vue.use()的原理及基本使用的相关资料,需要的朋友可以参考下
    2021-10-10
  • Vue使用openlayers实现绘制圆形和多边形

    Vue使用openlayers实现绘制圆形和多边形

    这篇文章主要为大家详细介绍了Vue如何使用openlayers实现绘制圆形和多边形,文中的示例代码讲解详细,感兴趣的小伙伴快跟随小编一起动手尝试一下
    2022-06-06
  • el-table表头根据内容自适应完美解决表头错位和固定列错位

    el-table表头根据内容自适应完美解决表头错位和固定列错位

    这篇文章主要介绍了el-table表头根据内容自适应完美解决表头错位和固定列错位,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Vuejs 组件——props数据传递的实例代码

    Vuejs 组件——props数据传递的实例代码

    本篇文章主要介绍了Vuejs 组件——props数据传递的实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • 浅谈一下Vue生命周期中mounted和created的区别

    浅谈一下Vue生命周期中mounted和created的区别

    每一个vue实例从创建到销毁的过程,就是这个vue实例的生命周期,在这个过程中,他经历了从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程,那么这些过程中,具体vue做了些啥,我们今天来了解一下
    2023-05-05

最新评论