简介
Single-Page Applications(SPA)由最初提供给客户端的_Single_HTML文档组成。应用程序中所需的任何新视图都是通过JavaScript在客户端单独生成的。请求-响应循环仍然会发生,但这通常只适用于REST风格的数据API;或者获取静态资源,如图像。
以这种方式编写应用程序有很多好处。然而,有些东西你会失去,比如网络爬虫遍历你的应用程序的能力,以及当应用程序加载时性能变慢,这可能会花费大量的时间。服务器端渲染(SSR)的出现弥补了这一差距。
在本文中,您将学习如何使用ANGLE Universal进行服务器端呈现。
前提条件
要学习本教程,您需要:
- 本地安装Node.js,可以按照如何安装Node.js并创建本地开发环境操作。
- 熟悉设置Angular项目。
本教程已通过Node v16.4.2、npm
v7.19.1、@angular/core
v12.1.1和@nguniversal/express-engine
v12.1.0验证。
第1步-Angel Universal入门
ANGLE应用程序是一个单页面应用程序--它在客户的浏览器中运行。不过,Angel Universal还允许您在服务器上运行您的Angel应用程序。这使您能够向客户端提供静态HTML。使用ANGLE Universal,服务器将预先呈现页面并向用户显示一些内容,而客户端应用程序则在后台加载。然后,一旦客户端准备就绪,它将从显示服务器呈现的页面无缝切换到客户端应用程序。你的用户应该不会注意到什么不同,除了这样一个事实,即他们至少可以有一些内容来保持他们的参与度,直到他们可以开始使用功能齐全的客户端应用程序,而不是等待你的加载
微调工具完成。
使用Angular Universal的SSR需要在客户端应用程序和服务器堆栈中进行更改才能工作。在本文中,我们假设这是一个全新的Angular应用程序,几乎没有使用Angular CLI创建,版本为version >= 7。几乎任何服务器技术都可以运行Universal应用程序,但它必须能够调用Angular Universal提供的一个特殊函数renderModuleFactory(),它本身就是一个Node包;因此从Node/Express服务器服务这个Angular应用程序对这个例子来说是有意义的。
我们将使用一张示意图来让我们迅速起身。
从应用程序目录中打开一个终端并运行以下命令:
1ng add @nguniversal/express-engine
您会注意到,此示意图对您的应用程序进行了几次更改,修改了一些文件并添加了一些文件:
更新angular.json
projects.{{project-name}}.architect.build.options.outputPath
更改为dist/Browser
- 增加了一个新的
Projects.{{project-name}}.Architecture
,称为服务器
这让ANGLE CLI了解我们的ANGLE应用程序的服务器/通用版本。
更新Package.json
除了一些新的依赖项(不出所料)外,我们还获得了一些新的脚本:
dev:ssr
build:ssr
serve:ssr
预渲染
更新main.ts
这一点已被修改,以便该应用程序的浏览器版本在Universal呈现的页面完全加载之前不会开始引导。
更新app.mode.ts
修改为在导入的BrowserModule
上执行静态方法.with ServerTaketion
。这会告诉应用程序的浏览器版本,客户端将在某个时候从服务器版本转换过来。
创建server.ts
这是NodeJS Express服务器。显然,您不必使用生成的确切服务器设置,但请注意以下行:
1server.engine('html', ngExpressEngine({ ... }))
ngExpressEngineering
是renderModuleFactory
的包装器,它使Universal工作。如果你没有在你的设置中使用这个确切的server.ts
文件,至少把这个部分复制出来,并整合到你的文件中。
创建tsconfig.server.json
这告诉ANGLE编译器在哪里可以找到Universal应用程序的入口模块。
创建app.server.mode.ts
这仅是服务器版本的根模块。您可以看到,它导入了我们的AppModule
,以及@Angel/Platform-server
中的ServerModule
,并引导了与AppModule
相同的AppComponent
。AppServerModule
是通用应用程序的入口点。
创建main.server.ts
这个新文件基本上只导出AppServerModule
,它是应用程序通用版本的入口点。我们很快就会重温这一点。
第二步-启动您的万能应用
从命令行运行以下命令:
1npm run build:ssr
然后运行:
1npm run serve:ssr
假设您在构建过程中没有遇到任何问题,打开浏览器进入http://localhost:4000
(或为您配置的任何端口),您应该会看到您的通用应用程序正在运行!它看起来不会有什么不同,但第一个页面的加载速度应该比常规的角度应用程序快得多。如果你的应用又小又简单,你可能很难注意到这一点。
你可以尝试通过打开Chrome Dev工具,在网络选项卡下,找到显示在线 的下拉列表,来尝试限制网络速度。选择** 慢速3G** 以模拟慢速网络上的设备-您应该仍然会看到登录页面和您转到的任何路由页面的良好性能。
另外,尝试查看页面源代码(在页面上单击鼠标右键并选择[查看页面源代码])。您将在<BODY>
标记中看到所有普通的HTML,该标记与您的页面上显示的内容相匹配--这意味着,您的应用程序可能会被网络爬虫抓取。将其与非通用应用程序的页面源代码进行比较,您将在<Body>
标记中看到的全部内容是<app-root>
(或您所称的引导AppComponent
的选择器)。
总结
在本文中,您了解了如何使用ANGLE Universal进行服务器端呈现。
由于通用应用程序在服务器上运行,而不是在浏览器中运行,因此您需要在应用程序代码中注意以下几点:
- 检查您是否使用了特定于浏览器的对象,如
window
、Document
或Location
。这些在服务器上不存在。您无论如何都不应该使用它们;尝试使用可注入的角度抽象,例如Document
或Location
。作为最后的手段,如果您确实需要它们,请将它们的用法包装在条件语句中,这样它们将只在浏览器上按角度使用。您可以通过从@Angel/Common
导入函数isPlatformBrowser
和isPlatformServer
,将PLATFORM_ID
内标识注入到您的组件中,然后运行导入的函数来查看您是在服务器上还是在浏览器上。 - 如果您使用
ElementRef
来获取对HTML元素的句柄,请不要使用nativeElement
来操作元素上的属性。相反,注入Renderer2
并使用there.方法之一 - 浏览器事件处理不起作用。在服务器上运行时,您的应用程序不会响应点击事件或其他浏览器事件。但是,通过
routerLink
生成的任何链接都可以用于导航。 - 尽量避免使用
setTimeout
。 - 将服务器请求的所有URL设置为绝对URL。从服务器运行时,从相对URL请求数据将失败,即使服务器可以处理相对URL。
- 类似地,从服务器发出的HTTP请求的安全性与从浏览器发出的不同。服务器请求可能具有不同的安全要求和功能。您必须亲自处理这些请求的安全问题。
继续了解Angel Universal在官方documentation.]中提供的内容