介绍

单页应用程序 (SPA) 由最初提供给客户端的单个 HTML 文档组成。应用程序中所需的任何新视图都通过 JavaScript 在客户端上单独生成。请求-响应循环仍然会发生,但这通常仅适用于数据的 RESTful API;或获取静态资源,如图像。

以这种方式编写应用程序有很多好处。但是,您会失去一些东西,例如网络爬虫遍历您的应用程序的能力以及在加载应用程序时会降低性能,这可能需要大量时间。在谈到服务器端渲染 (SSR),以缩小差距。

在本文中,您将学习如何使用 Angular Universal 进行服务器端渲染。

先决条件

要学习本教程,您需要:

本教程已通过 Node v16.4.2、npmv7.19.1、@angular/corev12.1.1 和 @nguniversal/express-enginev12.1.0 验证。

第 1 步 — Angular Universal 入门

Angular 应用程序是一个单页应用程序 – 它在客户端的浏览器中运行。然而,Angular Universal 还允许您在服务器上运行您的 Angular 应用程序。这使您能够向客户端提供静态 HTML。使用 Angular Universal,服务器将预渲染页面并向您的用户显示一些内容,而客户端应用程序则在后台加载。然后,一旦客户端一切准备就绪,它将无缝地从显示服务器呈现的页面切换到客户端应用程序。您的用户不应该注意到差异,除了等待您的“加载”微调器完成之外,他们至少可以有一些内容来保持他们的参与,直到他们可以开始使用功能齐全的客户端应用程序。

使用 Angular Universal 的 SSR 需要在客户端应用程序和服务器堆栈中进行更改才能工作。对于本文,我们假设这是一个全新的 Angular 应用程序,几乎不使用 Angular CLI 创建,版本 >= 7。几乎任何服务器技术都可以运行 Universal 应用程序,但它必须能够调用 renderModuleFactory()Angular Universal 提供的特殊函数,它本身就是一个 Node 包;所以从 Node/Express 服务器为这个 Angular 应用程序提供服务对于这个例子是有意义的。

我们将使用一个示意图来让我们快速上手。

从您的应用程序目录打开终端并运行以下命令:

ng add @nguniversal/express-engine

复制

您会注意到此示意图对您的应用程序进行了几处更改,修改了一些文件并添加了一些文件:

更新 angular.json

  • projects.{{project-name}}.architect.build.options.outputPath 更改为 "dist/browser"
  • projects.{{project-name}}.architect添加了一个新的,称为"server"

这让 Angular CLI 知道我们的 Angular 应用程序的服务器/通用版本。

更新 package.json

除了一些新的依赖项(在意料之中),我们还得到了一些新的脚本:

  • "dev:ssr"
  • "build:ssr"
  • "serve:ssr"
  • "prerender"

更新 main.ts

这已经过修改,因此在通用渲染页面完全加载之前,应用程序的浏览器版本不会开始引导。

更新 app.module.ts

修改为 .withServerTransition在导入的 BrowserModule. 这告诉应用程序的浏览器版本,客户端将在某个时候从服务器版本转换进来。

创造 server.ts

这是 NodeJS Express 服务器。显然,您不必使用生成的这个确切的服务器设置,但请注意以下行:

server.engine('html', ngExpressEngine({ ... }))

复制

ngExpressEngine是一个 renderModuleFactory使 Universal 工作的包装器。如果您不使用此确切 server.ts文件进行设置,请至少复制此部分并将其集成到您的文件中。

创造 tsconfig.server.json

这告诉 Angular 编译器在哪里可以找到通用应用程序的入口模块。

创造 app.server.module.ts

这只是服务器版本的根模块。你可以看到它导入我们的 AppModule,还有 ServerModule@angular/platform-server,并引导了相同 AppComponentAppModuleAppServerModule是通用应用程序的入口点。

创造 main.server.ts

这个新文件基本上只导出 AppServerModule,这是应用程序通用版本的入口点。我们很快就会重新审视这个问题。

第 2 步 – 启动您的通用应用程序

从命令行,运行以下命令:

npm run build:ssr

复制

然后运行:

npm run serve:ssr

复制

假设您在构建过程中没有遇到任何问题,打开您的浏览器 http://localhost:4000(或为您配置的任何端口),您应该会看到您的通用应用程序在运行!它看起来没有任何不同,但第一页的加载速度应该比常规的 Angular 应用程序快得多。如果您的应用程序小而简单,则可能很难注意到这一点。

您可以通过打开 Chrome Dev Tools 并在 Network 选项卡下找到显示Online 的下拉菜单来尝试限制网络速度。选择慢速 3G 以模拟慢速网络上的设备 – 您应该仍然看到着陆页和您转到的任何路由页面的良好性能。

此外,尝试查看页面源代码(右键单击页面并选择查看页面源代码 )。您将在 <body>标记中看到与您的页面上显示的内容相匹配的所有普通 HTML – 这意味着,您的应用程序可以被网络爬虫有意义地抓取。将此与非通用应用程序的页面源进行比较,您将在 <body>标记中看到的所有内容是 <app-root>(或任何您为 bootstrapped 调用的选择器 AppComponent)。

结论

在本文中,您学习了如何使用 Angular Universal 进行服务器端渲染。

由于通用应用程序在服务器上运行而不是在浏览器中运行,因此您需要在应用程序代码中注意以下几点:

  • 请检查您的浏览器特定的对象,如使用windowdocumentlocation。这些在服务器上不存在。无论如何你不应该使用这些;尝试使用可注入的 Angular 抽象,例如DocumentLocation。作为最后的手段,如果您确实需要它们,请将它们的用法包装在条件语句中,以便它们只能由浏览器上的 Angular 使用。您可以通过导入函数isPlatformBrowserisPlatformServerfrom @angular/common、将PLATFORM_ID令牌注入您的组件并运行导入的函数来查看您是在服务器上还是浏览器上来完成此操作。
  • 如果您使用ElementRef来获取 HTML 元素的句柄,请不要使用nativeElement来操作元素上的属性。相反,注入Renderer2使用其中的一种方法
  • 浏览器事件处理不起作用。在服务器上运行时,您的应用程序不会响应单击事件或其他浏览器事件。但是,从 a 生成的任何链接routerLink都可以用于导航。
  • setTimeout尽可能避免使用。
  • 将服务器请求的所有 URL 设为绝对。从服务器运行时,来自相对 URL 的数据请求将失败,即使服务器可以处理相对 URL。
  • 同样,从服务器发出的 HTTP 请求的安全性与从浏览器发出的请求的安全性不同。服务器请求可能具有不同的安全要求和功能。您必须自己处理这些请求的安全性。

继续了解 Angular Universal 在官方文档中提供的内容。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注