SPA 首屏加载优化

解决单页应用首屏加载速度慢的实用方案

问题

SPA(单页应用)首屏加载速度慢,影响用户体验。首屏时间(First Contentful Paint)指从用户输入网址到首屏内容渲染完成的时间。

可以通过以下方式计算首屏时间:

// 方案一:DOMContentLoaded
document.addEventListener('DOMContentLoaded', (event) => {
    console.log('first contentful painting');
});

// 方案二:Performance API
performance.getEntriesByName("first-contentful-paint")[0].startTime

// 返回结构
{
  name: "first-contentful-paint",
  entryType: "paint",
  startTime: 507.80000002123415,
  duration: 0,
}

解答

路由懒加载

将不同路由对应的组件分割成不同代码块,按需加载:

routes: [
    {
        path: 'Blogs',
        name: 'ShowBlogs',
        component: () => import('./components/ShowBlogs.vue')
    }
]

静态资源缓存

后端设置 HTTP 缓存头:

Cache-Control, Last-Modified, Etag

前端使用 localStorage 或 Service Worker 离线缓存。

UI 框架按需加载

避免引入整个 UI 库,只导入需要的组件:

// 不推荐
import ElementUI from 'element-ui'
Vue.use(ElementUI)

// 推荐
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui'
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)

避免组件重复打包

在 webpack 配置中设置 CommonsChunkPlugin:

minChunks: 3

将使用 3 次及以上的包抽离到公共依赖文件。

图片资源优化

  • 压缩图片资源
  • 使用字体图标或雪碧图替代小图标
  • 减少 HTTP 请求数量

开启 Gzip 压缩

安装插件:

npm i compression-webpack-plugin -D

配置 webpack:

const CompressionPlugin = require('compression-webpack-plugin')

configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
        config.mode = 'production'
        return {
            plugins: [new CompressionPlugin({
                test: /\.js$|\.html$|\.css/,
                threshold: 10240,
                deleteOriginalAssets: false
            })]
        }
    }
}

服务端配置(Express):

const compression = require('compression')
app.use(compression())

使用 SSR

服务端渲染可以直接返回 HTML 字符串,Vue 应用推荐使用 Nuxt.js 实现。

关键点

  • 路由懒加载减小入口文件体积,按需加载组件
  • 合理使用缓存策略(HTTP 缓存、localStorage、Service Worker)
  • UI 框架按需引入,避免加载无用代码
  • 开启 Gzip 压缩可显著减小资源体积
  • 图片优化和避免重复打包能有效减少请求数量