前端学习笔记-vue加载渲染优化

16 路由懒加载 + 异步组件

一句话理解

别把所有页面的代码打包成一个大 JS 文件------用到哪个页面才加载哪个(按需加载),首屏只加载首页代码。

为什么

SPA(单页应用)默认把所有路由组件打进一个 bundle。用户打开首页,却下载了"设置页、订单页、报表页......"的全部代码------大部分用不上,白等。

懒加载把每个路由拆成独立的小 chunk,访问时才请求。

代码示例

路由懒加载(最常用):

js 复制代码
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    component: () => import('../views/Home.vue'),     // 懒加载
  },
  {
    path: '/dashboard',
    component: () => import('../views/Dashboard.vue'), // 访问 /dashboard 时才加载
  },
  {
    path: '/settings',
    component: () => import('../views/Settings.vue'),  // 访问 /settings 时才加载
  },
]

export default createRouter({ history: createWebHistory(), routes })

组件级异步加载(重组件按需加载):

vue 复制代码
<script setup>
import { defineAsyncComponent, ref } from 'vue'

// 只在需要渲染时才加载这个重组件
const HeavyChart = defineAsyncComponent(() => import('./HeavyChart.vue'))

const showChart = ref(false)
</script>

<template>
  <button @click="showChart = true">加载图表</button>
  <HeavyChart v-if="showChart" />
</template>

带 loading / error 的异步组件:

js 复制代码
import { defineAsyncComponent, h } from 'vue'

const ReportPanel = defineAsyncComponent({
  loader: () => import('./ReportPanel.vue'),
  loadingComponent: () => h('div', '加载中...'),  // 加载时显示
  errorComponent:   () => h('div', '加载失败'),    // 失败时显示
  delay: 200,    // 200ms 后才显示 loading(避免闪烁)
  timeout: 10000,// 10s 超时判定失败
})

新人提示

  • 路由懒加载是 SPA 的标配,几乎是必做的优化,零成本收益大。
  • 异步组件适合重组件(图表、富文本编辑器、大表格),别滥用在小组件上。

17 预渲染(Prerendering)

一句话理解

如果你的页面内容大部分是静态的 (如博客、官网、文档),可以在构建时就把页面渲染成完整 HTML,用户打开直接拿到成品------既快又对 SEO 友好,还不需要服务器实时渲染。

为什么

  • 和 SSR 的区别:预渲染在 build 阶段一次性生成 HTML,运行时服务器只发静态文件;SSR 是每次请求都实时渲染。
  • 预渲染适合内容固定、不随用户变化 的页面;SSR 适合内容动态、千人千面的页面。

代码示例

Vite 项目用 vite-plugin-ssg 或 vite-plugin-prerender:

js 复制代码
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { ViteSSG } from 'vite-ssg'

export default defineConfig({
  plugins: [
    vue(),
    // 预渲染:构建时把指定路由生成静态 HTML
    ViteSSG({ /* 配置 */ }),
  ],
})

Vue 2 时代用 prerender-spa-plugin(理解原理):

js 复制代码
// 构建时用无头浏览器访问这些路由,把渲染结果存成 HTML 文件
new PrerenderSPAPlugin({
  routes: ['/', '/about', '/contact'],  // 这些页面会被预渲染成静态 HTML
})

新人提示

  • 适用场景:官网首页、博客文章、文档站、营销页------内容固定,追求首屏速度和 SEO。
  • 不适用:后台管理系统、社交动态流------内容因人而异,预渲染没意义,该上 SSR。
  • 预渲染的产物就是一堆 .html,部署到任何静态服务器(Nginx / CDN)都行。

18 SSR 服务端渲染

一句话理解

让 Node 服务器 把 Vue 组件渲染成 HTML 字符串发给浏览器,浏览器收到后直接显示(首屏秒开),然后再"激活"(hydrate)成可交互的 SPA。

为什么

指标 纯 CSR(普通 SPA) SSR
首屏白屏时间 长(要下载 JS + 执行 + 渲染) 短(HTML 直接显示)
SEO 差(爬虫看到空壳) 好(直接有内容)
服务器压力 低(只发静态文件) 高(每次请求都要渲染)
开发复杂度 低 高(要兼容服务端环境)

代码示例

用 Nuxt 3(Vue 官方推荐的 SSR 框架,开箱即用):

bash 复制代码
# 一行命令创建 SSR 项目
npx nuxi init my-ssr-app
cd my-ssr-app
npm install
npm run dev    # 开发
npm run build  # 构建 SSR 产物

服务端数据获取(Nuxt 的 useFetch,服务端执行):

vue 复制代码
<!-- pages/posts/[id].vue -->
<template>
  <article>
    <h1>{{ post.title }}</h1>
    <div>{{ post.content }}</div>
  </article>
</template>

<script setup>
// useFetch 在服务端就执行,HTML 里直接带数据,首屏即有内容
const { data: post } = await useFetch(`/api/posts/${route.params.id}`)
</script>

SSR 的坑(新人必看)

js 复制代码
import { onMounted } from 'vue'

// 错:服务端没有 window / document,setup 顶层直接用会报错
// const width = window.innerWidth

// 对:浏览器专属代码放进 onMounted(只在客户端执行)
onMounted(() => {
  const width = window.innerWidth
  console.log(width)
})

新人提示

  • 别为了"快"就上 SSR------它带来服务器成本、部署复杂度、调试难度。
  • 先问自己:"我真的需要 SEO 吗?首屏真的慢到需要 SSR 吗?" 不需要就别上。
  • 优先级:懒加载 + 预渲染能解决的,就别上 SSR。SSR 是最后的重武器。
相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
一隅论数智4 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
XiHongShi20164 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
爱吃苹果的日记本4 天前
离散数学第六课
学习·离散数学
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js