justInCaseでフロントエンドを担当している@diostrayです。
12/1に入社したばかりのアラサーおじさんです (入社は最近ですが、ジョインはもうちょっと前だったりします)
経歴上サーバサイドがメインだった(はず)なんですが、流れに身を任せた結果、気づいたらフロントエンドをやることになっていました。なぜだろう…フシギダネ
justInCaseのマイページ(契約者専用のWebポータル的なもの)でangularを使っているので、地味にハマった内容をシェアします。
TL;DR
angular-cliプロジェクトはnode-js
を使うことになるので、npm
に登録されているライブラリ(資産)がそのまま使えます。
けれども全てのJavaScriptライブラリがnpmに登録されているかと言われればそうではないわけで、外部のJavaScriptライブラリをscript
タグで読み込まないといけない場合があります。
例) facebook-sdk
/ google-api-sdk
そんな時にどうすればいいの?という疑問に対して、angular-cliプロジェクトにGoogleのJavaScriptライブラリ
を利用して、GoogleアカウントでのSSOを実装した時の設定内容を元に解説します。
ここの内容に近いんですが、違いは外部のJavaScriptというところと、angularのバージョンが違うというところです。
おことわり
- Google APIの使い方については触れません。
- Google APIを利用するために必要なもの(クライアントID etc...)は準備済みとします。
Envirionment(Version info)
node-js 8.11.1
angular-cli 6.0.1
angular 6.0.1
Step1. 外部のJavaScriptライブラリをindex.htmlに追加する
これはそのままなので、index.htmlの差分を貼り付るだけにします。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>justincase</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
+ <script src="https://apis.google.com/js/platform.js?onload=onLoadCallback" async defer></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
ポイント
-
Googleの参考サイトだと
?onload=~~
は書いてないですが、ビルドとかの都合上入れる必要があります - 理由は後で説明します
Step2. typesを導入する
後でng build
した時とかにエラーで泣く羽目になるので、先に解消するための仕込みをします。
こういう地味なところで躓くのは良いことなのか悪いことなのか未だに判断つきません。
※ typesとはなんぞ?という方はここを見てください。
Step2-1. Google APIの型定義を導入する
https://github.com/DefinitelyTyped/DefinitelyTyped で定義されています。
こういうリポジトリのメンテナにはいつも感謝です。
必要な型定義はgapi.auth2
(と依存するgapi
)です。
{
"name": "test-project",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
},
"private": true,
"devDependencies": {
+ "@types/gapi.auth2": "0.0.47",
}
}
npm i
で終わりと思いきや、大きな罠があります。
npmのライブラリはこれだけで良いんですが、外部ライブラリの場合は個別に読み込む設定を追加しないと型情報を拾ってくれません。(拾ってくれないだけなら良いんですが、ビルドエラーになってしまいます)
そこで、tsconfig.app.json
に型定義を読み込む設定を追加し、ソース内で型情報を認識させるようにします。
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
- "types": ["node"]
+ "types": ["node", "gapi", "gapi.auth2"]
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}
ポイント
- tsconfig.app.jsonに書くのを忘れない
- もう一つの解決方法もありますが、そちらはデメリットがあるので省略します
Step2-2. 個別の型定義を導入する
Step1で非同期インクルードの設定をしたのですが、(追加した?onload=~~
の部分)この関数を定義しないとビルドで落ちる羽目になります。
そこで、定義ファイルをsrc/types
の下にこんなファイルを追加することで読み込ませます。
interface Window {
onLoadCallback: () => void;
}
declare var window: Window;
ポイント
- 当然ですがindex.htmlとこの中の関数名は一緒にする
Step3. Google APIライブラリをプロジェクトに取り込む
ライブラリを使う時は、大抵の場合初期化処理が必要です。
どこに書くかは好みの問題だと思いますが、app.component.ts
にそのまま書いてしまいます。
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor() {
// configure google api component.
window.onLoadCallback = () => {
gapi.load('client:auth2', () => {
gapi.auth2.init({
client_id: "XXXXXXXXXXXXXXXXXXXXXX",
fetch_basic_profile: true,
scope: 'profile'
});
});
};
}
}
ポイント
- Step1で非同期インクルードの設定をしたのは、ここでの都合上
- componentの初期化とscriptの読み込みの開始時期を比較した時に、componentの初期化が早いと、未定義エラーになってしまうため、非同期インクルードの設定が必須
Step5. ng build
する
タイトルそのままなので省略…
Step6. ng test
用の設定を追加する
ググり力が低かったのか、なかなか見つけられなかったユニットテスト用の設定です。
(あまりやってないのか、それともハマってないのか…)
Step 6-1. type設定を読み込む
Step2-1の設定はビルド向けの設定で、テスト用の設定はtscofig.spec.json
に用意されています。
tsconfig.app.json
と同じ設定をこちらにも追加します。
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"module": "commonjs",
"types": [
"jasmine",
"node",
+ "gapi",
+ "gapi.auth2"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}
Step7. karmaの設定を変える(外部ライブラリの場合は不要かも?)
karmaはユニットテストのフレームワークです。
ユニットテスト時には当然index.html
なんてないわけで、index.htmlに書いてあるライブラリをどこかでインクルードしないと未定義エラーが出ます。
そのための設定を管理するのがkarma.conf.js
で、そこにインクルードする設定をfiles
で書きます。
ローカルファイルの場合はここの設定をしないとng test
でエラーになりました。
※これで相当時間を取られたのはいい思い出…
module.exports = function (config) {
config.set({
+ files: [
+ // ↓のような感じで、index.htmlで列記しているものを読み込み
+ { pattern: './assets/lib/hogehoge/fugagfuga.js', included: true, watch: false },
+ ],
});
);
ポイント
-
files
の位置は先頭が良い(位置は関係ないと思いたいですが、先頭じゃないと動かない時があったような気がします) - index.htmlに書いてある順番と同じにする
- 手抜きして
{ pattern: './assets/lib/**/*.js', included: true, watch: false }
と書かない
終わりに(テンプレ)
angularやAIを含めて、**最新技術で保険業界を変えていきたい!**という方をjustInCaseは募集しています!
justInCase では一緒にアプリ・サービスを作り上げていただけるエンジニアを絶賛募集中です。
- 国内初P2P保険を創る!ブロックチェーンエンジニア募集!
- フィンテック最期の砦:IT保険会社のインフラをサーバーレスで作る!
- 保険APIで保険フィンテック先駆けを作るサーバーサイドエンジニア!
-
フロントエンジニアfor保険テック保険会社!
上で絶賛募集中なので、興味のある方はぜひご応募くださいm(_ _)m