Angularアプリケーション開発を支えるツール

laco氏:よろしくお願いします。Angularの話をさせていただこうと思います。

まず軽く自己紹介をしますと、lacoと申します。Kaizen Platformという会社で働いていて、Angular日本ユーザーグループの代表をやっております。

Angularのコントリビューターをやっておりまして、最近、AngularでGoogle Developers Expertになりまして、Angularの啓蒙などをやっています。だいたいこのアイコンで活動しております。

2018年、Angularを書くにあたっていろいろなAngularのツールにお世話になったので、今日はAngularのツールの話をしようと思うんですが、まず「フロントエンドでツールっていろいろあるよね」というところから話します。

ツールはなんのためにあるかというと、タスクをこなすためにあるわけで、ある程度自動化・機械化できるものがタスク化されて、そのタスクをこなすツールがいっぱい生まれているわけですけど、大きく分けるとこんな感じかなと思います。

Scaffold。何か新しくコードを生成するものですね。プロジェクトを作る。例えば create-react-appとかangular-cliとかvue-cliとか、こういうコード生成の機能を持ったものがあります。あるいはBuildの機能。Debugの機能。あとはTesting、Refactor。あとデプロイ周りの機能とか、あとはCIとかCD、継続デプロイとか、いろいろタスクがあるわけで。

これらがいろいろあって、Angular CLIはこの5つの部分を面倒見ています。デプロイとCIに関しては、いまのところ面倒を見てないのですが、Angular CLI1つで、コード生成やプロジェクト生成、Build、Test、その他もろもろアプリ開発に必要なタスクは基本的に自動化できてます。

CLI のアーキテクチャ

CLIの中身について。多くのコマンドがあるんですが、基本的に2つに分かれます。1つはSchematics系と、もう1つはArchitects系というものです。

Schematicsは、何かコードを変更するとかファイルを生成するとか、そういうファイルシステムに影響を与えるものをそう呼んでいます。

例えば「ng new」コマンドはプロジェクトを新しく作る機能です。あとgenerateは、コンポーネントのコードを作ったり、サービスとかその他いろんなコードをコンポーネント単位で作ったりとか、そういった部分に使います。updateとaddもあるんですけど、これはちょっとあとで説明します。

下のArchitectsのほうは、既存のコードには影響を与えずに、そのコードを使って何かを起こすものです。例えば、buildコマンドだったりtestコマンド。あとはローカルサーバを立ち上げるserveコマンドだったり、E2Eテストを立ち上げるe2eコマンド。あとはlintを行うlintコマンドがあります。

ng add

ReactやVueなどツールがいろいろあるなかで、あんまり見覚えないのは、updateとaddだと思うので、この2つに絞って軽く説明をします。

Angular CLIは基本的にngコマンドなんですけど、その中に「ng add」コマンドがあります。

これは何をするかというと、Angularのライブラリ、例えば、Angularのマテリアルデザインのライブラリとか、ほかのUIフレームワークのライブラリとか、そういったものをインストールしてセットアップまでしてくれるコマンドです。

オフィシャルでは「@angular/material」とか「@angular/elements」とか「@angular/pwa」とか、そういったパッケージがあって、これらが「ng add」に対応しています。

とくに「ng pwa」は強力で「ng add @angular/pwa」というコマンドを叩くと、既存のアプリケーションがPWAになるという魔法のようなコマンドです。Service Workerのコードを生成して、キャッシュの設定をして、あとマニフェストファイルを作るところまでやってくれます。

Communityのパッケージでも対応しているものがあって、BootstrapのUIコンポーネントのngx-bootstrapとか、あとはAngular CLIのテストをJestに変えるjest-schematicというものを作っている人がいて。

公式だけでなく、コミュニティのサードパーティでも「ng add」を使って、普通だったらnpmをインストールして、自分でセットアップのコードを真似していろいろセットアップしてというフェーズが必要なんです。それらを「ng add」で自動化できるようになっております。

ng update

そして、「ng update」というコマンドがあります。

名前のとおりアップデートするのですが、基本的にnpmだったりYarnだったり、そのプロジェクトが使っているパッケージマネージャーを使ってアップデートするのですが、それに加えて、そのパッケージが「ng upgrade」のマイグレーションに対応していると、バージョン間のマイグレーションコードを実行できるというのがありまして。

