We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
说到服务端渲染,会先想问客户端渲染是什么
客户端渲染是我们最常用的渲染方式了,我们用的 vue ,react 这些框架实现的页面,整个加载js脚本和执行js脚本最后再展示出来UI的过程就是客户端渲染
服务端渲染就是在浏览器请求页面URL的时候,服务端将我们需要的HTML文本组装好,并返回给浏览器,这个HTML文本被浏览器解析之后,不需要经过 JavaScript 脚本的执行,即可直接构建出希望的 DOM 树并展示到页面中
网页爬虫也分低级爬虫和高级爬虫。
相对于客户端渲染,服务端渲染在浏览器请求URL之后已经得到了一个带有数据的HTML文本,浏览器只需要解析HTML,直接构建DOM树就可以。而客户端渲染,需要先得到一个空的HTML页面,这个时候页面已经进入白屏,之后还需要经过加载并执行 JavaScript、请求后端服务器获取数据、JavaScript 渲染页面几个过程才可以看到最后的页面。特别是在复杂应用中,由于需要加载 JavaScript 脚本,越是复杂的应用,需要加载的 JavaScript 脚本就越多、越大,这会导致应用的首屏加载时间非常长,进而降低了体验感。
理想的情况,我们肯定希望自己的项目不仅能保持原本的方式运行,又能支持SSR在服务端也正常运行,这时候就需要进行同构
假如现在有一个项目是使用 vue 开发的,一个常规的场景
当我们打开一个页面时,首先是打开这个页面的URL,这个URL,可以通过应用的路由匹配,找到具体的页面,不同的页面有不同的视图
在这个场景中,我们同构的重点就在将以下的几步能在服务端中能执行
1、路由模块的初始化
2、组件的render过程
3、data或者store的挂载
todo
SSR 的集大成框架
**基于文件的路由:**根据pages/目录的结构定义路由。这样可以更容易地组织应用程序,避免手动配置路由的需要。
**内置服务器端渲染:**Nuxt具备内置的服务器端渲染能力,因此你不需要自己设置单独的服务器。
**自动导入:**在各自的目录中编写Vue组件和可组合函数,并在使用时无需手动导入,享受树摇和优化JS捆绑包的好处。
**数据获取工具:**Nuxt提供了可用于处理与服务器端渲染兼容的数据获取的可组合函数,以及不同的策略。
零配置的TypeScript支持: 可以编写类型安全的代码,无需学习TypeScript,因为我们提供了自动生成的类型和tsconfig.json配置文件。
配置好的构建工具: 使用Vite来支持开发中的热模块替换(HMR),以及在生产中将代码打包成符合最佳实践的形式。
性能优化:
**代码分割:**Nuxt自动将代码拆分成较小的块,这有助于减少应用程序的初始加载时间。意味着只有访问特定页面时,才会加载该页面的脚本。这种自动代码分割减少了首屏加载时需要下载的资源量,加快了页面加载速度。
**图片优化:**使用 Nuxt.js 的 @nuxt/image 模块可以自动优化图片大小和格式,根据浏览器的支持情况选择最佳的图片格式,并提供懒加载等特性。图片优化可以显著减少页面体积和加载时间。
**支持vue异步组件:**异步加载某些不是立即需要的组件可以减少初始加载时间。Nuxt.js 支持 Vue.js 的异步组件,允许开发者根据需要动态加载组件。
**页面缓存和数据预取:**在服务端渲染期间预先获取页面所需数据,可以减少客户端请求和等待时间;使用服务器端缓存来存储渲染好的页面,以便于快速响应后续的请求。
流式渲染:传输来的 HTML 不需要等待整个html下载完成、吐出来的 html 流数据在浏览器上可以渐进地渲染出来,呈现给用户。
example
静态站点生成 (Static-Site Generation,缩写为 SSG),也被称为预渲染。如果用服务端渲染一个页面所需的数据对每个用户来说都是相同的,那么我们可以只渲染一次,提前在构建过程中完成,而不是每次请求进来都重新渲染页面。预渲染的页面生成后作为静态 HTML 文件被服务器托管。
如何将自己的站点升级为 SSG
1、使用 nuxt ,执行****nuxt build --prerender
打包后的文件目录树
**2、**VitePress 静态生成
VitePress 是一个静态站点生成器 ,专为构建快速、以内容为中心的站点而设计。简而言之,VitePress 获取用 Markdown 编写的内容,对其应用主题,并生成可以轻松部署到任何地方的静态 HTML 页面。
3、使用****Puppeteer 。在项目构建成功之后,通过无头浏览器,在构建服务器中动态访问指定的路由,并将页面的 html 吐出来
// packages { "name": "innereye_frontend", "version": "1.0.0", "prerender": ["page1", "page2"] } // webpack 插件 PrerenderSPAPlugin.prototype.apply = function (compiler) { const { prerender } = getPkgConfig(); const afterEmit = (compilation, done) => { routes.map( // 限制 promise 数量的一个小方法,防止太多页面导致内存爆炸 (route, index) => limiter(async () => { const page = await this._puppeteer.newPage(); // 注入 window 全局对象,标记当前处于预渲染环境 if (options.inject) { await page.evaluateOnNewDocument( `(function () { window['${ options.injectProperty }'] = ${JSON.stringify(options.inject)}; })();` ); } const baseURL = `http://localhost:${rootOptions.server.port}`; // 设置视窗大小 if (options.viewport) await page.setViewport(options.viewport); // 由使用方配置 renderAfterDocumentEvent 并在合适的时候 new Event(renderAfterDocumentEvent) if (options.renderAfterDocumentEvent) { page.evaluateOnNewDocument(function (options) { window["__PRERENDER_STATUS"] = {}; // https://developer.mozilla.org/zh-CN/docs/Web/API/Event // 使用浏览器的原生事件方式, document.addEventListener( options.renderAfterDocumentEvent, () => { // 可以准备把内容导出了 window["__PRERENDER_STATUS"].__DOCUMENT_EVENT_RESOLVED = true; } ); }, this._rendererOptions); } // 设置一下网络配置 const navigationOptions = options.navigationOptions ? { waituntil: "networkidle0", ...options.navigationOptions } : { waituntil: "networkidle0" }; // 打开页面 await page.goto(`${baseURL}${route}`, navigationOptions); // Wait for some specific element exists const { renderAfterElementExists } = this._rendererOptions; if ( renderAfterElementExists && typeof renderAfterElementExists === "string" ) { await page.waitForSelector(renderAfterElementExists); } // 在页面注入一个方法,因为在前面注入了一个 // 当触发生成的时候,window['__PRERENDER_STATUS'].__DOCUMENT_EVENT_RESOLVED // 会被标记为 true ,然后会触发下面这个 promise ,在这个页面执行完成,就有页面内容了 await page.evaluate(function (options) { options = options || {}; return new Promise((resolve, reject) => { if (options.renderAfterDocumentEvent) { // 如果很快就产生了文件,就可以直接 resolve 了 if ( window["__PRERENDER_STATUS"] && window["__PRERENDER_STATUS"].__DOCUMENT_EVENT_RESOLVED ) { resolve(); } // 不然就自己再监听一遍 document.addEventListener( options.renderAfterDocumentEvent, () => resolve() ); } }); }, this._rendererOptions); // 产出页面的基本内容 const rpath = await page.evaluate("window.location.pathname") const result = { originalRoute: route, route: rpath, html: await page.content(), }; await page.close(); compilerFS.writeFile('prerender/' + rpath + '.html', res.html) }) ); }; if (compiler.hooks) { const plugin = { name: "PrerenderSPAPlugin" }; compiler.hooks.afterEmit.tapAsync(plugin, afterEmit); } else { compiler.plugin("after-emit", afterEmit); } };
上述生成之后的文件列表 dist
修改 nginx 的代理配置
// nginx 配置 server { listen 80; server_name www.damin.com; location ~ ^/project_name/(.+)$ { # 定义本地文件的路径 root dist; # 替换为 pages 文件夹所在的父目录路径 # 将 URL 的最后一部分映射为文件名 rewrite ^/project_name/(.+)$ /prerender/$1.html break; # 尝试访问文件 try_files $uri =404; } # 错误处理(可选) error_page 404 /404.html; # 自定义 404 页面,如果需要 }
如果项目用了 vue-router ,有 about ,home 等 path 在访问到 www.damin.com/xxxxx/home 的时候,就可以被转发到 prerender 返回里面的 html 文件内容了,如果仅仅针对部分路由处理,那就是对部分路由的 ssg
参考资料:
书写友好的 ssr:https://cn.vuejs.org/guide/scaling-up/ssr#writing-ssr-friendly-code
nuxt文档:https://nuxt.com.cn/docs/getting-started/introduction
nuxt3重构实践:https://blog.csdn.net/qq_38974163/article/details/131420984
nuxt3加载优化:https://inx.fun/article/876
The text was updated successfully, but these errors were encountered:
No branches or pull requests
页面渲染流程
页面的渲染其实就是浏览器将HTML文本转化为页面帧的过程
服务端渲染
说到服务端渲染,会先想问客户端渲染是什么
客户端渲染是我们最常用的渲染方式了,我们用的 vue ,react 这些框架实现的页面,整个加载js脚本和执行js脚本最后再展示出来UI的过程就是客户端渲染
服务端渲染就是在浏览器请求页面URL的时候,服务端将我们需要的HTML文本组装好,并返回给浏览器,这个HTML文本被浏览器解析之后,不需要经过 JavaScript 脚本的执行,即可直接构建出希望的 DOM 树并展示到页面中
为什么要用服务端渲染
SEO
网页爬虫也分低级爬虫和高级爬虫。
也就是说,低级爬虫对客户端渲染的页面来说,简直无能为力,因为返回的HTML是一个空壳,它需要执行 JavaScript 脚本之后才会渲染真正的页面。目前还是有一部分年代老旧的爬虫还属于低级爬虫,使用服务端渲染,对这些低级爬虫更加友好一些,SEO总体上也能更好地提升
白屏时间更短
相对于客户端渲染,服务端渲染在浏览器请求URL之后已经得到了一个带有数据的HTML文本,浏览器只需要解析HTML,直接构建DOM树就可以。而客户端渲染,需要先得到一个空的HTML页面,这个时候页面已经进入白屏,之后还需要经过加载并执行 JavaScript、请求后端服务器获取数据、JavaScript 渲染页面几个过程才可以看到最后的页面。特别是在复杂应用中,由于需要加载 JavaScript 脚本,越是复杂的应用,需要加载的 JavaScript 脚本就越多、越大,这会导致应用的首屏加载时间非常长,进而降低了体验感。
服务端渲染流程
项目如何改造为SSR
理想的情况,我们肯定希望自己的项目不仅能保持原本的方式运行,又能支持SSR在服务端也正常运行,这时候就需要进行同构
假如现在有一个项目是使用 vue 开发的,一个常规的场景
当我们打开一个页面时,首先是打开这个页面的URL,这个URL,可以通过应用的路由匹配,找到具体的页面,不同的页面有不同的视图
在这个场景中,我们同构的重点就在将以下的几步能在服务端中能执行
1、路由模块的初始化
2、组件的render过程
3、data或者store的挂载
todo
Nuxt
SSR 的集大成框架
**基于文件的路由:**根据pages/目录的结构定义路由。这样可以更容易地组织应用程序,避免手动配置路由的需要。
**内置服务器端渲染:**Nuxt具备内置的服务器端渲染能力,因此你不需要自己设置单独的服务器。
**自动导入:**在各自的目录中编写Vue组件和可组合函数,并在使用时无需手动导入,享受树摇和优化JS捆绑包的好处。
**数据获取工具:**Nuxt提供了可用于处理与服务器端渲染兼容的数据获取的可组合函数,以及不同的策略。
零配置的TypeScript支持: 可以编写类型安全的代码,无需学习TypeScript,因为我们提供了自动生成的类型和tsconfig.json配置文件。
配置好的构建工具: 使用Vite来支持开发中的热模块替换(HMR),以及在生产中将代码打包成符合最佳实践的形式。
性能优化:
**代码分割:**Nuxt自动将代码拆分成较小的块,这有助于减少应用程序的初始加载时间。意味着只有访问特定页面时,才会加载该页面的脚本。这种自动代码分割减少了首屏加载时需要下载的资源量,加快了页面加载速度。
**图片优化:**使用 Nuxt.js 的 @nuxt/image 模块可以自动优化图片大小和格式,根据浏览器的支持情况选择最佳的图片格式,并提供懒加载等特性。图片优化可以显著减少页面体积和加载时间。
**支持vue异步组件:**异步加载某些不是立即需要的组件可以减少初始加载时间。Nuxt.js 支持 Vue.js 的异步组件,允许开发者根据需要动态加载组件。
**页面缓存和数据预取:**在服务端渲染期间预先获取页面所需数据,可以减少客户端请求和等待时间;使用服务器端缓存来存储渲染好的页面,以便于快速响应后续的请求。
流式渲染:传输来的 HTML 不需要等待整个html下载完成、吐出来的 html 流数据在浏览器上可以渐进地渲染出来,呈现给用户。
example
服务端渲染会带来更大的心智负担
所以在使用服务端渲染SSR之前,需要开发者考虑投入产出比,比如大部分应用系统都不需要SEO,而且首屏时间并没有非常的慢,如果使用SSR反而小题大做了
SSG
静态站点生成 (Static-Site Generation,缩写为 SSG),也被称为预渲染。如果用服务端渲染一个页面所需的数据对每个用户来说都是相同的,那么我们可以只渲染一次,提前在构建过程中完成,而不是每次请求进来都重新渲染页面。预渲染的页面生成后作为静态 HTML 文件被服务器托管。
如何将自己的站点升级为 SSG
1、使用 nuxt ,执行****nuxt build --prerender
打包后的文件目录树
**2、**VitePress 静态生成
VitePress 是一个静态站点生成器 ,专为构建快速、以内容为中心的站点而设计。简而言之,VitePress 获取用 Markdown 编写的内容,对其应用主题,并生成可以轻松部署到任何地方的静态 HTML 页面。
3、使用****Puppeteer 。在项目构建成功之后,通过无头浏览器,在构建服务器中动态访问指定的路由,并将页面的 html 吐出来
上述生成之后的文件列表 dist
修改 nginx 的代理配置
如果项目用了 vue-router ,有 about ,home 等 path
在访问到 www.damin.com/xxxxx/home 的时候,就可以被转发到 prerender 返回里面的 html 文件内容了,如果仅仅针对部分路由处理,那就是对部分路由的 ssg
参考资料:
书写友好的 ssr:https://cn.vuejs.org/guide/scaling-up/ssr#writing-ssr-friendly-code
nuxt文档:https://nuxt.com.cn/docs/getting-started/introduction
nuxt3重构实践:https://blog.csdn.net/qq_38974163/article/details/131420984
nuxt3加载优化:https://inx.fun/article/876
The text was updated successfully, but these errors were encountered: