docs: update universal docs for new ivy implementation (#33040)

PR Close #33040
This commit is contained in:
Alan Agius 2019-10-08 19:31:44 +02:00 committed by Matias Niemelä
parent 1b4eaea6d4
commit 755a80c7ec
5 changed files with 75 additions and 63 deletions

View File

@ -1,61 +1,66 @@
// These are important and needed before anything else
import 'zone.js/dist/zone-node'; import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express'; import * as express from 'express';
import { join } from 'path'; import { join } from 'path';
// Faster server renders w/ Prod mode (dev mode never needed) import { AppServerModule } from './src/main.server';
enableProdMode(); import { APP_BASE_HREF } from '@angular/common';
// Express server // The Express app is exported so that it can be used by serverless Functions.
const app = express(); export function app() {
const server = express();
const distFolder = join(process.cwd(), 'dist/express-engine-ivy/browser');
const PORT = process.env.PORT || 4000; // #docregion ngExpressEngine
const DIST_FOLDER = join(process.cwd(), 'dist'); server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
// #enddocregion ngExpressEngine
server.set('view engine', 'html');
server.set('views', distFolder);
// * NOTE :: leave this as require() since this file is built Dynamically from webpack // #docregion data-request
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main'); // TODO: implement data requests securely
server.get('/api/*', (req, res) => {
res.status(404).send('data requests are not supported');
});
// #enddocregion data-request
// Express Engine // #docregion static
import { ngExpressEngine } from '@nguniversal/express-engine'; // Serve static files from /browser
// Import module map for lazy loading server.get('*.*', express.static(distFolder, {
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; maxAge: '1y'
}));
// #enddocregion static
// #docregion ngExpressEngine // #docregion navigation-request
app.engine('html', ngExpressEngine({ // All regular routes use the Universal engine
bootstrap: AppServerModuleNgFactory, server.get('*', (req, res) => {
providers: [ res.render('index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
provideModuleMap(LAZY_MODULE_MAP) });
] // #enddocregion navigation-request
}));
// #enddocregion ngExpressEngine
app.set('view engine', 'html'); return server;
app.set('views', join(DIST_FOLDER, 'browser')); }
// #docregion data-request function run() {
// TODO: implement data requests securely const port = process.env.PORT || 4000;
app.get('/api/*', (req, res) => {
res.status(404).send('data requests are not supported');
});
// #enddocregion data-request
// #docregion static // Start up the Node server
// Server static files from /browser const server = app();
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'))); server.listen(port, () => {
// #enddocregion static console.log(`Node Express server listening on http://localhost:${port}`);
});
}
// #docregion navigation-request // Webpack will replace 'require' with '__webpack_require__'
// All regular routes use the Universal engine // '__non_webpack_require__' is a proxy to Node 'require'
app.get('*', (req, res) => { // The below code is to ensure that the server is run only when not requiring the bundle.
res.render('index', { req }); declare const __non_webpack_require__: NodeRequire;
}); const mainModule = __non_webpack_require__.main;
// #enddocregion navigation-request if (mainModule && mainModule.filename === __filename) {
run();
}
// Start up the Node server export * from './src/main.server';
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});

View File

@ -1 +1,10 @@
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module'; export { AppServerModule } from './app/app.server.module';
export { renderModule, renderModuleFactory } from '@angular/platform-server';

View File

@ -1,16 +1,15 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.app.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/app", "outDir": "./out-tsc/app-server",
"baseUrl": "./",
"module": "commonjs", "module": "commonjs",
"types": [] "types": ["node"]
}, },
"exclude": [ "files": [
"test.ts", "src/main.server.ts",
"**/*.spec.ts" "server.ts"
], ],
"angularCompilerOptions": { "angularCompilerOptions": {
"entryModule": "src/app/app.server.module#AppServerModule" "entryModule": "./src/app/app.server.module#AppServerModule"
} }
} }

View File