これはいまのところサポートしているのは基本的にAngular公式のパッケージだけなんですが、仕様的にはサードパーティのパッケージでも対応できます。

例えば「ng update @angular/cli」というコマンドを叩くと、そのプロジェクトのCLIのバージョンを、npmパッケージのバージョンを上げて、既存のファイルの中のマイグレーションが必要な設定ファイルの一部とかを書き換えてくれる。

あるいは「@angular/core」というものを叩くと、これはAngularのcoreだけじゃなくて、それに依存するほかのAngularのパッケージもまとめて全部上げてくれるんですね。

例えば、ルーターとかHTTPのライブラリとか。そういった@angular/coreのマイグレーションコードの中に「このパッケージも一緒に上げなきゃ」というのが書いてあるので、自動的にやってくれると。

なので、Angularのパッケージに関しては「このバージョンとこのバージョンは対応しているから一緒に上げなきゃ」みたいなことを考える必要がなくて、coreだけ上げたらそれで終わりというふうな世界観になっております。

Angular CLI v7で追加されたこと

そして、先月Angular CLIがバージョン7になりました。そこで入った一番目覚ましい機能としては、Performance Budgetがデフォルトになったというところですね。Performance Budgetという名前聞いたことある方? Angularに限らず。あまりご存知ない?

Webのパフォーマンスっていろいろ文脈があるんですけど、ここで言うと、バンドルサイズに上限を設けよというBudgetを設けて、Budgetを超えたら警告なりエラーなり出すという、そういったパフォーマンス改善の取り組みのことをPerformance Budgetと言うんですけど、それをAngular CLIはサポートしています。

具体的に言うと、Angular CLIでビルドしたバンドルサイズが大きくなると、任意のサイズで警告を出したり、あるいはエラーにしてビルドを失敗させたりできます。そうすることで、うっかりサードパーティのライブラリ入れてすごいサイズになっちゃったみたいなときに、エラーになって落ちてくれるということができます。

これはいままでもあったんですが、バージョン7から作ったプロジェクトではデフォルトで有効になっています。その基準は、「バンドルサイズが2MBを超えると警告が出ます。それで、5MBを超えるとエラーが出るという基準があって。この基準どこから来ているかというと、Chromeのデータセーブモードで受け付けられるギリギリのJSのサイズです。

5MB超えるとデータセーブモードで落とせなくなるっぽいので、そこの仕様に合っていて。なので、見てのとおりすごく緩いんですけど、デフォルトで入っています。

なので、うっかりwebpackで画像のバイナリを入れちゃったとか、すごいでかいバイナリを入れちゃったりしない限り、まず引っかからないんですけど、こういう機能があります。設定ファイルが2MBとか5MBとかで入っているので、自由にプロジェクトに合わせてこのサイズを変更できます。

initialとはなにか

ここで注目してほしいのは、ここで規制しているのはこのinitial sizeなんですね。

initialって何かというと、いまJavaScriptの世界では、Lazy Loadとか、最初にJS全部読むんじゃなくて、分割しておいて必要なときに必要なJSを読むという、そういった流れがけっこう起きていて、Lazy Import、Dynamic Importとか言いますけど。そういったものを使ってできるだけJavaScriptのサイズを小さくしようという風潮になっています。

それに倣って、そのWebアプリケーションが最初に起動して読み込まれるであろうバンドルを「initialバンドル」と読んで、それ以外の分割されていつでも読み込めるやつを「chunk」と呼んでいて、このうちのinitialのサイズだけを規制するのが、さっきのinitialのPerformance Budgetです。

どうやってchunkを作るかというと、Angularの中でもとくに変わりはなくて、Dynamic Importのグローバルのimport 関数を使えば、任意のモジュールを遅延読み込みできるんですけど、この例ではコンポーネントの中でimportLazyModuleというメソッドを呼び出すと、Lazy ModuleをImportして、読み込みが終わったらメッセージを出すという、すごく簡単なものになっています。

何が起きるかというと、下のGIF画像を見てください。

