由于Angular Universal不会在CLI中呆一段时间,因此我必须使用Prerender.io允许SEO正常工作。但是,经过一些测试后,它似乎并没有那么出色,因为它似乎没有等待懒惰的加载模块,因此SEO仍然失败。
在此位置的网站上,他们这样说:
您的页面只是部分渲染吗?
我们的Prerender Server尽力确定页面何时完成 通过计算飞行中的请求数来加载。一旦数字 在飞行中的请求达到零,我们等待一小段时间 然后保存HTML。如果这太早保存页面,您可以使用 我们的window.prerenderready标志通知服务器您的页面是 准备保存。
将其放入您的html:
<script> window.prerenderReady = false; </script>
当我们看到window.prerenderready设置为false时,我们将等到它 设置为true保存HTML。当您的页面是 准备就绪(通常在Ajax呼叫后):
window.prerenderReady = true;
这是我不明白该怎么做的地方。由于Angular从模板中删除脚本标签(不确定这只是CLI行为还是Angular本身),因此我无法设置初始脚本标签。我也无法弄清楚如何从组件类中的模板脚本标签中更新window
属性prerenderReady
,因为我不能仅使用window.prerenderReady = true
并期望它可以正常工作,因为必须将脚本添加到模板中。
是否有人设法弄清楚这个问题或对我如何实现这一目标有任何想法?
remove: server.use(prerender.removeScriptTags());
prerender.io可以设置为留在脚本中,以便它们可以运行。
我的Meteor-Angular2设置给了我同样的悲伤。我的标题和页脚模块会呈现,但不会输出路由器输出。我放置:
<script> window.prerenderReady = false; </script>
在我的主index.html上(包含主<app></app>
标签),并放置:
window.prerenderReady = true;
在我上次回调结束时。然后我评论了:
//server.use(prerender.removeScriptTags());
在我的Prerender Server的服务器中 - 最终正确渲染。
好吧,我做了这个工作,但是这似乎是一个相当复杂的解决方案,所以希望有人比我更聪明:)
首先, src/polyfills.ts
中的所有浏览器polyfills(可能不是所有浏览器都需要,但我尚未一对一测试它们):
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
接下来,您需要在index.html
的<head>
中获得prerenderReady
标志。Angular不会剥离评论,因此在建造之前,我会在其中留一个旗帜:
<head>
<!--prerender-->
</head>
现在,运行ng build
后,您需要用实际的脚本标签替换该标志。我使用Shell脚本和sed
命令来执行此操作。类似:
TPL="<!--prerender-->"
PRERENDER_SCRIPT="<script>window.prerenderReady = false;</script>"
# replace the comment with the actual script tag in the html file and save
# that file's contents as a string in the INDEX_HTML variable
INDEX_HTML=$(sed "s/$TPL/$PRERENDER_SCRIPT/g;" dist/browser/index.html);
# remove the original index.html file and create an empty one in its place
rm dist/browser/index.html
touch dist/browser/index.html
# echo the INDEX_HTML string into the new file
echo "$INDEX_HTML" > dist/browser/index.html
注意我对OSX上安装sed
的安装有模糊的回忆,但我真的不记得这些步骤。如果您不在Linux上,并且sed
对您不起作用,那么您只需要搜索解决方案即可。
最后,您需要将该prerenderReady
标志设置为True某个地方。我在AppComponent
的OnInit
实现中这样做:
export class AppComponent implements OnInit
{
ngOnInit()
{
window.prerenderReady = true;
}
}
它可能还提到要在打字稿应用中使用window
,您需要在文件中使用类似的内容,我调用typings.d.ts
:
interface Window
{
prerenderReady:boolean;
}
以及对我放在app.module.ts
文件顶部的该输入文件的引用:
/// <reference path="../typings.d.ts" />
希望能帮助某人。
我建议在使用angular.json或编辑WebPack构建注入Angular JS文件之前,将第一个脚本放在页面顶部的index.html中。window.prerenderready = false
然后在主app.ts文件中,获取对窗口对象的引用,然后put window.prerenderready = true ngonviewinit hook:
public ngAfterViewInit(): void {
this.windowReference.prerenderReady = true;
}