名前: ちきさん
所属: オプト
GitHub/Twitter/Qiita: @ovrmrw
今回のGitHubリポジトリ
参考にしたもの
Angular Universalやってみたい
Expressが必要...
Firebase好きだし、Firebase HostingでAngular Universalやりたい
Firebase HostingにはExpressアプリをホスティングできない...
Cloud Functions for Firebaseでワンチャンあるかも...!
Angular CLI 1.3.0-rc.3以上とFirebase CLIをインストールする
$ npm install -g @angular/cli@next firebase-tools
ng new で新しいプロジェクトを作成する。
$ ng new angular-universal-with-firebase-hosting
Firebaseプロジェクトにする。
$ cd angular-universal-with-firebase-hosting
$ firebase init
※ HostingとFunctionsは必須。その他は下記のように設定する。
Do you want to install dependencies with npm now? (Y/n): N
What do you want to use as your public directory? (public): public
Configure as a single-page app (rewrite all urls to /index.html): Y
@angular/platform-serverをインストールする。
$ npm install --save-dev @angular/platform-server
src/app/app.module.ts を編集する。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
// BrowserModule
BrowserModule.withServerTransition({ appId: 'my-app' }) // ←ここ
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
src/app/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: [
AppModule, // ←ここにAppModuleを入れる。
ServerModule,
],
bootstrap: [AppComponent],
})
export class AppServerModule { }
src/main.server.ts を追加する。
import { enableProdMode } from '@angular/core';
export { AppServerModule } from './app/app.server.module';
enableProdMode();
src/tsconfig.server.json を追加する。
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"module": "commonjs"
},
"exclude": [
"test.ts",
"**/*.spec.ts"
],
"angularCompilerOptions": {
"entryModule": "app/app.server.module#AppServerModule"
}
}
angular-cli.json を編集する。
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "angular-universal-with-firebase-hosting"
},
"apps": [
{
.......
},
{
"platform": "server",
"root": "src",
"outDir": "functions/dist-server",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.server.ts",
"test": "test.ts",
"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"
}
}
],
.......
}
src/index.html を functions/dist-serverディレクトリ にコピーする。
$ cp src/index.html functions/dist-server
functions/package.json の dependencies
を編集する。この後 functionsディレクトリに移動して npm install
する。
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"dependencies": {
"firebase-admin": "~4.2.1",
"firebase-functions": "^0.5.7",
"@angular/animations": "^4.0.0",
"@angular/common": "^4.0.0",
"@angular/compiler": "^4.0.0",
"@angular/core": "^4.0.0",
"@angular/forms": "^4.0.0",
"@angular/http": "^4.0.0",
"@angular/platform-browser": "^4.0.0",
"@angular/platform-browser-dynamic": "^4.0.0",
"@angular/platform-server": "^4.0.0",
"@angular/router": "^4.0.0",
"core-js": "^2.4.1",
"express": "^4.15.3",
"rxjs": "^5.4.2",
"zone.js": "^0.8.16"
}
"private": true
}
functions/index.js を編集する。
require('zone.js/dist/zone-node');
const functions = require('firebase-functions');
const express = require('express');
const path = require('path')
const renderModuleFactory = require('@angular/platform-server').renderModuleFactory;
const AppServerModuleNgFactory = require('./dist-server/main.bundle').AppServerModuleNgFactory;
const index = require('fs').readFileSync(path.resolve(__dirname, './dist-server/index.html'), 'utf8');
const app = express();
app.get('/', (req, res) => {
renderModuleFactory(AppServerModuleNgFactory, { document: index, url: '/' })
.then(html => {
res.send(html);
})
.catch(err => {
console.log(err)
});
});
exports.ssr = functions.https.onRequest(app);
firebase.json を編集する。
{
"hosting": {
"public": "public",
"rewrites": [
{
"source": "**",
"function": "ssr"
}
]
}
}
publicフォルダを追加し、空の hoge.css というファイルを配置する。
(ファイルが何もないとそのフォルダをFirebase Hostingにデプロイできないため)
package.json の scripts
を編集する。
{
"scripts": {
.....,
"build": "ng build --prod --app 1 --output-hashing=none",
"copy": "cp src/index.html functions/dist-server",
"deploy": "npm run build && npm run copy && firebase deploy",
.....
}
}
デプロイする。
$ npm run deploy
動作確認