@ -21,7 +21,7 @@ For an existing application, you have to manually add the `RouterModule` and def
Use the CLI to automatically create the app shell. Use the CLI to automatically create the app shell.
<code-example language="bash"> <code-example language="bash">
ng generate app-shell --client-project my-app ng generate app-shell
</code-example> </code-example>
* `client-project` takes the name of your client application. * `client-project` takes the name of your client application.

View File

@ -33,7 +33,7 @@ To create the server-side app module, `app.server.module.ts`, run the following
<code-example language="bash"> <code-example language="bash">
ng add @nguniversal/express-engine --clientProject angular.io-example ng add @nguniversal/express-engine
</code-example> </code-example>
@ -53,7 +53,6 @@ tsconfig.app.json <i>TypeScript client configuration</i>
tsconfig.server.json <i>* TypeScript server configuration</i> tsconfig.server.json <i>* TypeScript server configuration</i>
tsconfig.spec.json <i>TypeScript spec configuration</i> tsconfig.spec.json <i>TypeScript spec configuration</i>
package.json <i>npm configuration</i> package.json <i>npm configuration</i>
webpack.server.config.js <i>* webpack server configuration</i>
</code-example> </code-example>
The files marked with `*` are new and not in the original tutorial sample. The files marked with `*` are new and not in the original tutorial sample.
@ -152,7 +151,7 @@ The sample web server for this guide is based on the popular [Express](https://e
<div class="alert is-helpful"> <div class="alert is-helpful">
**Note:** _Any_ web server technology can serve a Universal app as long as it can call Universal's `renderModuleFactory()` function. **Note:** _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. The principles and decision points discussed here apply to any web server technology.
</div> </div>
@ -162,15 +161,15 @@ server implementations of the DOM, `XMLHttpRequest`, and other low-level feature
The server ([Node Express](https://expressjs.com/) in this guide's example) The server ([Node Express](https://expressjs.com/) in this guide's example)
passes client requests for application pages to the NgUniversal `ngExpressEngine`. Under the hood, this passes client requests for application pages to the NgUniversal `ngExpressEngine`. Under the hood, this
calls Universal's `renderModuleFactory()` function, while providing caching and other helpful utilities. calls Universal's `renderModule()` function, while providing caching and other helpful utilities.
The `renderModuleFactory()` function takes as inputs a *template* HTML page (usually `index.html`), The `renderModule()` function takes as inputs a *template* HTML page (usually `index.html`),
an Angular *module* containing components, an Angular *module* containing components,
and a *route* that determines which components to display. and a *route* that determines which components to display.
The route comes from the client's request to the server. The route comes from the client's request to the server.
Each request results in the appropriate view for the requested route. Each request results in the appropriate view for the requested route.
The `renderModuleFactory()` function renders the view within the `<app>` tag of the template, The `renderModule()` function renders the view within the `<app>` tag of the template,
creating a finished HTML page for the client. creating a finished HTML page for the client.
Finally, the server returns the rendered page to the client. Finally, the server returns the rendered page to the client.
@ -263,7 +262,7 @@ The important bit in the `server.ts` file is the `ngExpressEngine()` function.
<code-example path="universal/server.ts" header="server.ts" region="ngExpressEngine"> <code-example path="universal/server.ts" header="server.ts" region="ngExpressEngine">
</code-example> </code-example>
The `ngExpressEngine()` function is a wrapper around Universal's `renderModuleFactory()` function which turns a client's The `ngExpressEngine()` function is a wrapper around Universal's `renderModule()` function which turns a client's
requests into server-rendered HTML pages. requests into server-rendered HTML pages.
* The first parameter is `AppServerModule`. * The first parameter is `AppServerModule`.
@ -282,7 +281,7 @@ which then forwards it to the client in the HTTP response.
<div class="alert is-helpful"> <div class="alert is-helpful">
**Note:** These wrappers help hide the complexity of the `renderModuleFactory()` function. There are more wrappers **Note:** These wrappers help hide the complexity of the `renderModule()` function. There are more wrappers
for different backend technologies at the [Universal repository](https://github.com/angular/universal). for different backend technologies at the [Universal repository](https://github.com/angular/universal).
</div> </div>