サーバサイドレンダリングプロジェクト Angular Universal を使ってみます。本来は angular-cli で Angular Universal を利用するのが最も良い方法ではありますが、ここではより簡単に universal-cli を使ってみます。universal-cli は非公式なプロジェクトで angular-cli をフォークし作られています。 angular-cli で --universal スイッチ(現在 angular-cli にこのようなスイッチはありません)で Angular Universal の環境が作れるようになることを願います。

Universal CLI のインストールとプロジェクトの生成

Angular CLI と同様にインストールしプロジェクトを生成します。コマンドの使い方はほとんど同じです。

$ npm install universal-cli -g

universal-cli のインストールが終わったら --universal スイッチを使ってプロジェクトを作成します。今回は universal-app というプロジェクト名で作ります。

$ ung new universal-app --universal
installing ng2
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/index.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.json
  create src/typings.d.ts
  create angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tslint.json
installing universal
  create src/app/app.browser.module.ts
  create src/app/app.node.module.ts
  create src/client.ts
  create src/server.routes.ts
  create src/server.ts
  create webpack.client.ts
  create webpack.server.ts
Successfully initialized git.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
$

プロジェクトが生成されたら cd コマンドでプロジェクトに入り ung serve コマンドを実行しブラウザで表示確認しますが、現時点のバージョンでは若干の不具合(インストールモジュールのバージョン互換性が正しくない)があります。

$ ung --version
universal-cli: 1.0.0-alpha.universal.2-2
angular-cli: 1.0.0-beta.20-1
node: 6.7.0
os: darwin x64
$

何はともあれプロジェクトディレクトリに移動しましょう。

$ cd universal-app

package.json を次のように書き換えて下さい。

{
  "name": "universal-app",
  "version": "0.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "start": "ung serve",
    "lint": "tslint \"src/**/*.ts\"",
    "test": "ung test",
    "pree2e": "webdriver-manager update",
    "e2e": "protractor"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "2.1.0",
    "@angular/compiler": "2.1.0",
    "@angular/core": "2.1.0",
    "@angular/forms": "2.1.0",
    "@angular/http": "2.1.0",
    "@angular/platform-browser": "2.1.0",
    "@angular/platform-browser-dynamic": "2.1.0",
    "@angular/router": "3.1.0",
    "@angular/platform-server": "2.1.0",
    "angular2-platform-node": "2.0.11",
    "angular2-universal": "2.0.11",
    "angular2-universal-polyfills": "2.0.11",
    "angular2-express-engine": "2.0.11",
    "compression": "1.6.2",
    "express": "^4.14.0",
    "core-js": "^2.4.1",
    "rxjs": "5.0.0-beta.12",
    "ts-helpers": "^1.1.1",
    "zone.js": "^0.6.23"
  },
  "devDependencies": {
    "@angular/compiler-cli": "2.1.0",
    "@types/jasmine": "^2.2.30",
    "@types/node": "^6.0.42",
    "@types/body-parser": "0.0.29",
    "@types/compression": "0.0.29",
    "@types/cookie-parser": "^1.3.29",
    "@types/express": "^4.0.29",
    "@types/express-serve-static-core": "^4.0.29",
    "@types/mime": "0.0.28",
    "@types/serve-static": "^1.7.27",
    "universal-cli": "1.0.0-alpha.universal.2-2",
    "codelyzer": "~1.0.0-beta.3",
    "jasmine-core": "2.4.1",
    "jasmine-spec-reporter": "2.5.0",
    "karma": "1.2.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-cli": "^1.0.1",
    "karma-jasmine": "^1.0.2",
    "karma-remap-istanbul": "^0.2.1",
    "protractor": "4.0.9",
    "ts-node": "1.2.1",
    "tslint": "3.13.0",
    "typescript": "~2.0.3",
    "webdriver-manager": "10.2.5"
  }
}

書き換えた後 node_modules を削除し npm install コマンドを実行し直して下さい(はじめに --skip-npm スイッチを使ったほうが効率的です)。

すべての作業が終わったら簡易サーバを実行してください。

$ ung serve

何が違うのか

プロジェクト生成時のコンソールログからも分かるように Angular Universal 用のファイルが追加されています。

installing universal
  create src/app/app.browser.module.ts
  create src/app/app.node.module.ts
  create src/client.ts
  create src/server.routes.ts
  create src/server.ts
  create webpack.client.ts
  create webpack.server.ts

Angular Universal は現在

  • Node.js
  • .NET Core

でサポートされています。この universal-cli では Express/Node.js を使って実装しています。 src/server.tsを見て下さい。MEAN サンプルで見かけた Express のコードと似たようなものになっています。これに Angular Universal のコードを配置しています。

/**
 * the polyfills must be the first thing imported
 */
import './polyfills.ts';
import * as path from 'path';
import * as express from 'express';
import * as compression from 'compression';
import { createEngine } from 'angular2-express-engine';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app/app.node.module';
import { environment } from './environments/environment';
import { routes } from './server.routes';

// App

const app  = express();
const ROOT = path.join(path.resolve(__dirname, '..'));
const port = process.env.PORT || 4200;

/**
 * enable prod mode for production environments
 */
if (environment.production) {
  enableProdMode();
}

/**
 * Express View
 */
app.engine('.html', createEngine({}));
app.set('views', __dirname);
app.set('view engine', 'html');

/**
 * Enable compression
 */
app.use(compression());

/**
 * serve static files
 */
app.use(express.static(path.join(ROOT, 'dist'), {index: false}));

/**
 * place your api routes here
 */
// app.use('/api', api);

/**
 * bootstrap universal app
 * @param req
 * @param res
 */
function ngApp(req: any, res: any) {
  res.render('index', {
    req,
    res,
    ngModule: AppModule,
    preboot: false,
    baseUrl: '/',
    requestUrl: req.originalUrl,
    originUrl: req.hostname
  });
}

/**
 * use universal for specific routes
 */
app.get('/', ngApp);
routes.forEach(route => {
  app.get(`/${route}`, ngApp);
  app.get(`/${route}/*`, ngApp);
});

/**
 * if you want to use universal for all routes, you can use the '*' wildcard
 */

app.get('*', function (req: any, res: any) {
  res.setHeader('Content-Type', 'application/json');
  const pojo = {status: 404, message: 'No Content'};
  const json = JSON.stringify(pojo, null, 2);
  res.status(404).send(json);
});

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});

実行するとわかるようにサーバで Angular コードを HTML に書き換え送信してますので、ブラウザの表示は抜群に早くなっていると思います。

results matching ""

    No results matching ""