Angular 中的预渲染——第二部分

Angular 中的预渲染——第二部分

单一多语言版本

今天我们将继续我们之前的努力 在 Angular 中替换 i18n 包 ,并调整我们的 Express 服务器以生成每种语言的多个静态页面。计划是:

  1. 适应多语言支持,URL 驱动
  2. 测试 APP_BASE_URL 支持
  3. 适应以使其运行于 cookie 驱动的应用程序
  4. 查看 Firebase Netlify 和 Surge 支持

多语言 URL 驱动的应用程序

以终为始进行规划,我们需要用不同的语言文件夹创建相同的路由,所以 /client/projects/index.html 需要坐在里面 /client/en/projects/index.html .为此,我们需要调整我们的 fetch 模块,以遍历所有支持的语言。

注意:如果你有多个构建(根据默认的 Angular 行为),输出目录将被交换。例如: /en/static/projects/index.html

 // 主机/预渲染/fetch.js  
 // 支持的语言示例,可能应该在配置文件中  
 const 语言= ['in', 'yes', 'tr']; // 通过接受语言来适应  
 异步函数 renderToHtml(lang, route, port, outFolder) {  
 // 适配以 URL 为前缀的语言调用 fetch  
 const response = await fetch(`http://localhost:${port}/${lang}/${route}`);  
 // ... // 适应放置在 /client/static/en/route/index.html  
 常量 d = `${outFolder}${lang}/${route}`;  
 // ...  
 } module.exports = 异步(端口)=> {  
 // ...  
 // 适应循环语言  
 for (const lang of 语言) {  
 for (const route of routes) {  
 等待 renderToHtml(lang, route, port, prerenderOut);  
 }  
 }  
 };

我们的 Express 规则不需要改变,只要我们的 基础href value 设置为正确的语言,这是预期的行为 URL 驱动的应用程序 .

 module.exports = 功能(应用程序){  
 // 只要将基本 href 设置为正确的语言文件夹,此规则就成立  
 // 例如“/en/”  
 app.use('/', express.static(rootPath + 'client/static'));  
 // ... 其他路线  
 }

运行服务器,浏览到 http://localhost:port/en/projects ,禁用 JavaScript,然后进行测试。您应该看到文件的静态版本。

获取脚本在 StackBlitz 上 .

APP_BASE_HREF 令牌

这与 URL 驱动的应用程序完全一样,不同之处在于 基础href 设置为根 / .无需适应。阅读有关此解决方案的信息 使用 Angular APP_BASE_HREF .

Cookie 驱动的应用程序

不推荐基于 cookie 值的单一构建应用程序。尽管如此,让我们深入研究一下。需要调整两点:

  • 在预渲染之前设置 cookie 拿来 (不允许)
  • 在为我们的网站提供服务之前检查物理文件

在 fetch 中,我们不允许设置 cookie 标头,但我们可以解决设置不同的标头。然后在语言中间件中,我们检查该标头值以及其他因素。

 // 预渲染/fetch.js  
 // 调整函数以设置自定义标题  
 异步函数 renderToHtml(lang, route, port, config) {  
 const response = await fetch(`http://localhost:${port}/${route}`,  
 {  
 标题:{'cr-lang':lang}  
 }); // ... 其余的,像往常一样保存在不同的语言文件夹中  
 // ... 输出索引文件的基本 href 设置为 '/'  
 }

我们只需要捕获中间件中的标头即可知道要服务哪个索引

 // language.js 中间件,调整值以读取“自定义标头”  
 // 在解析为 cookie 之前,然后解析为默认值  
 res.locals.lang = req.get('cr-lang') || req.cookies['cr-lang'] || '恩';

上面的语言循环在语言文件夹中生成静态文件,就像在 URL 驱动的应用程序中一样,除了生成的 基础href , 设置为根 / .现在要提供这些文件,Express 路由需要物理匹配它们,这可以通过中间件来完成(比如 服务静态中间件 ),但在这里我们将保持简单:

 // 为 cookie 驱动的应用表达路由  
 // ...  
 const { existsSync } = require('fs'); app.get('/*', (req, res) => {  
 // 首先找到物理页,相对于 __dirname 和 routes 文件  
 // res.locals.lang 假定由中间件 cookie reader 设置  
 // 如果在 Angular 中使用,去掉 URL 参数 ";param=something"  
	     
 const static = rootPath + 'client/static/' + res.locals.lang + req.path.split(';')[0] + '/index.html';  
 如果(存在同步(静态)){  
 res.sendFile(静态);  
 返回;  
 }  
 // 然后渲染 Angular SSR(前一篇文章)  
 res.render(rootPath + `index/index.${res.locals.lang}.html`, {  
 要求,  
 资源  
 }); });

不幸的是,在 StackBlitz 中,我无法设置 cookie 也无法检测自定义标头来测试预渲染功能,但我确认它在本地工作。

基于 cookie 的应用程序在 StackBlitz 上 .

云托管

公共主机的主要区别是缺乏强大的 Express 静态中间件 ,但解决方案是简单地保存文件,在 客户 (公共)文件夹。因此,如果您托管在 Firebase、Netlify 和 Surge 上,唯一的区别就是拥有 预渲染输出 文件夹设置为 客户 .但是,您仍然必须至少在本地创建一个 SSR,才能生成预渲染文件。所以没有办法让本地 Express 服务器运行它。出色地, 有一种方法。 这将使努力更小。 Angular 构建器 使用 渲染模块 .这得等下一集了。

感谢您继续阅读,如果您发现任何需要打磨的标记,请告诉我。

关于无服务器功能

如果您在无服务器功能(如 Firebase)下将 SSR 托管在云上,这与 Express 服务器一样好。您可以使用 Express 静态中间件公开您的静态文件夹,并在本地运行 firebase 模拟器:

firebase 模拟器:开始

然后你运行一个单独的 express 脚本来简单地获取已经运行的 firebase 应用程序(通常在端口 5000 )。像这样:

 // 在 firebase 模拟器运行时运行的简单脚本 /prerender/serverless.js  
 const config = require('../server/config');  
 const prerender = require('./fetch-url'); 异步函数行为(端口){  
 等待预渲染(端口,配置);  
 console.log('完成预渲染');  
 } 法案(5000);

这不会关闭端口,而且比尝试运行更容易 火力基地 从节点。

cd prerender && node serverless

代码在 StackBlitz .

Angular 系列中的预渲染:

  1. 在 Express 服务器中为 Angular 预渲染路由——第一部分
  2. Angular 中的预渲染——第二部分

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/39378/40092611

posted @ 2022-09-26 11:42  哈哈哈来了啊啊啊  阅读(61)  评论(0编辑  收藏  举报