Angular 服务器端渲染的学习笔记(二)
官網地址:https://angular.io/guide/universal
I have mainly used angular universal for SEO purposes. In that, the server will render enough information on the page so that when Google crawls the page, you can have the server load some asynchronous data (eg. a description of a product from a databse) before serving the page so the crawler sees the information.
使用服務器端渲染,可以提前讓服務器加載一些異步數據,比如從數據庫里讀取產品的描述信息,便于爬蟲讀取。
Asynchronously loaded html via javascript is often missed by crawlers.
網絡爬蟲一般不會通過執行 JavaScript 的方式去異步加載 HTML.
so you need the server to run a bit of javascript before serving the page to the client sometimes.
因此通常情況下,我們需要服務器先執行一些 JavaScript 片段,才能將生成的頁面返回給客戶端。
SSR can generate a static version of a page and serve it. That doesn’t mean it will be fully functional.
SSR 可以生成一個應用的靜態版本,但并不意味著該版本完全可用。
Serve, as needed, a static version of the page with most of the DOM elements preloaded, instead of waiting for angular to bootstrap and do this asynchronously via Javascript.
應用頁面的靜態版本,大多數 DOM 元素都已經提前加載。這種情況下,不需要等待 Angular 完成 bootstrap 后,再執行 JavaScript 完成頁面異步加載的效果。
To support offline mode, it has to be combined with pwa techniques, such as caching from the serviceWorker, getting data from local/session storage/ indexedDB, etc.
為了支持離線模式,SSR 需要和 PWA 技術配合起來使用,比如基于 Service Worker 的緩存,從 local / session 存儲介質里讀取數據,等等。
Universal web servers
A Universal web server responds to application page requests with static HTML rendered by the Universal template engine.
Universal web 服務器,使用 Universal 模板引擎,給應用程序的頁面請求,回復一個靜態版本的渲染完畢的 HTML 頁面。
The server receives and responds to HTTP requests from clients (usually browsers), and serves static assets such as scripts, CSS, and images.
服務器接收到從客戶端(通常情況下都是瀏覽器)發起的 HTTP 請求,并且以靜態資源,比如 scripts,CSS 和圖片的方式來響應。
It may respond to data requests, either directly or as a proxy to a separate data server.
它也能響應數據請求,或者直接響應,或者作為代理,將該數據請求轉發給另外的數據服務器。
The sample web server for this guide is based on the popular Express framework.
Any web server technology can serve a Universal app as long as it can call Universal’s renderModule() function. The principles and decision points discussed here apply to any web server technology.
任何 web 服務器都能夠架設 Universal 應用,只要其能夠調用 Universal 的 renderModule() 方法。
Universal applications use the Angular platform-server package (as opposed to platform-browser)
Universal 應用使用 Angular platform-server 包
which provides server implementations of the DOM, XMLHttpRequest, and other low-level features that don’t rely on a browser.
這個包提供了服務器端的 DOM 實現,XMLHttpRequest,以及其他不依賴于瀏覽器的底層特性。
The server (Node.js Express in this guide’s example) passes client requests for application pages to the NgUniversal ngExpressEngine.
服務器(在這個學習筆記里,服務器由 nodejs Express 實現) 將客戶端對于應用頁面的請求,轉發給 NgUniversal Express engine.
Under the hood, this calls Universal’s renderModule() function, while providing caching and other helpful utilities.
其底層實現原理是,調用 Universal renderModule 函數,提供緩存和其他功能。
The renderModule() function takes as inputs a template HTML page (usually index.html), an Angular module containing components, and a route that determines which components to display. The route comes from the client’s request to the server.
renderModule 的輸入:
- HTML 模板頁面,通常為 index.html
- 一個包含 Components 的 Angular module
- 一個 route,決定哪些 Component 應該顯示
Each request results in the appropriate view for the requested route. The renderModule() function renders the view within the tag of the template, creating a finished HTML page for the client.
每個請求最終會導致其對應的路由視圖被渲染在模板的 app 標簽里。
Because a Universal app doesn’t execute in the browser, some of the browser APIs and capabilities may be missing on the server.
Universal 應用并不會執行在瀏覽器環境里,因此部分瀏覽器 API 和功能,很可能在服務器端不可用。
For example, server-side applications can’t reference browser-only global objects such as window, document, navigator, or location.
例如,服務器端應用無法使用只有在瀏覽器端可用的 window,document,navigator,location 等全局對象。
Angular provides some injectable abstractions over these objects, such as Location or DOCUMENT; it may substitute adequately for these APIs.
針對這些對象,Angular 提供了可注入的抽象,比如 Location 或者 DOCUMENT.
If Angular doesn’t provide it, it’s possible to write new abstractions that delegate to the browser APIs while in the browser and to an alternative implementation while on the server (aka shimming).
當然我們也能自行在應用程序里編寫這些抽象邏輯,即所謂的 shimming.
Similarly, without mouse or keyboard events, a server-side app can’t rely on a user clicking a button to show a component.
相應的,因為缺少鼠標或者鍵盤事件,服務器端應用無法基于用戶點擊按鈕的方式來觸發 Component 的顯示。
The app must determine what to render based solely on the incoming client request. This is a good argument for making the app routable.
應用必須能夠純粹基于客戶端發起的請求來判斷出什么內容需要渲染。這是讓應用支持路由的一個極佳的理由。
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) server.engine('html', ngExpressEngine({bootstrap: AppServerModule, }));The ngExpressEngine() function is a wrapper around Universal’s renderModule() function which turns a client’s requests into server-rendered HTML pages.
ngExpressEngine 函數是 Universal renderModule 函數的一個 wrapper,將客戶端請求轉換成服務器端渲染好的 HTML 頁面。
接收的輸入參數:
bootstrap: The root NgModule or NgModule factory to use for bootstraping the app when rendering on the server.
根 NgModule 或者 NgModule 工廠,用于 bootstrap 在服務器端渲染的應用。
For the example app, it is AppServerModule.
It’s the bridge between the Universal server-side renderer and the Angular application.
AppServerModule 是 Universal 服務器端渲染器和 Angular 應用之間的橋梁。
SSR 需要對下列三種不同類型的請求分別進行處理:
- Data request: request URL that begins /api. 數據請求,url 里常包含諸如 api 類型的片段。
- App navigation: request URL with no file extension.路由請求,不包含文件擴展名。
- Static asset: all other requests.靜態資源請求。
A Node.js Express server is a pipeline of middleware that filters and processes requests one after the other.
nodejs Express 服務器實際是一種中間件傳播途徑,以一個接一個的方式,過濾和處理請求。
下列的代碼,將所有不包含 file extension 的請求,都當作是導航請求進行處理:
server.get('*', (req, res) => {res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); });To ensure that clients can only download the files that they are permitted to see, put all client-facing asset files in the /dist folder and only honor requests for files from the /dist folder.
一個最佳實踐是,為了確保客戶端只能下載其權限允許范圍內的文件,將所有該類型的文件都放到 /dist 文件夾里。
// Serve static files from /browser server.get('*.*', express.static(distFolder, {maxAge: '1y' }));In a server-side rendered app, HTTP URLs must be absolute (for example, https://my-server.com/api/heroes).
服務器端渲染,HTTP URL 必須是絕對路徑。
This means that the URLs must be somehow converted to absolute when running on the server and be left relative when running in the browser.
這意味著,當運行在服務器端時,url 必須被轉換成絕對路徑,而運行在瀏覽器端時,可以仍然保留成相對路徑。
If you are using one of the @nguniversal/*-engine packages (such as @nguniversal/express-engine), this is taken care for you automatically. You don’t need to do anything to make relative URLs work on the server.
@nguniversal/express-engine 會幫助我們自動完成絕對路徑轉相對路徑的操作。
2021年6月3日補充
服務器端渲染,main.js 并不包含完整的 SAP Spartacus Storefront 代碼,而是像瀏覽器一樣的渲染 Storefront 代碼,并且將結果返回。
main.js is basically all browser angular javascript code wrapped into rendering layer.
所有瀏覽器端的 JavaScript 代碼,包裹到渲染層中。
what you get by using curl is basically the result of running main.js
curl 的結果,就是用 node 運行 main.js 之后的輸出結果。
更多Jerry的原創文章,盡在:“汪子熙”:
 
總結
以上是生活随笔為你收集整理的Angular 服务器端渲染的学习笔记(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: nova5pro可以无线充电吗
- 下一篇: 使用 Angular Universal
