import{_ as l,o as e,c as o,R as a}from"./chunks/framework.a304f0f7.js";const D=JSON.parse('{"title":"服务端渲染(SSR)","description":"","frontmatter":{},"headers":[],"relativePath":"note/SSR.md","lastUpdated":1682252217000}'),i={name:"note/SSR.md"},t=a(`
我们使用Vue开发的网页一般都是单页面应用程序(SPA Single Page Application)
.html
文件与之相对的,就是服务端渲染(SSR Server Side Rendering)
于是,同构SSR应运而生,我们称之为BFF(Backend for Frontend 服务于前端的后端)
浏览器请求.html
文件 => 服务端运行Vue / React代码并生成.html
=> 发送.html
文件给浏览器 => 浏览器显示网页内容
=> 浏览器加载JS文件 => 绑定DOM事件 客户端渲染接管界面 => 再次跳转路由就是客户端渲染 无需请求后台
.html
文件,页面切换不需要重新加载,所以比传统Web应用程序更快h1
,一个页面只应当由一个 h1
标签,副标题用 h2 - h6
h
标签,多次使用不会增加SEOp
标签 列表用 ul
标签,且 li
只放在 ul
中<a href="https://www.example.com" />
<a href="/relative/path/file" />
<b>
和<strong>
加粗文本的标签,爬虫会关注到该内容img
标签添加alt
属性,图片加载失败时供爬虫读取alt
内容服务端渲染 SSR (Server Side Rendering)
app = createSSRApp(App)
renderToString(app) => App String Html
client_bundle.js
客户端通过脚本激活应用程序 让应用程序可以进行交互,这个过程叫水合( Hydration)静态网页生成 SSG(Static Site Generate)
.html
页面的内容.html
文件给客户端,相当于一个静态资源html
文件,有利于SEO在SPA中,整个生命周期只有一个App对象实例/一个Router对象实例/一个Store对象实例
然而在SSR的环境下,App模块通常只在
服务器启动时
初始化一次,同一个应用模块会在多个服务器请求之间被复用
为了避免这种跨请求状态污染,SSR的解决方案是:
h3
实现部署可移植性(h3
是一个极小的高性能http框架) 使用命令行工具 Nuxi
初始化Nuxt:
npx nuxi init project-name
pnpm dlx nuxi init project-name
npm install -g nuxi && nuxi init project-name
解读脚手架创建的初始化项目的package.json
中的脚本:
{
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"devDependencies": {
"nuxt": "^3.2.0"
}
}
build
构建正式版本,将被输出到.output
文件夹dev
开发环境generate
打包正式版本项目,但是会预渲染每个路由(nuxt build --prerender
)preview
对打包项目启动本地预览服务器postinstall
该脚本为NPM的生命周期函数,将在npm install
后执行针对postinstall
中执行的nuxi prepare
脚本,官方文档有如下解释:
The
prepare
command creates a.nuxt
directory in your application and generates types. This can be useful in a CI environment or as apostinstall
command in yourpackage.json
.
执行该脚本后,将在项目根目录创建.nuxt
文件夹
.d.ts
结尾,是Nuxt的TS类型声明nuxt.config.ts
文件,对Nuxt进行自定义配置runtimeConfig
运行时配置 即定义环境变量runtimeConfig
中的值,仅在服务端可以访问到 runtimeConfig.public
中的变量,在客户端和服务端中都能读取到.env
文件中,优先级.env > runtimeConfig
NUXT_
开头的会作为私有环境变量读取到运行时NUXT_PUBLIC_
开头的会作为公共变量读取到运行时appConfig
应用配置,定义在构建时确定的公共变量,如 theme app.config.ts > appConfig
app
app的配置head
给每个页面设置head信息,也支持useHead配置和内置组件 useHead
函数Head
ssr
指定应用渲染模式 ssr: false
则会采用SPA的方式渲染应用,即客户端渲染router
配置路由相关的信息,比如在客户端渲染可以配置hash路由 router: { options: { hashMode: false } }
alias
路径别名 modules
配置Nuxt扩展的模块,比如@pinia/nuxt
@nuxt/image
routeRules
定义路由规则,可以更改路由的渲染模式或分配基于路由缓存策略builder
指定使用Vite还是Webpack来构建应用,默认是Vite,如切换为Webpack还需要安装额外依赖runtimeConfig
: 定义环境变量,比如:运行时需要指定的私有/公共的token等appConfig
: 定义公共变量,比如:构建时确定的公共token、网站配置等针对他们的比较,官方文档提供了一个表格可以参阅:
Feature | runtimeConfig | app.config |
---|---|---|
Client Side | Hydrated | Bundled |
Environment Variables | ✅ Yes | ❌ No |
Reactive | ✅ Yes | ✅ Yes |
Types support | ✅ Partial | ✅ Yes |
Configuration per Request | ❌ No | ✅ Yes |
Hot Module Replacement | ❌ No | ✅ Yes |
Non primitive JS types | ❌ No | ✅ Yes |
Nuxt为我们扩展了Node的process对象,并为我们在浏览器环境提供了process对象:
dev
server
client
以供使用typeof window === 'object'
检查是服务器环境/浏览器环境Nuxt会自动为我们:注册组件、注册页面路由,约定>配置
pages/
下的页面都会被注册路由 components/
下的组件都会被自动全局注册Nuxt3 框架提供了一些内置的组件,常用的如下:
pages/
.html
文件中文件目录即路由,,可以手动创建 也可以通过命令行快速创建页面
npx nuxi pages category/index
: 创建pages/category/index.vue
npx nuxi pages home/index
: 创建pages/home/index.vue
npx nuxi pages detail/[id]
: 创建pages/detail/[id].vue
动态路由
页面路由
Nuxt提供了一个可定制的路由中间件,用来监听路由的导航,包括:局部和全局监听
definePageMeta
定义middleware
目录下定义,会自动加载中间件middleware
目录中,需要带.global
后缀的文件,每次路由更改会自动运行Nuxt支持对每个页面路由进行验证,可以通过definePageMeta
中的validate
数学对路由进行验证
route
作为参数 false
拦截路由 默认重定向到404页面true
放行路由 正常跳转{ statusCode: 401 }
返回自定义的 401 页面 验证失败error.vue
Layout布局是页面的包装器,可以将多个页面共性的东西抽取到Layout布局中
例如:每个页面的页眉和页脚,这些具有共性的组件,我们可以写到一个Layout布局中
本质上是Vue3的<slot>
组件
layouts/default.vue
app.vue
中通过内置组件<NuxtLayout>
使用layouts/custom-layout.vue
app.vue
中,为<NuxtLayout>
传入name
属性(具名插槽)浏览器和服务器都可以解释JavaScript代码,都可以将Vue.js组件呈现为HTML元素,此过程称为渲染
而Nuxt3支持多种渲染模式
ssr
选项,可以选择以SSR模式渲染,还是CSR方式渲染routeRules
根据每个路由动态配置渲染模式