Angular 中的预渲染——第二部分
Angular 中的预渲染——第二部分
单一多语言版本
今天我们将继续我们之前的努力 在 Angular 中替换 i18n 包 ,并调整我们的 Express 服务器以生成每种语言的多个静态页面。计划是:
- 适应多语言支持,URL 驱动
- 测试 APP_BASE_URL 支持
- 适应以使其运行于 cookie 驱动的应用程序
- 查看 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,然后进行测试。您应该看到文件的静态版本。
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
Angular 系列中的预渲染:
- 在 Express 服务器中为 Angular 预渲染路由——第一部分
- Angular 中的预渲染——第二部分
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明