import lazy moduleを押すと、右側のほうのネットワークのところで、1個JSの読み込みが発生しているんですね。つまりこのボタンを押したときにimport関数が呼ばれて、新しいJSが取ってこられて、それで処理が行われているところです。

こういうことはAngularでもすでに可能なんですが、先ほどのPerformance Budgetを実際に動かすために、2MBを超えるJSを作ろうとがんばった結果、この4行で2.9MBに到達できました。

これはちょっと豆知識なんですが、aws-sdkが1.数MBで、fakerが1.数MBです。足したらだいたい3MBになります。

fakerってダミーのデータを作るやつなんですけど、うっかりプロダクションコードに入れないように、みんな気をつけましょう。テストコードだけです。

バンドルのサイズを制限する

というわけで、この4行だけコードがさっきのlazyです。

ここのimportしているlazyです。このファイルを、上のビルド結果はOKなんですね。ちょっと文字が多いんですけど、右側にinitialという黄色い文字があるんですけど、これはinitialバンドルです。一番下のinitialついていないのが、2.95MBあるさっきのlazyです。

この4つ、上のinitialはサイズオーバーしないのでOKなんですが、下の場合、普通の静的なimportをしてしまうと、バンドルがmainにまとまってしまいます。mainというこの2番目のやつが3.12MBというでかいバンドルになっちゃって、これはinitialなので下に黄色い警告が出てて、mainのバンドルがサイズオーバーしてるよというふうに出ます。

これを応用するといろいろできて、まず簡単なのはサイズ小さくして200KBで警告して、300KBでエラーにするとか、よくありそうな設定です。

あるいは、initialだけじゃなくてすべてのバンドルに対してルールをつけることもできて、その場合「type : “any”」とすると、あらゆる個別のバンドルに対してサイズの制限ができます。

これらはOR条件なので、全ルールが同時に適用されます。そういう感じで、下のほうではinitialはOKなんだけど、anyでだめという感じのエラーになりますね。

これをさらに応用すると、プロダクションビルド、ステージングビルドでBudgetの設定を変えるとかもできます。

これはけっこう夢があるというか、Angular CLIならではという感じがします。

これらを防ぐために、Angular CLIでサポートしているというか、tslintがサポートしているんですが、「importのブラックリストを作っておくといいよね」という話です。これは別にAngularの話ではないんですけど。Rxとかlodashとか、importを防ごうねと。

その他の機能の紹介

おまけとして、ここからはCLIがまだサポートできていない部分の話なんですが、フォーマットはないです。なので、Prettierを使います。

先々週にPrettierがAngularをサポートしたので、これからは全部PrettierでOKです。Prettierでソースの下のts, scss, htmlなりなんなり全部つっこめば、Angularのコードは全部フォーマットできます。

プロトタイピングについては、ツールはいまのところありませんが、StackBlitzというオンラインのサービスを使うと、ブラウザ上でAngular CLIと同じ構成のAngularのアプリケーションを簡単に作れます。

最近「Deploy to Firebase」という謎コマンドが生まれて、簡単にFirebaseにアップロードできます。

あんまり知られてないんですけど、Angularチームが作っているDockerイメージがあります。これ何が入っているかというと、NodeとNPM/Yarnと、Chrome ・Firefox、あとはヘッドレスです。ヘッドレスブラウザ上のXvfbというやつが入っていて。

「フロントエンドのテストとビルドするなら、全部これで済むよね」という環境が揃っているangular/ngcontainerというDockerイメージがあって、これけっこう便利なので、フロントエンド全体的に、困ったら参考にするといいんじゃないかなと思います。

これはAngular Consoleという、さっき話したAngular CLIのGUIです。

これはangularconsole.comからアクセスして調べてください。

Angularのこれから

最後にfuture。

Angular CLIは、もうすぐBazel対応します。Bazelについてはググってください。WebWorkerもおそらくV8までに対応するんじゃないかなという感じです。WebWorker対応がしやすくなります。

あとClosure Compilerは、あんまり音沙汰ないですが、進行しているっぽいです。

という感じで、来年も粛々と内側がアップデートされていきますので、Angular CLIに乗っかっておくと安心です。

発表を終わります。ありがとうございました。

(会場拍手)