Ответ 1
Angular Cli теперь поддерживает это в версии 1.3.0-rc.0 и выше.
Вы можете установить эту версию, используя
npm install -g @angular/cli
Инструкции по установке из Angular Cli Wiki на Универсальный рендеринг
У меня есть демонстрационное приложение, которое можно найти на GitHub
Источник: https://github.com/joejordanbrown/angular-cli-universal
Live Demo: https://uixd.co.uk/open-source-software/angular-cli-universal/
Шаг 1. Создайте новое Angular приложение Cli
$ ng new angular-cli-universal
Шаг 2. Установка @ angular/platform-server
Установите в проект проект @ angular/platform-server. Убедитесь, что вы используете ту же версию, что и другие пакеты @angular в вашем проекте.
$ npm install --save-dev @angular/platform-server
или
$ yarn add @angular/platform-server
Шаг 3: Подготовьте свое приложение для универсальной рендеринга
Первое, что вам нужно сделать, это сделать ваш AppModule совместимым с Universal, добавив .withServerTransition() и идентификатор приложения в ваш импорт BrowserModule:
SRC/приложение/app.module.ts:
@NgModule({
bootstrap: [AppComponent],
imports: [
// Add .withServerTransition() to support Universal rendering.
// The application ID can be any identifier which is unique on
// the page.
BrowserModule.withServerTransition({appId: 'my-app'}),
...
],
})
export class AppModule {}
Затем создайте модуль специально для своего приложения при работе на сервере. Он рекомендовал назвать этот модуль AppServerModule.
Этот пример помещает его рядом с app.module.ts в файл с именем app.server.module.ts:
SRC/приложение/app.server.module.ts:
import {NgModule} from '@angular/core';
import {ServerModule} from '@angular/platform-server';
import {AppModule} from './app.module';
import {AppComponent} from './app.component';
@NgModule({
imports: [
// The AppServerModule should import your AppModule followed
// by the ServerModule from @angular/platform-server.
AppModule,
ServerModule,
],
// Since the bootstrapped component is not inherited from your
// imported AppModule, it needs to be repeated here.
bootstrap: [AppComponent],
})
export class AppServerModule {}
Шаг 4: Создайте основной файл сервера и tsconfig для его создания
Создайте основной файл для вашего универсального пакета. Этот файл должен экспортировать только AppServerModule. Он может идти в src. Этот пример вызывает этот файл main.server.ts:
SRC/main.server.ts:
export {AppServerModule} from './app/app.server.module';
Скопируйте tsconfig.app.json в tsconfig-server.json и измените его на создание с помощью "модуля" цели "commonjs".
Добавьте раздел для "angularCompilerOptions" и установите "entryModule" в свой AppServerModule, указанный как путь к импорту с хешем (#), содержащим имя символа. В этом примере это будет src/app/app.server.module # AppServerModule.
ЦСИ /tsconfig.server.json:
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"baseUrl": "./",
// Set the module format to "commonjs":
"module": "commonjs",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts"
],
// Add "angularCompilerOptions" with the AppServerModule you wrote
// set as the "entryModule".
"angularCompilerOptions": {
"entryModule": "app/app.server.module#AppServerModule"
}
}
Шаг 5: Создайте файл сервера NodeJS Вам необходимо создать сервер NodeJS для рендеринга и обслуживания приложения. В этом примере используется выражение.
Установить экспресс и сжатие
$ npm install --save express compression @nguniversal/express-engine
или
$ yarn add express compression @nguniversal/express-engine
ЦСИ /express.server.js:
const path = require('path');
const fs = require('fs');
const express = require('express');
const compression = require('compression');
const ngExpressEngine = require('@nguniversal/express-engine').ngExpressEngine;
require('zone.js/dist/zone-node');
require('rxjs/add/operator/filter');
require('rxjs/add/operator/map');
require('rxjs/add/operator/mergeMap');
var hash;
fs.readdirSync(__dirname).forEach(file => {
if (file.startsWith('main')) {
hash = file.split('.')[1];
}
});
const AppServerModuleNgFactory = require('./main.' + hash + '.bundle').AppServerModuleNgFactory;
const app = express();
const port = Number(process.env.PORT || 8080);
app.engine('html', ngExpressEngine({
baseUrl: 'http://localhost:' + port,
bootstrap: AppServerModuleNgFactory
}));
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/../browser'));
app.use(compression());
app.use('/', express.static(path.join(__dirname, '/../browser'), {index: false}));
app.get('/*', function (req, res) {
res.render('index', {
req: req,
// res: res
});
});
app.listen(port, function() {
console.log(`Listening at ${port}`);
});
Шаг 6. Создайте новый проект в .angular-cli.json
В .angular-cli.json есть массив под ключевым "apps". Скопируйте конфигурацию для своего клиентского приложения и вставьте ее как новую запись в массив, а дополнительный ключ "платформа" настроен на "сервер".
Затем удалите ключ "polyfills" - они не нужны на сервере и не настроят "main" и "tsconfig", чтобы указать на файлы, которые вы написали на шаге 2. Наконец, настройте "outDir" на новый location (в этом примере используется dist/server).
.angular-cli.json:
{
...
"apps": [
{
// Keep your original application config the same apart from changing outDir to dist/browser.
// It will be app 0.
"outDir": "dist/browser",
},
{
// This is your server app. It is app 1.
"platform": "server",
"root": "src",
// Build to dist/server instead of dist. This prevents
// client and server builds from overwriting each other.
"outDir": "dist/server",
"assets": [
"assets",
"favicon.ico",
"express.server.js"
],
"index": "index.html",
// Change the main file to point to your server main.
"main": "main.server.ts",
// Remove polyfills.
// "polyfills": "polyfills.ts",
"test": "test.ts",
// Change the tsconfig to point to your server config.
"tsconfig": "tsconfig.server.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
...
}
Построение пакета
По завершении этих шагов вы должны будете создать серверный пакет для своего приложения, используя флаг -app, чтобы сообщить CLI о создании пакета серверов, ссылаясь на его индекс 1 в массиве "apps". угловой-cli.json:
# This builds the client application in dist/browser/
$ ng build --prod
...
# This builds the server bundle in dist/server/
$ ng build --prod --app 1
Date: 2017-07-24T22:42:09.739Z
Hash: 9cac7d8e9434007fd8da
Time: 4933ms
chunk {0} main.988d7a161bd984b7eb54.bundle.js (main) 9.49 kB [entry] [rendered]
chunk {1} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes [entry] [rendered]
Запуск экспресс-сервера
$ node dist/server/express.server.js
Просмотрите Angular Cli Wiki для получения более подробной информации https://github.com/angular/angular-cli/wiki/stories-universal-rendering