mirror of
https://github.com/ZiuChen/ZiuChen.github.io.git
synced 2025-08-18 23:49:33 +08:00
14 lines
27 KiB
JavaScript
14 lines
27 KiB
JavaScript
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":1681736919000}'),i={name:"note/SSR.md"},t=a(`<h1 id="服务端渲染-ssr" tabindex="-1">服务端渲染(SSR) <a class="header-anchor" href="#服务端渲染-ssr" aria-label="Permalink to "服务端渲染(SSR)""></a></h1><ul><li>邂逅SPA和SSR</li><li>Node服务搭建</li><li>Vue3 + SSR搭建</li><li>SSR + Hydration 水合</li><li>Vue SSR + Router</li><li>Vue SSR + Pinia</li></ul><h2 id="邂逅spa和ssr" tabindex="-1">邂逅SPA和SSR <a class="header-anchor" href="#邂逅spa和ssr" aria-label="Permalink to "邂逅SPA和SSR""></a></h2><p>我们使用Vue开发的网页一般都是单页面应用程序(SPA Single Page Application)</p><ul><li>SPA应用是在客户端呈现的,我们称这个渲染过程为CSR(Client Side Rendering)</li><li>常见的B端Web应用开发模式,<strong>渲染工作在客户端进行,服务器压力较轻</strong>,服务器直接返回未经加工的<code>.html</code>文件</li><li>所需要的资源(HTML CSS JS等),在一次请求中就加载完成,首屏时间更长,需要额外的首屏优化</li></ul><p>与之相对的,就是服务端渲染(SSR Server Side Rendering)</p><ul><li>SSR并不是什么新鲜的概念,早期的JSP或PHP就已经体现了服务端渲染的原理</li><li>但是传统开发模式,代码耦合度较高,不容易维护</li></ul><p>于是,同构SSR应运而生,我们称之为BFF(Backend for Frontend 服务于前端的后端)</p><ul><li>前后端一体化,一套Vue / React代码在服务器上运行一遍,在到达浏览器又运行一遍。</li><li>前后端都参与到渲染中,并且首次渲染出的HTML相同</li></ul><p>浏览器请求<code>.html</code>文件 => 服务端运行Vue / React代码并生成<code>.html</code> => 发送<code>.html</code>文件给浏览器 => 浏览器显示网页内容</p><p>=> 浏览器加载JS文件 => 绑定DOM事件 客户端渲染接管界面 => 再次跳转路由就是客户端渲染 无需请求后台</p><h3 id="spa的优点与缺点" tabindex="-1">SPA的优点与缺点 <a class="header-anchor" href="#spa的优点与缺点" aria-label="Permalink to "SPA的优点与缺点""></a></h3><ul><li>SPA的优点 <ul><li>只需要加载一次 更好的用户体验 <ul><li>只有一个<code>.html</code>文件,页面切换不需要重新加载,所以比传统Web应用程序更快</li></ul></li><li>轻松构建功能丰富的Web应用程序</li></ul></li><li>SPA的缺点 <ul><li>SPA应用默认只返回一个空HTML文件,不利于SEO</li><li>首屏加载资源过大,影响首屏渲染速度</li><li>不利于复杂项目构建</li></ul></li></ul><h3 id="seo优化" tabindex="-1">SEO优化 <a class="header-anchor" href="#seo优化" aria-label="Permalink to "SEO优化""></a></h3><ul><li>语义性HTML标记 <ul><li>标题用 <code>h1</code>,一个页面只应当由一个 <code>h1</code> 标签,副标题用 <code>h2 - h6</code></li><li>不要过度使用 <code>h</code> 标签,多次使用不会增加SEO</li><li>段落用 <code>p</code> 标签 列表用 <code>ul</code> 标签,且 <code>li</code> 只放在 <code>ul</code> 中</li></ul></li><li>每个页面都需要包含标题+内部链接 <ul><li>每个页面对应的title,同一个网站所有页面都有内链可以指向首页</li></ul></li><li>保证链接可供抓取 <ul><li><code><a href="https://www.example.com" /></code></li><li><code><a href="/relative/path/file" /></code></li></ul></li><li>meta标签优化:设置description和keywords等</li><li>文本标记和img <ul><li>比如<code><b></code>和<code><strong></code>加粗文本的标签,爬虫会关注到该内容</li><li><code>img</code>标签添加<code>alt</code>属性,图片加载失败时供爬虫读取<code>alt</code>内容</li></ul></li><li>robots.txt 文件,规定爬虫可以访问网址上的哪些页面</li><li>sitemap.xml 站点地图,在站点地图列出所有网页,确保爬虫不会漏掉某些网页</li></ul><h2 id="服务端渲染-ssr-1" tabindex="-1">服务端渲染 SSR <a class="header-anchor" href="#服务端渲染-ssr-1" aria-label="Permalink to "服务端渲染 SSR""></a></h2><p>服务端渲染 SSR (Server Side Rendering)</p><ul><li>页面是在服务端渲染的,用户每请求一个SSR页面,都会先在服务端渲染</li><li>服务端渲染完成后,返回给浏览器呈现,浏览器发现JS脚本,解析脚本,向服务器发起请求,之后网页就可以交互了 <ul><li><code>app = createSSRApp(App)</code> <code>renderToString(app) => App String Html</code></li><li><code>client_bundle.js</code> 客户端通过脚本激活应用程序 让应用程序可以进行交互,这个过程叫水合( Hydration)</li></ul></li><li>Vue Nuxt / React Next.js,SSR应用也称为同构应用(server_bundle.js & client_bundle.js)</li></ul><h3 id="ssr的优点" tabindex="-1">SSR的优点 <a class="header-anchor" href="#ssr的优点" aria-label="Permalink to "SSR的优点""></a></h3><ul><li>更快的首屏渲染速度 <ul><li>浏览器显示静态页面的内容要比JavaScript动态生成的内容快得多</li><li>用户访问首页时立刻返回静态页面内容,而不需要等待浏览器先加载完整个SPA应用的JS代码</li></ul></li><li>更好的SEO <ul><li>爬虫擅长爬取HTML页面,服务端直接返回一个静态的HTML给浏览器</li><li>有利于爬虫快速爬取网页内容,并编入索引,有利于SEO</li></ul></li><li>SSR 应用程序在 Hydration 之后仍然可以保留Web应用程序的可交互性 <ul><li>如:前端路由、响应式数据、虚拟DOM等</li></ul></li></ul><h3 id="ssr的缺点" tabindex="-1">SSR的缺点 <a class="header-anchor" href="#ssr的缺点" aria-label="Permalink to "SSR的缺点""></a></h3><ul><li>SSR 通过需要对服务器进行更多的API调用,在服务端渲染需要消耗更多的服务器资源,成本较高</li><li>100个人访问这个网站,服务器就要为每个人渲染100次</li><li>增加了一定的开发成本,开发者需要关心哪些代码是运行在服务端的,哪些则是运行在浏览器的</li><li>SSR配置站点的缓存通常会比SPA站点要更复杂</li></ul><h3 id="ssr-解决方案" tabindex="-1">SSR 解决方案 <a class="header-anchor" href="#ssr-解决方案" aria-label="Permalink to "SSR 解决方案""></a></h3><ul><li>传统方案:PHP JSP ...</li><li>从0开始,搭建SSR项目:Node+Webpack+Vue/React</li><li>选用现成的框架 <ul><li>React Next.js</li><li>Vue3 + Nuxt3 || Vue2 + Nuxt.js</li></ul></li></ul><h2 id="静态网站生成-ssg" tabindex="-1">静态网站生成 SSG <a class="header-anchor" href="#静态网站生成-ssg" aria-label="Permalink to "静态网站生成 SSG""></a></h2><p>静态网页生成 SSG(Static Site Generate)</p><ul><li>SSG应用在构建阶段就确定了<code>.html</code>页面的内容</li><li>用户访问网站,服务器直接返回<code>.html</code>文件给客户端,相当于一个静态资源</li><li>优点 <ul><li>直接返回静态的<code>html</code>文件,有利于SEO</li><li>相比于SSR,不需要每次请求都由服务端处理,所以可以大幅减轻服务端压力,也可以将文件放到CDN上优化访问速度</li><li>保留了SPA应用的特性,比如前端路由、响应式数据、虚拟DOM等</li></ul></li><li>缺点 <ul><li>如果网站的内容需要更新,那么需要重新构建与部署</li><li>只能生成偏静态的页面,不利于与用户的交互,所有用户获取到的页面都是相同的</li></ul></li><li>哪些应用场景:文档站、个人博客、新闻站点等</li></ul><h3 id="ssr与ssg的优势" tabindex="-1">SSR与SSG的优势 <a class="header-anchor" href="#ssr与ssg的优势" aria-label="Permalink to "SSR与SSG的优势""></a></h3><ul><li>更短的首屏时间 <ul><li>只需要请求一个HTML文件就能展示出页面</li><li>虽然在服务端仍然需要调取相关接口,但是服务器-服务器之间的通信远比客户端快,有时甚至是同一台服务器的本地接口</li><li>不再需要大量的js文件请求,这就使得SSR/SSG可以拥有更短的首屏时间</li></ul></li></ul><h3 id="跨请求状态污染" tabindex="-1">跨请求状态污染 <a class="header-anchor" href="#跨请求状态污染" aria-label="Permalink to "跨请求状态污染""></a></h3><ul><li><p>在SPA中,整个生命周期只有一个App对象实例/一个Router对象实例/一个Store对象实例</p><ul><li>因为每个用户使用SPA时,各自的渲染进程都是在自己的浏览器上独立进行的,这是一种<strong>单例模式</strong></li></ul></li><li><p>然而在SSR的环境下,App模块通常只在</p><p>服务器启动时</p><p>初始化一次,同一个应用模块会在多个服务器请求之间被复用</p><ul><li>单例状态对象也会在多个请求之间被复用:</li><li>某个用户对共享的单例状态进行修改,那么这个状态可能会意外地泄露给另一位正在请求的用户</li><li>我们将这种情况称为:<strong>跨请求状态污染</strong></li></ul></li><li><p>为了避免这种跨请求状态污染,SSR的解决方案是:</p><ul><li>在每个请求中,为整个应用创建一个<strong>全新的实例</strong>,包括后面的Router和Store等实例</li><li>带来的缺点就是:需要消耗更多的服务器资源</li></ul></li></ul><h2 id="nuxt3-系统学习" tabindex="-1">Nuxt3 系统学习 <a class="header-anchor" href="#nuxt3-系统学习" aria-label="Permalink to "Nuxt3 系统学习""></a></h2><ul><li>邂逅Nuxt3</li><li>Nuxt3 初体验</li><li>Nuxt3 全局配置</li><li>Nuxt3 内置组件</li><li>Nuxt3 样式和资源</li><li>Nuxt3 页面和导航</li><li>Nuxt3 动态路由</li></ul><h3 id="认识nuxt3" tabindex="-1">认识Nuxt3 <a class="header-anchor" href="#认识nuxt3" aria-label="Permalink to "认识Nuxt3""></a></h3><ul><li>支持数据双向绑定和组件化:Vue.js</li><li>处理客户端导航:Vue Router</li><li>支持开发中热模块替换、生产环境代码打包:Webpack5 Vite</li><li>兼容旧版浏览器,支持ES6+语法转译:ESBuild</li><li>支持开发环境服务器,支持服务端渲染/API接口转发</li><li>使用<code>h3</code>实现部署<strong>可移植性</strong>(<code>h3</code>是一个极小的高性能http框架) <ul><li>如:支持在Serverless、Worker、Node.js环境中运行</li></ul></li></ul><h3 id="搭建nuxt3环境" tabindex="-1">搭建Nuxt3环境 <a class="header-anchor" href="#搭建nuxt3环境" aria-label="Permalink to "搭建Nuxt3环境""></a></h3><p>使用命令行工具 <code>Nuxi</code> 初始化Nuxt:</p><ul><li><code>npx nuxi init project-name</code></li><li><code>pnpm dlx nuxi init project-name</code></li><li><code>npm install -g nuxi && nuxi init project-name</code></li></ul><p>解读脚手架创建的初始化项目的<code>package.json</code>中的脚本:</p><div class="language-json line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C792EA;">private</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">true,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C792EA;">scripts</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">build</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">nuxt build</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">dev</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">nuxt dev</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">generate</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">nuxt generate</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">preview</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">nuxt preview</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">postinstall</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">nuxt prepare</span><span style="color:#89DDFF;">"</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C792EA;">devDependencies</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#FFCB6B;">nuxt</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">^3.2.0</span><span style="color:#89DDFF;">"</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><ul><li><code>build</code> 构建正式版本,将被输出到<code>.output</code>文件夹</li><li><code>dev</code> 开发环境</li><li><code>generate</code> 打包正式版本项目,但是会预渲染每个路由(<code>nuxt build --prerender</code>)</li><li><code>preview</code> 对打包项目启动本地预览服务器</li><li><code>postinstall</code> 该脚本为NPM的生命周期函数,将在<code>npm install</code>后执行</li></ul><p>针对<code>postinstall</code>中执行的<code>nuxi prepare</code>脚本,官方文档有如下解释:</p><blockquote><p>The <code>prepare</code> command creates a <code>.nuxt</code> directory in your application and generates types. This can be useful in a CI environment or as a <code>postinstall</code> command in your <code>package.json</code>.</p></blockquote><p>执行该脚本后,将在项目根目录创建<code>.nuxt</code>文件夹</p><ul><li>这个文件夹将作为默认构建输出的文件夹</li><li>其中的文件都以<code>.d.ts</code>结尾,是Nuxt的TS类型声明</li></ul><h3 id="配置-configuration" tabindex="-1">配置 Configuration <a class="header-anchor" href="#配置-configuration" aria-label="Permalink to "配置 Configuration""></a></h3><ul><li>通过 <code>nuxt.config.ts</code> 文件,对Nuxt进行自定义配置</li><li><code>runtimeConfig</code> 运行时配置 即定义<strong>环境变量</strong><ul><li>直接定义在 <code>runtimeConfig</code> 中的值,仅在服务端可以访问到 <ul><li>定义在<code>runtimeConfig.public</code>中的变量,在客户端和服务端中都能读取到</li><li>也可以将环境变量定义在<code>.env</code>文件中,优先级<code>.env > runtimeConfig</code><ul><li>以<code>NUXT_</code>开头的会作为私有环境变量读取到运行时</li><li>以<code>NUXT_PUBLIC_</code>开头的会作为公共变量读取到运行时</li></ul></li></ul></li><li><code>appConfig</code> 应用配置,定义在<strong>构建时</strong>确定的公共变量,如 theme <ul><li>配置会和app.config.ts合并,优先级<code>app.config.ts > appConfig</code></li></ul></li><li><code>app</code> app的配置</li><li><code>head</code> 给每个页面设置head信息,也支持useHead配置和内置组件 <ul><li>在这个配置中定义的标签,会注入到所有页面的head标签中</li><li>也可以在某些页面动态插入head标签内容 使用<code>useHead</code>函数</li><li>或者在template中使用Nuxt的内置组件<code>Head</code></li></ul></li><li><code>ssr</code> 指定应用渲染模式 <ul><li>默认值为true 即采用SSR方式渲染应用</li><li>如果指定了<code>ssr: false</code> 则会采用SPA的方式渲染应用,即客户端渲染</li></ul></li><li><code>router</code> 配置路由相关的信息,比如在客户端渲染可以配置hash路由 <ul><li>需要注意的是:SSR并不支持哈希路由</li><li><code>router: { options: { hashMode: false } }</code></li></ul></li><li><code>alias</code> 路径别名 <ul><li>默认已经为我们配置好了一些别名,详情可以参阅文档</li></ul></li><li><code>modules</code> 配置Nuxt扩展的模块,比如<code>@pinia/nuxt</code> <code>@nuxt/image</code></li><li><code>routeRules</code> 定义路由规则,可以更改路由的渲染模式或分配基于路由缓存策略</li><li><code>builder</code> 指定使用Vite还是Webpack来构建应用,默认是Vite,如切换为Webpack还需要安装额外依赖</li></ul></li></ul><h4 id="runtimeconfig-与-appconfig" tabindex="-1">runtimeConfig 与 appConfig <a class="header-anchor" href="#runtimeconfig-与-appconfig" aria-label="Permalink to "runtimeConfig 与 appConfig""></a></h4><ul><li><code>runtimeConfig</code>: 定义<strong>环境变量</strong>,比如:<strong>运行时</strong>需要指定的私有/公共的token等</li><li><code>appConfig</code>: 定义<strong>公共变量</strong>,比如:<strong>构建时</strong>确定的公共token、网站配置等</li></ul><p>针对他们的比较,官方文档提供了一个表格可以参阅:</p><table><thead><tr><th>Feature</th><th>runtimeConfig</th><th>app.config</th></tr></thead><tbody><tr><td>Client Side</td><td>Hydrated</td><td>Bundled</td></tr><tr><td>Environment Variables</td><td>✅ Yes</td><td>❌ No</td></tr><tr><td>Reactive</td><td>✅ Yes</td><td>✅ Yes</td></tr><tr><td>Types support</td><td>✅ Partial</td><td>✅ Yes</td></tr><tr><td>Configuration per Request</td><td>❌ No</td><td>✅ Yes</td></tr><tr><td>Hot Module Replacement</td><td>❌ No</td><td>✅ Yes</td></tr><tr><td>Non primitive JS types</td><td>❌ No</td><td>✅ Yes</td></tr></tbody></table><p><a href="https://nuxt.com/docs/getting-started/configuration#runtimeconfig-vs-appconfig" target="_blank" rel="noreferrer">runtimeconfig-vs-appconfig</a></p><h4 id="区分client和server环境" tabindex="-1">区分Client和Server环境 <a class="header-anchor" href="#区分client和server环境" aria-label="Permalink to "区分Client和Server环境""></a></h4><p>Nuxt为我们扩展了Node的process对象,并为我们在浏览器环境提供了process对象:</p><ul><li>Nuxt会在服务端的process对象中注入属性<code>dev</code> <code>server</code> <code>client</code>以供使用</li><li>也会在浏览器网页中注入process对象,包含上述的三个属性</li><li>也可以手动判断<code>typeof window === 'object'</code>检查是服务器环境/浏览器环境</li></ul><h3 id="页面与组件-view-and-component" tabindex="-1">页面与组件 View and Component <a class="header-anchor" href="#页面与组件-view-and-component" aria-label="Permalink to "页面与组件 View and Component""></a></h3><p>Nuxt会自动为我们:注册组件、注册页面路由,<em>约定>配置</em></p><ul><li>位于<code>pages/</code>下的页面都会被注册路由 <ul><li>路由使用内置组件NuxtPage占位,相当于router-view</li><li>相对应的,可以使用NuxtLink执行跳转,相当于router-link</li><li>因为底层是vue-router,所以动态路由、嵌套路由都是支持的</li></ul></li><li>位于<code>components/</code>下的组件都会被自动全局注册</li></ul><h4 id="nuxt3-内置组件" tabindex="-1">Nuxt3 内置组件 <a class="header-anchor" href="#nuxt3-内置组件" aria-label="Permalink to "Nuxt3 内置组件""></a></h4><p>Nuxt3 框架提供了一些内置的组件,常用的如下:</p><ul><li>SEO组件:Html Body Head Title Meta Style Link NoScript Base <ul><li>这些组件的作用是,向页面中不同部分插入标签,在SSR的过程中渲染出来并返回给客户端</li><li>这样爬虫就会在同步获取页面数据时获取到这些标签</li></ul></li><li>NuxtPage:是Nuxt自带的页面占位组件 <ul><li>需要显示位于目录中的顶级或嵌套页面<code>pages/</code></li><li><strong>是对 router-view 的封装</strong></li></ul></li><li>ClientOnly:该组件包裹的内容只会在客户端渲染 <ul><li>其中内容不会出现在服务端返回的<code>.html</code>文件中</li><li>会在客户端通过JS脚本动态渲染出来 <ul><li>类似于Vue3新增的内置组件Suspence</li><li>可以为其传入具名插槽#fallback展示组件被渲染前的加载中状态</li></ul></li></ul></li><li>ServerOnly:该组件包裹的内容只会在服务端渲染</li></ul><h3 id="创建页面" tabindex="-1">创建页面 <a class="header-anchor" href="#创建页面" aria-label="Permalink to "创建页面""></a></h3><p>文件目录即路由,,可以手动创建 也可以通过命令行快速创建页面</p><ul><li><p><code>npx nuxi pages category/index</code>: 创建<code>pages/category/index.vue</code></p></li><li><p><code>npx nuxi pages home/index</code>: 创建<code>pages/home/index.vue</code></p></li><li><p><code>npx nuxi pages detail/[id]</code>: 创建<code>pages/detail/[id].vue</code> 动态路由</p></li><li><p>页面路由</p><ul><li>页面水合之后,页面导航会通过前端路由来实现,可以防止整页刷新</li><li>当然,手动输入URL之后,点击刷新浏览器也可以导航,但这会导致整页刷新</li></ul></li></ul><h4 id="路由中间件" tabindex="-1">路由中间件 <a class="header-anchor" href="#路由中间件" aria-label="Permalink to "路由中间件""></a></h4><p>Nuxt提供了一个可定制的路由中间件,用来<strong>监听路由的导航</strong>,包括:局部和全局监听</p><ul><li>匿名中间件 <ul><li><strong>在页面中</strong>,通过<code>definePageMeta</code>定义</li><li>可以监听局部路由,当注册多个中间件时,会按照注册顺序执行</li><li>首次访问会在双端执行,后续都<strong>只会在客户端执行</strong></li></ul></li><li>命名路由中间件 <ul><li>在<code>middleware</code>目录下定义,会自动加载中间件</li><li>首次访问会在双端执行,后续都<strong>只会在客户端执行</strong></li></ul></li><li>全局路由中间件 <ul><li>在<code>middleware</code>目录中,需要带<code>.global</code>后缀的文件,每次路由更改会自动运行</li><li>与前两者不同,<strong>每次页面切换,双端都会执行全局中间件</strong></li></ul></li></ul><h4 id="路由验证-validate" tabindex="-1">路由验证 Validate <a class="header-anchor" href="#路由验证-validate" aria-label="Permalink to "路由验证 Validate""></a></h4><p>Nuxt支持对每个页面路由进行验证,可以通过<code>definePageMeta</code>中的<code>validate</code>数学对路由进行验证</p><ul><li>validate属性接收一个回调函数,回调函数以<code>route</code>作为参数 <ul><li>此回调返回一个布尔值,来决定是否放行路由 <ul><li><code>false</code> 拦截路由 默认重定向到404页面</li><li><code>true</code> 放行路由 正常跳转</li></ul></li><li>返回一个对象 <ul><li><code>{ statusCode: 401 }</code> 返回自定义的 401 页面 验证失败</li></ul></li></ul></li><li>可以自定义错误页面 <ul><li>在项目根目录 新建<code>error.vue</code></li></ul></li></ul><h3 id="页面布局-layout" tabindex="-1">页面布局 Layout <a class="header-anchor" href="#页面布局-layout" aria-label="Permalink to "页面布局 Layout""></a></h3><p>Layout布局是页面的包装器,可以将多个页面共性的东西抽取到Layout布局中</p><p>例如:每个页面的页眉和页脚,这些具有共性的组件,我们可以写到一个Layout布局中</p><p>本质上是Vue3的<code><slot></code>组件</p><ul><li>默认布局,创建<code>layouts/default.vue</code><ul><li>然后在<code>app.vue</code>中通过内置组件<code><NuxtLayout></code>使用</li></ul></li><li>自定义布局 <ul><li>创建<code>layouts/custom-layout.vue</code></li><li>然后在<code>app.vue</code>中,为<code><NuxtLayout></code>传入<code>name</code>属性(具名插槽)</li></ul></li></ul><h3 id="渲染模式" tabindex="-1">渲染模式 <a class="header-anchor" href="#渲染模式" aria-label="Permalink to "渲染模式""></a></h3><p>浏览器和服务器都可以解释JavaScript代码,都可以将Vue.js组件呈现为HTML元素,此过程称为渲染</p><ul><li>在客户端渲染组件为HTML元素的过程,称为客户端渲染</li><li>在服务端完成这个此操作的过程,称为服务端渲染</li></ul><p>而Nuxt3支持多种渲染模式</p><ul><li>之前在配置文件中提到的<code>ssr</code>选项,可以选择以SSR模式渲染,还是CSR方式渲染</li><li>混合渲染模式(SSR | CSR | SSG | SWR):需要在 <code>routeRules</code> 根据每个路由动态配置渲染模式</li></ul>`,80),s=[t];function n(c,r,d,p,u,h){return e(),o("div",null,s)}const g=l(i,[["render",n]]);export{D as __pageData,g as default};
|