からあげ🐔とおんせん♨の国のkpondaです。
この記事はAngular Advent Calendar 2018 12日目の記事です。
Angularでの複数プロジェクト構成とFirebase Hostingを使った公開方法について書こうと思います。
はじめに
Angularのプロジェクト構成にはAngular CLIを、Firebaseの設定などはFirebase Toolsを使用します。
複数プロジェクト構成
Angularでアプリケーションを書いていて、ユーザ向けと管理者向けなどユーザ種別毎に別のアプリケーションとして作成したいことはありませんか?
例えば利用者向けのアプリケーションと管理者向けのアプリケーションを用意したい状況などあるかと思います。
別のアプリケーションとして構築する
ng newで別々のAngularアプリケーションとして作成することができます。
この場合API呼び出しなど共通して使用するコードの共有の仕方などを別途考える必要があります。
$ ng new userapp
$ ng new adminapp
Angular CLIの複数プロジェクト
Angular CLIでは複数プロジェクトを扱う機能が提供されています。
Angular CLIで作成したアプリケーションの中で、ng generate applicationを実行します。
$ ng new userapp
$ cd userapp
$ ng g application adminapp
ng g applicationを実行するとprojects配下にファイルが生成されます。
userapp
├-projects
│ ├-adminapp
│ └-adminapp-e2e
複数プロジェクトの実行
ng serve等実行する時はプロジェクト名を指定します。
$ ng serve userapp
$ ng serve adminapp
Userappの方はプロジェクト名を省略して実行できます。
プロジェクト名を省略した時は、angular.json の defaultProject の設定に応じます。
開発時には同時に両方起動させておきたいので、ポート番号を指定して起動させると便利です。
package.json に 次のような"all"スクリプトを追加しています。
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"all": "ng serve & ng serve adminapp --port 4210"
},
$ npm run all
を実行するとuserapp, adminappが両方起動します。
上記の設定ではuserappは4200番ポート、adminappは4210番ポートで接続できます。
ビルドを行う際もプロジェクト名を指定して行います。
$ ng build userapp —-prod
$ ng build adminapp --prod
Firebase Hosting
ビルドしたアプリケーションを公開するのにFirebase Hosting便利ですね。
複数プロジェクト構成のAngularアプリケーションをFirebase Hostingで公開する方法を試してみました。
既述のプロジェクト構成でビルドを行うと、dist配下にuserapp, adminappが作られています。
これらをデプロイする方法として以下の2つの方法があります。
- ディレクトリで分ける
- サイト(ホスト名)で分ける
サイト(ホスト名)で分ける場合は、Firebaseの無償プランでは行うことができないので注意が必要です。
Firebase Tools
FirebaseをCLIから操作するFirebase Toolsは下記のページなどを参照してください。
https://firebase.google.com/docs/cli/?hl=ja
firebase initコマンドでHostingを有効にします。
public directoryの指定はdistを、single-page appの設定にはYesでひとまず設定しておきます。
=== Hosting Setup
Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.
? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
✔ Wrote dist/index.html
i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...
✔ Firebase initialization complete!
ディレクトリを区切ってデプロイ
dist配下をそのままデプロイして使用します。
ビルドオプション
ディレクトリで区切ってデプロイする際には、ビルドオプションを指定してbase urlを設定します。
--base-hrefオプションを使用します。次のような感じでビルドを行います。
$ ng build --prod --base-href /userapp/ userapp
$ ng build --prod --base-href /adminapp/ adminapp
firebase.jsonを、サブディレクトリでうまく動くように変更します。
sigle-page appを指定しているとfirebase.jsonのrewritesは次のようになっています。
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
この部分をuserapp, adminappに合わせて次のように変更します。
"rewrites": [
{
"source": "adminapp/**",
"destination": "/adminapp/index.html"
},
{
"source": "userapp/**",
"destination": "/userapp/index.html"
}
]
firebase deployを行うと、それぞれのディレクトリを指定してアクセスできるようになります。
ルートディレクトリの表示
ディレクトリ毎に表示ができるようになりますが、ルートを表示するとFirebase Hosting Setup Completeなんて表示されます。
/index.html が存在しないから表示されるので、dist/index.htmlを作ってデプロイすれば表示されなくなります。
Firebase Hostingにはリダイレクト機能があるので、ルートディレクトリが指定された際にはサブディレクトリにリダイレクトさせてもよいでしょう。
userappディレクトリにリダイレクトさせる際には、firebase.jsonに以下のような設定を追加します。
"redirects": [
{
"source": "/",
"destination": "/userapp",
"type": 302
}
]
複数サイトにデプロイ
ディレクトリを区切ったデプロイで機能的には問題ありませんが、firebase delployを行う際に、dist配下をまとめてデプロイするのでアプリケーションの規模が大きくなってくると少し心配になってきます。
失敗しそうなことを想像してみると、dist配下をクリーンにしたあとに、一部のプロジェクトだけビルドした状態でデプロイしてしまい、アクセスできなくなってしまうことなど考えられます。恐ろしいですね。
Firebaseの従量制プランにすると複数サイトを扱えるようになります。
プロジェクト毎にFirebase Hostingのサイトを割り当ててデプロイしてみます。
Firebaseのプランを変更する
FirebaseコンソールのHostingを開くとこんな商売上手なメッセージが表示されています。
複数サイトを扱えるようにアップグレードボタンをポチッとなして、課金設定を行います。
サイトを追加
料金プランの変更ができたら「アップグレード」が表示されていあたりが「別のサイトを追加」ボタンに変わっているので、ホスト名を指定して新しいサイトを追加します。
デプロイターゲットの設定
firebase target:apply コマンドを使ってデプロイターゲットを設定します
$ firebase target:apply hosting ターゲット名 サイト名
で指定します。
ターゲット名はこのあとfirebase.jsonの設定で使用する名前になります。
サイト名がFirebase Hostingで作成したホスト名の部分になります。
ユーザ向けサイトが user.firebase.com
管理者向けサイトが admin.firebase.com
の場合、次のように実行します。
$ firebase target:apply hosting user user
$ firebase target:apply hosting admin admin
ホスティング設定
firebase.jsonを編集してデプロイターゲット毎に設定を行います。
変更前の"hostings"の値はオブジェクトが1つ設定されていますが、複数サイト指定するため配列で設定します。
"hostings": {}
だったのを
"hostings": [{}, {}]
という感じに変更します。
userapp, adminapp用の設定は下記のようになります。
"target"にデプロイターゲットの設定で指定したターゲット名を指定します。
"public"にはそれぞれのアプリケーションのdist配下のディレクトリを指定しています。
{
"hosting": [
{
"target": "user",
"public": "dist/userapp",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "admin",
"public": "dist/adminapp",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
]
}
設定完了後 firebase deploy を実行するとそれぞれにサイトにデプロイされます。
※ディレクトリを区切ってデプロイをためしたままの状態ではdist配下が --base-href をつけた状態になっているので注意してください
どちらか1つのサイトだけデプロイをかけたい時は --only オプションを指定します。
$ firebase deploy --only hosting:ターゲット名
adminappだけデプロイする時は次のようになります。
$ firebase deploy --only hosting:admin
最後に
複数プロジェクト構成は、Angular 4の頃はMultiple Apps構成としてファイル構成が異なる形で提供されていました。
Multipe Apps構成のプロジェクトを5に更新する際に、設定に少し手を加える必要がありちょっと面倒でした。
複数プロジェクト構成ではアプリケーションの他にライブラリプロジェクトを追加したりすることができます。(ng g library...)
が、このライブラリプロジェクトの扱いが微妙な感じなので、もう少し手が加わって改善されるとより使いやすくなりそうです。
明日のAngular Advent Calendarは@Quramyさんです。