らいふうっどの閑話休題

興味のあることをゆる~く書いていく

Angular: Supercharging The Router の翻訳

mediumAngular: Supercharging The Router の翻訳です ルーターがルーティング以上のことをする場合

f:id:ic_lifewood:20200104224653j:plain
Photo by Shahadat Rahman on Unsplash

アプリに「お問い合わせ」リンクがあり、専用ページにルーティングする代わりに、問い合わせフォームをポップアップ表示したいとします。

「お問い合わせ」ボタンをハードコーディングしても、クリックしたときとは異なる操作をすることは問題ありませんが、ルーターに「何か違う」ことを指示する方法があると便利ではないでしょうか。

これの最大の利点は、ツールバーまたはメニュー上のすべてのリンクを処理するユニークな方法を持つことです。実際にナビゲーションをトリガーするか、必要な他の操作を実行するかは関係ありません。

これを達成する方法を見てみましょう。

ActionLink Observer

基本的な考え方は、 CanActivate 保護メカニズムを利用してルーティング要求をインターセプトすることです。

gist.github.com

上記のコードは、ルーティングガードとして使用される ActionLinkObserver という名前のサービスを実装しています。

gist.github.com

上記の例では、 ActionLinkObserver を使用して「popup」というパスを保護しているため、アプリケーションがそこをナビゲートするたびに、オブザーバーはリクエストをインターセプトし、実際のナビゲーションが行われないようにします。

代わりに、他のユーザーが次のセクションで説明するようにコンテンツをさらに処理できるように、ルートは observer$ subject に沿ってプッシュされます。

お気づきかもしれませんが、ルートはコンポーネントプロパティとして NotFoundComponent を使用します。 これは、ルーターがルートの一貫性を確認しているときにエラーをスローするのを避けるために必要であるため、コンポーネントを定義する必要があります。

ところで、これは静的ルートを定義する場合にのみ必要であるため、遅延ロードモジュールで ActionLinkObserver を使用するときはいつでも、コンポーネントプロパティを未定義のままにすることができます。

Observer の登録

ルーティングガードとして機能することに加えて、サービスは任意のコンポーネントまたはディレクティブに挿入できるため、後者は必要に応じてリンクのアクティブ化に基づいて機能します。

gist.github.com

register() メソッドを呼び出すことにより、サービスは Observable を返します。この Observable は、指定されたリンクがアクティブになると発行されます。

フィルタリングメカニズムは、関数の呼び出しに沿って渡されるアクションコードを、ルート構成で定義されているルートパス値と比較することで実現されます。

最終的にルート内でエンコードされるすべてのクエリパラメーターは、プロパティとして単一のオブジェクトにパックされ、サブスクライバーに渡されるため、結果のアクションの動作をさらにカスタマイズできます。

ActionLink Directive

汎用ディレクティブでもまったく同じロジックを実装できます。

gist.github.com

この実装では、 wmActionLink 入力が動作するリンクパスを取得し、それに応じて ActionLinkObserver サービスに登録して、結果を activate 出力に出力します。

すべてまとめる

すべてのピースを配置したら、ポップアップダイアログを表示できます。

gist.github.com

ここでは、 MatDialog の declarative version を使用しています。

このダイアログは、wmActionLink ディレクティブを使用して app.component.html テンプレートで宣言され、アクティブ化されると開きます。

自分で試してみてください

ここで説明するコードは、Github でホストされるオープンソースプロジェクトである wizdm.io の一部です。 質問や好奇心については、 hello@wizdm.io までお気軽にご連絡ください。

ここで説明するコードの完全に機能するデモは、 StackBlitz でライブで利用できます。

stackblitz.com

medium.com

medium.com

11 Must-Know FrontEnd Trends for 2020 の翻訳

11 Must-Know FrontEnd Trends for 2020 の翻訳です 2020年 11 の知っておくべきフロントエンドトレンド - 昼食で、スマートにフロントエンドの会話をする方法

f:id:ic_lifewood:20200104195311p:plain

チームのランチトークでスマートに話すことは、最新のフロントエンドトレンドを常に最新の状態に保つ大きな理由です。 それはあなたがより良い開発者になり、より良い技術とより良い製品を構築するのに役立つかもしれません。 多分。

それで、いくつかの興味深い方向にあなたを向けることによって、この名誉あるクエストをより簡単にさせてください。 A 〜 Z のすべての概念を説明するわけではありませんが、その概念、それがどのように有用であり、さらなるリソースにつながるかを紹介します。

たとえば、 Micro Fontends 、 Atmoic Design 、 Web コンポーネント TS take-over 、ESM CDN、さらにはデザイントークンの概要を簡単に説明します。 自由にスクロールして、詳細を知りたいトピックをマークしてください。 ご質問やその他の提案については、コメントを下にドロップしてください。 楽しんで!

・・・・・・

1. Micro frontends

Micro frontendsは、昼食の会話で最も話題の多いフロントエンドトピックです。

皮肉なことに、フロントエンド開発はコンポーネントのモジュール式の利点を享受していますが、それでもバックエンドのマイクロサービスよりもはるかに monolithic です。

f:id:ic_lifewood:20200104195956p:plain

マイクロフロントエンドは、アプリのさまざまな部分で作業するさまざまなチームのために、フロントエンドアーキテクチャをさまざまなフロントエンドに分割することを約束します。 各チームは、マイクロフロントエンドのエンドツーエンドのライフサイクル全体にわたって自律性を獲得できます。これは、ビットなどのツールを使用して、個別に開発、バージョン管理、テスト、構築、レンダリング、更新、展開できます。

ここでコンセプト全体を説明する代わりに、 @martinfowler ブログで公開されている @thecamjackson によるこの素晴らしい投稿を読んでください。 これは本当に良いことであり、この概念を掘り下げるために必要なすべてを網羅しているはずです。

f:id:ic_lifewood:20200104201154p:plain

しかし、今日のエコシステムにはまだ一定の不足があります。 ほとんどの場合、人々は個別のフロントエンドの展開、バンドル、環境の違いなどの問題を心配しています。 Bit を使用すると、個々のフロントエンド/コンポーネントを分離、バージョン化、ビルド、テスト、更新できます。 現在のところ、これは主に複数のアプリケーションを使用する場合に便利です(ただし、コンポーネントを介して既存のアプリケーションの一部を徐々にリファクタリングするために既に一般的に使用されています)。

Bit が 2020 年に展開を導入すると、独立したチームは、スタンドアロンのフロントエンドを開発、構成、バージョン管理、展開、および更新することができます。 UIアプリを一緒に構成し、チームが独立した継続的な展開とインクリメンタルアップグレードを使用して単純な分離コードベースを作成できるようにします。 これらのフロントエンドの構成により、アプリケーションが作成されます。 Bit を使用して作成されたアプリは次のようになります。

f:id:ic_lifewood:20200104201708p:plain

もっと詳しく知る:

martinfowler.com

2. Atomic Design

f:id:ic_lifewood:20200104201958j:plain
Read: Atomic Design Explained in 30 seconds!

Atomic Design は、ランチトークのもう1つの非常に興味深いトピックであり、純粋な方法論というよりも哲学として考えるのが好きです。

簡単に言うと、 Brad Frost によって導入された理論は、Webアプリケーションの構成を、 Atoms , Molecules , Organisms などの自然な構成と比較し、具体的なWebページで終わります。 Atoms は Molecules を構成します(例:テキスト入力+ボタン+ラベル Atoms =検索 Molecules )。 Molecules は Organisms を構成します。 Organisms はレイアウト template に存在し、ユーザーに配信されるページに具体化できます。

30 秒間の詳細な説明と視覚的な例を示します。 素晴らしい芸術的才能で私が作成した非常に印象的な図面が含まれています。これをコピーしてオフィスボードに貼り付けることができます。😆

Atomic コンポーネントの利点は、モジュール式で再利用可能なコンポーネントを介したモジュール式 UI アプリケーションの構築にとどまりません。 このパラダイムにより、構成を考えるように強制されるため、すべてのコンポーネントの役割と API 、それらの階層、およびアプリケーションの構築プロセスを効果的かつ効率的な方法で抽象化する方法をよりよく理解できます。 ご覧ください。

bradfrost.com

blog.bitsrc.io

3.カプセル化されたStyling と Shadow Dom

f:id:ic_lifewood:20200104203043p:plain
Source: developer.mozzila.org

コンポーネントの重要な側面はカプセル化です。マークアップ構造、スタイル、および動作をページ上の他のコードから隠して分離できるため、異なる部分が衝突せず、コードをきれいに保つことができます。 Shadow DOM API はこの重要な部分であり、隠された分離された DOM を要素にアタッチする方法を提供します。

Shadow DOMは、実際には長い間ブラウザで実際に使用されています。 Shadow DOM は “DOM within a DOM” と考えることができます。 これは、独自の要素とスタイルを持つ独自の分離DOMツリーであり、元のDOMから完全に分離されています。

非表示の DOM ツリーを通常の DOM ツリーの要素にアタッチできます。この Shadow DOM ツリーは、通常の DOM と同様に、下にあるシャドウルートで始まり、必要な要素にアタッチできます。 これの主な意味は、名前の衝突やスタイルの流出のリスクがないため、クラスの名前空間が必要ないことです。 追加の利点もあります。 多くの場合、 Web コンポーネントのスタイルの真のカプセル化に対する長年の有望なソリューションと呼ばれています。 もっと詳しく知る:

developer.mozilla.org

4. TypeScript take over

したがって、最近のすべての会話は、 TS がフロントエンド開発を引き継いでいるように聞こえます。 開発者の 80 %が次のプロジェクトで TypeScript を使用または学習したいと認めていることが報告されています。

欠点はありますが、 TS コードは理解しやすく、実装が速く、バグが少なく、定型文も少なくて済みます。 TS で動作するように React アプリをリファクタリングしたいですか? 頑張れ。 徐々に始めたいですか? Bit のようなツールを使用して、アプリ内のコンポーネントをTSに徐々にリファクタリングし、 React-Typescript コンパイラを使用してアプリから独立してビルドします。 この方法により、コードを一度に 1 コンポーネントずつ徐々にアップグレードできます。

もっと詳しく知る:

medium.com

eng.lyft.com

5. Web components

f:id:ic_lifewood:20200104204941p:plain

基本的に、これは未来です。 どうして? これらの純粋な Web コンポーネントフレームワークに依存せず、フレームワークなしで、またはフレームワークのスペルの標準化で動作できるためです。 JS の疲労から解放され、最新のブラウザーでサポートされているためです。 バンドルのサイズと消費量が最適であり、 VDOM レンダリングは驚くべきものだからです。

これらのコンポーネントは、新しい種類の html タグ、レイアウトを指定する HTML テンプレート、および当然コンポーネント固有の Shadow DOM を定義できる Javascript API であるカスタム要素を提供します。

この分野で有名な著名なツールは、 Lit-html (および Lit-element)、 StencilJSSvelteJS 、そしてもちろん、どこでも直接共有、消費、開発できる再利用可能なモジュラーコンポーネント用の Bit です。

UI 開発の未来を考え、コンポーネントの時代にモジュール性、再利用性、カプセル化、標準化の原則がどのように見えるかを考えると、 Web コンポーネントが答えになります。 もっと詳しく知る:

6.コンポーネントライブラリからダイナミックコレクションまで

f:id:ic_lifewood:20200104210330p:plain
Organize components in dynamic collections; reuse, compose, stay independent

コンポーネント駆動型開発の出現により、さまざまなツールが誕生しました。 有名なツールの1つは、そのホストプラットフォームである Bit.dev と並んで Bit です。

面倒で高度に結合されたコンポーネントライブラリを構築するために一生懸命働く代わりに、Bitを使用して、既存のコンポーネントを動的に再利用可能な共有コレクションに継続的に分離およびエクスポートします。

Bit(GitHub) を使用すると、UI コンポーネントを個別に分離、バージョン化、ビルド、テスト、および更新できます。 既存のアプリのコンポーネントを分離し、リモートコレクションに収集し、どこでも使用するプロセスを合理化します。 すべてのコンポーネントは、プロジェクトの外部でビルド、テスト、およびレンダリングできます。 アプリ全体ではなく、単一のコンポーネント(および依存コンポーネント)を更新できます。

f:id:ic_lifewood:20200104210925g:plain

bit.dev プラットフォーム(または独自のサーバー)で、コンポーネントをリモートでホストし、さまざまなチーム向けに整理して、すべてのチームが独自のコンポーネントの開発を制御できるようにします。 すべてのチームはコンポーネントを共有および再利用できますが、その独立性と制御を維持します。

このプラットフォームは、すぐに使用できる共有コンポーネントのオールインワンエコシステムも提供します。UI コンポーネントの自動ドキュメント化、インタラクティブなプレイグラウンドでのコンポーネントレンダリング、 npm / yarn を使用してコンポーネントをインストールするための組み込みレジストリも提供します。さらに、任意のリポジトリで変更のためにコンポーネントbit import できます。

f:id:ic_lifewood:20200104211517g:plain

短期的には、これは、 Spotify / iTunes が静的 CD 音楽アルバムを介して以前に音楽を共有するプロセスを変更したのと同様の方法で、コンポーネントの共有および構成プロセスに革命をもたらします。 動的でモジュール式のソリューションであり、誰もがコンポーネントを共有して使用できます。

長い目で見れば、 Bit は micro-frontends への道を開くのに役立ちます。 どうして? UI アプリケーションの一部を個別にバージョン管理、テスト、ビルド、および更新できるためです。 2020 年には独立した展開が導入され、最終的に異なるチームがアプリの一部をエンドツーエンドで所有できるようになります:分離されたシンプルなコードベースを維持し、チームが慎重かつ継続的に UI の増分アップグレードを構築して展開し、フロントエンドを一緒に構成できるようにします。

bit.dev

bit.dev

github.com

7.状態管理:Bye Bye Redux? (ない…。)

f:id:ic_lifewood:20200104212208p:plain

Redux は辞めるのが難しい道具です。 フロントエンドのモジュール化が進むにつれて、アプリの状態をグローバルに管理することの苦痛はより明確になりますが、 Redux の非常に有用な機能により、多くのチームにとって重要なソリューションになります。

2020 年に Redux に別れを告げますか? おそらく完全ではない 😄

ただし、状態( React フック、 Context-API など)を処理するフレームワーク内の新機能の蜂起は、グローバルストアなしで未来への道を描いています。 Mobx のようなツールは、ほんの1年前にはあまり採用されていませんでしたが、コンポーネント指向でスケーラブルな性質のおかげで、毎日人気が高まっています。 他の選択肢についてはこちらをご覧ください。

読む:Making Sense of React HooksDan Abramov

8. ESM CDN

f:id:ic_lifewood:20200104213925j:plain

ES モジュールは、ブラウザでモジュールを操作するための標準であり、 ECMAScript によって標準化されています。 ES モジュールを使用すると、機能を CDN などで使用できるモジュールに簡単にカプセル化できます。 Firefox60 のリリースにより、すべての主要なブラウザーが ES モジュールをサポートし、Node mteamは Node.js への ES モジュールサポートの追加に取り組んでいます。 また、 WebAssembly の ES モジュール統合は、今後数年間で行われます。 CDN を介してアプリで構成されるモジュラー Bit UI コンポーネントを想像してください…

9.プログレッシブ Web アプリ。 まだ成長しています。

プログレッシブ Web アプリケーションは、最新のテクノロジーを利用して、最高の Web アプリとモバイルアプリを組み合わせます。 Web テクノロジーを使用して構築された Web サイトであると考えてください。 ブラウザとサービスワーカーの可用性、およびキャッシュ API とプッシュ API の最近の進歩により、 Web 開発者はユーザーが Web アプリをホーム画面にインストールしたり、プッシュ通知を受信したり、オフラインで作業したりできるようになりました。

PWA は親密なユーザーエクスペリエンスを提供し、すべてのネットワーク要求はサービスワーカーを介してインターセプトできるため、中間者攻撃を防ぐためにHTTPSを介してアプリをホストすることが不可欠であり、これもセキュリティの向上につながります。 Facebook 開発者の Omer Goldberg による、PWAのベストプラクティスの概要を説明する素晴らしい講演です。

10.デザイナーと開発者の統合

f:id:ic_lifewood:20200104215312g:plain

製品やチーム全体で一貫した UI を実現するコンポーネント駆動設計システムの台頭により、デザイナーと開発者の間のギャップを埋めるための新しいツールが登場しました。 ただし、これは簡単な作業ではありません。 コード自体が本当に唯一の真実のソースである(これはユーザーが本当に得ているものです)が、ほとんどのツールはデザイナーの終わりからのギャップを埋めようとします。 このカテゴリには、Framer、Figma、Invision DSMなどがあります。

開発者の側から、次世代コンポーネントライブラリをホストし、共有コンポーネントの採用を支援する Bit.dev のようなプラットフォームを確認できます。 このプラットフォームは、実際のソースコードレンダリングされた視覚化を提供するため、設計者は開発者と協力して、ソースコード自体を視覚的に議論することができます。

注目すべきもう1つの有望なアイデアは、design-tokens です。 コードにトークンを配置することで、外部のコラボレーションツールを介して、デザイナーが単純なスタイリングの側面(色など)を直接制御できるようにします。 Bit.devなどのプラットフォームと統合されているため、これまでにないほどタイトなワークフローを作成できます。

dev.to

codeburst.io

blog.bitsrc.io

11. Web assembly — 未来へ?

Web assembly は言語の多様性を Web 開発にもたらし、 JavaScript によって生じたギャップをカバーします。 「スタックベースの仮想マシン用のバイナリ命令形式」として定義されています。 Wasm は、C / C++ / Rust のような高レベル言語のコンパイル用のポータブルターゲットとして設計されており、クライアントおよびサーバーアプリケーション用に Web 上に展開できます。

Eric Elliott は彼の投稿で、このコンセプトの利点を簡潔に説明しています。

  • JavaScript の改善:パフォーマンスに重要な要素を wasm に実装し、標準の JavaScript モジュールのようにインポートします。
  • 新しい言語:Web Assembly コードは、バイナリ形式で表される AST( Abstract Syntax Tree )を定義します。 読みやすいようにテキスト形式で作成およびデバッグできます。
  • ブラウザーの改善ブラウザーはバイナリ形式を理解するため、現在使用しているテキスト JavaScript よりも小さいサイズで圧縮するバイナリバンドルをコンパイルできるようになります。 ペイロードが小さいほど配信が高速になります。 コンパイル時の最適化の機会によっては、 Web Assembly バンドルも JavaScript よりも高速に実行される場合があります!
  • コンパイルターゲット:他の言語が Web プラットフォームスタック全体で一流のバイナリサポートを取得する方法

このコンセプト、それがなぜ役に立つのか、どこで使われるのか、なぜまだここにないのかについては、この素晴らしい投稿とこの素晴らしいビデオをお勧めします。

medium.com

・・・・・・

もっと詳しく知る

blog.bitsrc.io

blog.bitsrc.io

blog.bitsrc.io

blog.bitsrc.io

blog.bitsrc.io

Most in-demand JavaScript testing tools in 2020 の翻訳

Most in-demand JavaScript testing tools in 2020 - LogRocket Blog の翻訳です。

f:id:ic_lifewood:20200104163134p:plain

この記事では、2020年に中心となる JavaScript テストフレームワークを示すために、2019年の JavaScript の状態レポートのレビューと分析を行います。

JavaScript の状態

2019 年を迎えて、世界中の 21,000 人以上の開発者を調査した State of JS からの洞察に反映されている JavaScript の状態を見ていきます。

StateOfJSとは何ですか?

State of JS は基本的にすべての JavaScript の年次調査であり、調査を行う開発者の意見が記録され、その年の JavaScript の状態を示す洞察を示すために美しく視覚化されます。

データポイントには、フロントエンド Web 開発フレームワーク、データベース、状態管理、フレームワーク間の関係、受信と使いやすさ、 JavaScriptコンパイルされる言語、モバイルフレームワーク、ビルドツール、 JavaScript テストツールなどが含まれます。

これは、2016 年に Sacha Greif と他の数人の協力者によって開始された非常に包括的な JavaScript 調査です。 現在、この最新版では 21,000 を超える開発者の回答があります。

StateOfJS を選ぶ理由

私の意見では、 State of JS は実際には JavaScript のみに関する開発者アンケートとしては初めてのものであり、 JavaScript コミュニティに関する限りでは広く尊敬されています。

100,000 人以上の回答者を集めた StackOverflow 開発者調査のような他の非常に人気のある調査があります。 Jetbrain の State of Developer Ecosystem Report も非常に包括的で、6,000人を超える回答者がいます。

テストツール

調査の洞察によれば、これらは 2019 年の JavaScript 開発者による最も需要の高いテストツールであり、認識、関心、満足によって決定された重要度順に並べられています。

Jest

f:id:ic_lifewood:20200104170217p:plain

Jest は、 Facebook のチームによって構築され、常に保守されている最も人気のある JavaScript テストフレームワークの1つです。 これは、 React が推奨するゼロ構成の JavaScript テストフレームワークであり、最も使いやすいものです。

Jest は 2018 年に非常に印象的な受け入れ率を持ち、さらに今年は JavaScript コミュニティの中でさらに受け入れられています。 GitHub のデータによると、 Jest は現在 150 万以上のプロジェクトで使用されています。

過去 12 か月で、保持率は 39 %から 61 %に大幅に増加しました。 これは 2017 年から 2018 年にかけて増加したため、再発率です。

また、 Jest に興味を持つ人の割合が減少しました。 数は現在 29 %から 22 %に減少しています。 それらのほとんどは、リテンションインサイトによって示されるように、現在はリピーターユーザーです。

Mocha

f:id:ic_lifewood:20200104171021p:plain

Mocha は何年もの間、最も使用されている JavaScript テストフレームワークの1つです。 サードパーティアサーション、モック、 Chai や Enzyme などのスパイツールで使用されます。 大規模なエコシステムの他に、 Mocha には優れたドキュメントを備えた十分に確立されたオプションがあります。

これは非常に柔軟で、多くの拡張機能に対してオープンです。 GitHub のデータによると、 Mocha は 900,000 以上のプロジェクトで使用されています。

調査の洞察によると、保持率は過去 12 か月で 39 %から 42 %に増加しました。 回答者の約 8 %は、 Mocha について聞いたことがない。また、昨年 10 %だったため、 Mocha が常に埋めている認識のギャップがあります。

Storybook

f:id:ic_lifewood:20200104171457p:plain

Storybookは、UIコンポーネントの開発環境です。

コンポーネントライブラリの参照、各コンポーネントのさまざまな状態の表示、およびコンポーネントインタラクティブな開発とテストを行うことができます。 GitHub で約 44,000 回主演されており、大規模なユーザーベースを持っています。

Storybook を使用した保持率は、12 か月で 15 %から 32 %に倍増し、同じ時間枠で関心レベルも 23 %から 26 %に上昇しました。

Storybook は昨年、デベロッパーの注目を集めていませんでしたが、 2019 年に大きく成長し、 2020 年に向かっています。興味深い年になります。

Cypress

f:id:ic_lifewood:20200104171832p:plain

Cypress は、非常に高速で信頼性の高い JavaScript テストツールです。 基本的に、 Web アプリケーションにテストを挿入し、非常に明確で広範なドキュメントを提供し、 TestCafe と呼ばれる別のテストフレームワークと常に競合しています。

GitHub のデータによると、25,000 以上のプロジェクトで使用されています。

Cypress の保有率は 23 %、金利は 28 %です。 認識のギャップがあり、Cypress はそれを埋めるために取り組んでいます。

Enzyme

f:id:ic_lifewood:20200104172041p:plain

Enzyme は、 React の JavaScript テストユーティリティであり、 React コンポーネントの出力を簡単にテストできます。 また、出力を指定してランタイムを操作、トラバース、およびいくつかの方法でシミュレートすることもできます。

Enzyme の API は、 DOM 操作およびトラバーサル用の jQueryAPI を模倣することにより、直感的で柔軟なものにすることを目的としています。

保持率は過去 12 か月で 20 %から 23 %に増加しました。 46 %から 38 %に至るまで、認識のギャップを埋めます。

Ava

f:id:ic_lifewood:20200104172642p:plain

Ava は Node.js のテストランナーであり、簡潔な API 、詳細なエラー出力、新しい言語機能の採用、テストをより効果的に記述できるプロセス分離を備えています。

Ava を使用すると、さらに素晴らしいコードを出荷できます。 GitHub のデータによると、現在 47,000 のプロジェクトで使用されています。

昨年、 JavaScript 開発者の約 72 %が Ava について知っていました。 今年、その数は 69 %に減少し、保持率は 5 %に増加しました。

Jasmine

f:id:ic_lifewood:20200104173008p:plain

Jasmine は、 JavaScript の動作駆動開発テストフレームワークです。

ブラウザ、 DOM 、または JavaScript フレームワークに依存しません。 その結果、 Web サイト、 Node.js プロジェクト、または JavaScript を実行できるあらゆる場所に適しています。

調査の洞察によれば、保持率は過去 12 か月でわずかに増加しました。 ただし、 Jasmine は 2020 年に橋渡しを試みることができる意識のギャップが大きくなっています。

Puppeteer

f:id:ic_lifewood:20200104173329p:plain

Google のチームによって構築された Puppeteer は、 DevTools プロトコルChrome または Chromium を制御するための高レベル API を提供する Node ライブラリです。

Puppeteer はデフォルトでヘッドレスで実行されますが、フル(ヘッドレスではない) Chrome または Chromium を実行するように構成できます。 また、ネイティブなので高速です。

調査の洞察では、Puppeteer の保持率は 24.3 %、金利は 24 %です。 55,000 以上のプロジェクトで既に使用されていますが、この製品にはより多くの認知度が必要です。

要約

Puppeteer と Cypress は、今年 JavaScript 開発者によって特定された新規参入者です。 2016 年以来、 Mocha 、 Jasmine 、 Jest 、 Enzyme 、 および Ava です。

開発者からテストツールまでの種類が均等に分布しているようですが、 Jest は 96 %以上のユーザーがリピーターで市場をリードしているようです。

どのテストフレームワークを使用していますか? コメント欄で教えてください。

プラグ: LogRocket 、 Web アプリ用の DVR

f:id:ic_lifewood:20200104174002p:plain

LogRocket は、問題を自分のブラウザで発生したかのように再現できるフロントエンドアプリケーション監視ソリューションです。 LogRocket では、エラーが発生した理由を推測したり、スクリーンショットやログダンプをユーザーに要求したりする代わりに、セッションを再生して、問題の原因をすばやく把握できます。 フレームワークに関係なく、どのアプリでも完全に動作し、 Redux 、 Vuex 、 及び @ngrx/store から追加のコンテキストを記録するプラグインがあります。

Redux のアクションと状態のログに加えて、 LogRocket はコンソールログ、 JavaScript エラー、スタックトレース、 headers + bodies を含むネットワーク requests/responses 、 browser metadata 、カスタムログを記録します。 また、 DOM を器具して HTML と CSS をページに記録し、最も複雑な単一ページのアプリでさえも完璧な動画を再現します。

React アプリの完全な可視性

React アプリケーションのデバッグは、特にユーザーが再現するのが難しい問題を経験する場合、困難になる可能性があります。 Redux の状態の監視と追跡、 JavaScript エラーの自動表示、遅いネットワーク要求とコンポーネントの読み込み時間の追跡に関心がある場合は、LogRocket を試してください。

f:id:ic_lifewood:20200104175234p:plain f:id:ic_lifewood:20200104175100p:plain

LogRocket は Web アプリの DVR のようなもので、文字通り React アプリで発生するすべてを記録します。 問題が発生する理由を推測する代わりに、問題が発生したときのアプリケーションの状態を集計して報告できます。 LogRocket は、アプリのパフォーマンスも監視し、クライアント CPU 負荷、クライアントメモリ使用量などのメトリックでレポートします。

LogRocket Redux ミドルウェアパッケージは、ユーザーセッションに可視性のレイヤーを追加します。 LogRocket は、 Redux ストアからのすべてのアクションと状態を記録します。

React アプリのデバッグ方法を最新化してください - 無料で監視を開始してください。

無料でお試しください。

Angular 9/8 Tutorial: Build a Web App with HttpClient and RxJS の翻訳

itnextAngular 9/8 Tutorial: Build a Web App with HttpClient and RxJS の翻訳です。

f:id:ic_lifewood:20200104014414j:plain

この Angular 9 チュートリアルでは、 REST API の作成/シミュレーション、新しいプロジェクトの足場、重要なAPIの設定、最終的なアプリケーションの構築とデプロイから必要なすべてのステップを経て Angular 9 サンプルアプリケーションをクラウドへ構築する方法を学びます。

  • 例として、URLクエリ文字列とパラメーターを使用して GET リクエストを送信し、 JSON データを取得および使用するために Httplient を使用して、 Angular 9/8 アプリケーションの REST API サーバーから HTTP 応答を処理する方法、 HTTP エラーのエラー処理方法を学習します RxJS throwError() および catchError() 演算子、RxJS retry() および takeUntil() 演算子を使用して、劣悪なネットワーク接続で失敗した HTTP 要求を再試行し、保留中の要求をキャンセルする方法、最後に最新の Angular 8.3以上の機能です。
  • また、 Angular サービスと RxJS Observables の使用方法を確認し、プロジェクトで Angular Material を設定し、 Material Design コンポーネントで UI をスタイルする方法を学びます。
  • Angular 8.3+ の新しい ng デプロイ機能を使用して、 Angular 9 アプリケーションをコマンドラインから Firebase ホスティングに簡単にデプロイする方法について説明します。

現在、Angular 9 は RC バージョンであり、特に新しい Ivy レンダラーをはじめとするさまざまな新機能と改善が含まれています。

このチュートリアルは、最新のAngular 9バージョンに更新されました。

注:HTTP クライアント API の改良版である HttpClient を使用していることに注意してください。これは、 Angular バージョン 4.3.0-rc.0 以降で利用可能です。 古い HTTP クライアントは、Angular 9では使用できません。

このチュートリアルでは、 Angular 9 で HttpClient を使用して、サードパーティREST API から JSON データを取得するニュースアプリケーションを構築する方法も確認できます。

このステップバイステップのAngular 9チュートリアルでは、@angular/common/http パッケージから入手できる HttpClient を使用して、get() メソッドを使用して HTTP GET リクエストを作成する方法の実用的な例を見ていきます。

mid_content 143について説明

  • 疑似動作機能する作成し、 JSON REST API を完成させる方法、
  • Angular CLI v9 のインストール方法、
  • Angular CLI を使用して Angular 9 プロジェクトを作成する方法、
  • Angular Material をセットアップし、Material Design でアプリケーションをスタイルする方法、
  • Angular コンポーネントの作成方法、それらの間のルーティングとナビゲーション、
  • Angular サービスを作成および注入する方法、
  • HttpClient を使用してサーバーにHTTP GETリクエストを送信する方法、
  • HttpParams クラスを使用して、HttpRequest に URL クエリ文字列を追加する方法、
  • HttpClient によって返された RxJS Observables をサブスクライブおよびサブスクライブ解除する方法、
  • throwError() および catchError() 演算子を使用して HTTP エラーを処理する方法、
  • RxJS retry() 演算子を使用して失敗した HTTP 要求を再試行する方法、
  • リクエストがキャンセルされたときに takeUntil() 演算子を使用して、 HttpClient メソッドから返された RxJS Observables を unsubscribe する方法、
  • Angular 8.3+ から利用可能な新しい ng deploy コマンドを使用して、実稼働用のアプリケーションをビルドし、 Firebase ホスティングにデプロイする方法

この Angular 9 チュートリアルの手順は次のとおりです。

  • ステップ01 — Angular CLI v9 のセットアップ
  • ステップ02 — 新しい Angular 9 サンプルプロジェクトの初期化
  • ステップ03 — 疑似 JSON REST API をセットアップする
  • ステップ04 — サンプルプロジェクトで Angular HttpClient v9 を設定する
  • ステップ05 — Angular 9 コンポーネントの作成
  • ステップ06 — Angular 9 ルーティングを追加する
  • ステップ07 — Angular Material v9 を使用して UI をスタイル設定する
  • ステップ08 — Angular HttpClient v9 で JSON REST API を使用する
  • ステップ09 — RxJS catchError() および HttpClient を使用した HTTP エラー処理の追加
  • ステップ10 — RxJS retry() および HttpClient を使用して失敗した HTTP リクエストを再試行する
  • ステップ11 — RxJS takeUntil() を使用した HttpClient Observablesからのサブスクライブ解除
  • ステップ12 — HttpClient get() メソッドに URL クエリパラメーターを追加する
  • ステップ13 — Angular HttpClient v9 で完全な HTTP レスポンスを取得する
  • ステップ14 — Angular HttpClient v9 で型指定された HTTP 応答を要求する
  • ステップ15 — Angular 9 アプリケーションを Firebase Hosting にビルドおよびデプロイする

Angular HttpClient 、その機能、およびそれを使用する理由を紹介することから始めましょう。

Angular HttpClient とは何ですか?

Angular などのフレームワークを使用して構築されたフロントエンドアプリケーションは、 XMLHttpRequest インターフェイスまたは fetch() API を使用して、 REST API ( HTTP プロトコルに基づく)を介してバックエンドサーバーと通信します。

Angular HttpClient は、最新のブラウザーとレガシーブラウザーの両方をサポートする XMLHttpRequest インターフェイスを利用します。

HttpClient は @angular/common/http パッケージから入手でき、簡単なAPIインターフェイスと、簡単なテスト容易性、型指定された要求および応答オブジェクト、要求および応答インターセプター、RxJS Observables を備えたリアクティブ API 、合理化されたエラー処理などの強力な機能を備えています。

Angular HttpClient を使用する理由

HttpClient ビルトインサービスは、 Angular 開発者に多くの利点を提供します。

  • HttpClient を使用すると、 HTTP 要求と応答を簡単に送信および処理できます。
  • HttpClient には、テストユニットを実装するための多くの組み込み機能があり、
  • HttpClient は、次のような一般的な Web 開発タスクを簡素化する Promise の代わりに、 RxJS Observables を使用して非同期操作を処理します。
    • HTTP リクエストの集中、
    • ダウンロードおよびアップロード操作の進行を聞いて、
    • 簡単なエラー処理、
    • 失敗したHTTP要求などの再試行

HttpClient を紹介した後、 Angular 9 チュートリアルを正常に完了するために必要な前提条件からサンプルアプリケーションの構築に進みましょう。

前提条件

始める前に、いくつかの前提条件が必要です。

  • TypeScript の基本的な知識。 特に、TypeScript クラスやデコレータなどのオブジェクト指向の概念に精通している。
  • NPM 6+ がインストールされた Node10+ を備えたローカル開発マシン。 最近のほとんどのフロントエンドツールのように、 Angular CLI にはノードが必要です。 公式 Web サイトのダウンロードページにアクセスして、オペレーティングシステムのバイナリをダウンロードするだけです。 パッケージマネージャを使用してNodeをインストールする方法については、特定のシステム手順を参照することもできます。 ただし、推奨される方法は、 NVM — Node Version Manager — POSIX 準拠の bash スクリプトを使用して、複数のアクティブな Node.js バージョンを管理することです。

注:Angular開発用のローカル環境をインストールしたくないが、このチュートリアルのコードを試してみたい場合は、Angular CLI と互換性のあるAngularプロジェクトを作成するために使用できるフロントエンド開発用のオンラインIDEであるStackblitzを使用できます。

以前の前提条件がある場合、Angular HttpClient を使用して JSON データと catchError() などのさまざまな RxJS オペレーターを取得するための HTTP GET リクエストを送信する方法を例として説明する、 Angular 9 チュートリアルの次のステップに進む準備ができています。 エラー処理、失敗した HTTP 要求の再試行、保留中の要求のキャンセルなどの高度な機能を実装するための tap()retry() 、および takeUntil()

チュートリアルの最初のステップでは、 Angular CLI 9 をインストールし、ゼロからサンプルプロジェクトを作成する方法を見ていきます。

ステップ01 — Angular CLI v9 のセットアップ

この手順では、最新の Angular CLI 9 バージョンをインストールします(このチュートリアルの執筆時点)。

注:これらの手順は、 Angular 8 でも有効です。

f:id:ic_lifewood:20200104052525j:plain

Angular CLI は、 Angular プロジェクトを初期化して操作するための公式ツールです。 それをインストールするには、新しいコマンドラインインターフェイスを開き、次のコマンドを実行します。

$ npm install -g @angular/cli@next

このチュートリアルを書いている時点で、 angular/cli v9.0.0-rc.2 がシステムにインストールされます。

Angular 9 が正式にリリースされるまで、 @next タグを使用して最新のプレリリースバージョンをインストールする必要があることに注意してください。

ng version コマンドを実行すると、同様の出力が得られます。

Angular CLI: 9.0.0-rc.2
Node: 10.16.3
OS: win32 ia32
Angular:
...Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.900.0-rc.2
@angular-devkit/core         9.0.0-rc.2
@angular-devkit/schematics   9.0.0-rc.2
@schematics/angular          9.0.0-rc.2
@schematics/update           0.900.0-rc.2
rxjs                         6.5.3

次のステップでは、コマンドラインから新しいサンプルプロジェクトを初期化する方法を学習します。

ステップ02 — 新しい Angular 9 サンプルプロジェクトの初期化

このステップでは、サンプルプロジェクトの作成に進みます。 コマンドラインインターフェイスに戻り、次のコマンドを実行します。

$ cd ~
$ ng new angular-httpclient-example

CLIからいくつか質問があります。 Angular ルーティングを追加しますか? [はい]の y と入力し、どのスタイルシート形式を使用しますか? CSS を選択します。

これにより、プロジェクトにルーティングを自動的に設定するようにCLIに指示されるため、アプリケーションにナビゲーションを実装するためにコンポーネントのルートを追加するだけで済みます。

プロジェクトのフォルダー内で ng version コマンドを実行すると、同様の出力が得られます。

Angular CLI: 9.0.0-rc.2
Node: 10.16.3
OS: win32 ia32
Angular: <error>
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... routerPackage                         Version
---------------------------------------------------------
@angular-devkit/architect       0.900.0-rc.2 (cli-only)
@angular-devkit/build-angular   <error>
@angular-devkit/core            9.0.0-rc.2 (cli-only)
@angular-devkit/schematics      9.0.0-rc.2 (cli-only)
@schematics/angular             9.0.0-rc.2 (cli-only)
@schematics/update              0.900.0-rc.2 (cli-only)
rxjs                            6.5.3 (cli-only)
typescript                      3.6

次に、プロジェクトのフォルダーに移動し、次のコマンドを使用してローカル開発サーバーを実行します。

$ cd angular-httpclient-example
$ ng serve

ローカル開発サーバーは、 http://localhost:4200/ アドレスでリッスンを開始します。

f:id:ic_lifewood:20200104055526j:plain

Webブラウザーを開き、 http://localhost:4200/ アドレスに移動して、アプリが稼働していることを確認します。 これはこの時点でのスクリーンショットです。

f:id:ic_lifewood:20200104055653j:plain

ここで、開発サーバーを実行したままにして、次の手順の CLI コマンドを実行するための新しいコマンドラインインターフェイスを開始する必要があります。

次のステップでは、 Angular サンプルアプリケーションで使用する疑似 JSON REST API を作成する方法を学習します。

ステップ03 — 疑似 JSON REST API をセットアップする

Angularアプリケーションの開発に進む前に、 HttpClient を使用して JSON REST API を準備する必要があります。

サードパーティREST API サーバーから JSON データを消費または取得することもできますが、この例では、疑似 REST API を作成することを選択します。 実際の REST API の例については、このチュートリアルをご覧ください。 Angular に関する限り、疑似のAPIと実際の REST API の使用に違いはありません。

前述のように、外部 API サービスを使用するか、実際の REST API サーバーを作成するか、 json-server を使用して疑似 API を作成できます。 この例では、最後のアプローチを使用します。

したがって、新しいコマンドラインインターフェイスに戻り、プロジェクトの npm から json-server をインストールすることから始めます。

$ cd ~/angular-httpclient-example
$ npm install --save json-server

次に、Angularプロジェクトのルートフォルダーに サーバー フォルダーを作成します。

$ mkdir server
$ cd server

サーバー フォルダーで、 database.json ファイルを作成し、次の JSON オブジェクトを追加します。

{
    "products": []
}

この JSON ファイルは、 REST API サーバーのデータベースとして機能します。 REST API で提供するデータを追加するか、 Faker.js を使用して大量の現実的な疑似データを自動的に生成できます。

コマンドラインに戻り、サーバー フォルダーから戻って、次のコマンドを使用してnpmから Faker.js をインストールします。

$ cd ..
$ npm install faker --save

この例を作成すると、 faker v4.1.0 がインストールされます。

次に、 generate.js ファイルを作成し、次のコードを追加します。

var faker = require('faker');
var database = {
  products: []
};

for (var i = 1; i<= 300; i++) {
  database.products.push({
    id: i,
    name: faker.commerce.productName(),
    description: faker.lorem.sentences(),
    price: faker.commerce.price(),
    imageUrl: "https://source.unsplash.com/1600x900/?product",
    quantity: faker.random.number()
  });
}
console.log(JSON.stringify(database));

最初に faker をインポートし、次に製品の空の配列を1つ持つオブジェクトを定義しました。 次に、forループに入って、製品名を生成するために faker.commerce.productName() などの faker メソッドを使用して300の疑似エントリを作成しました。 利用可能なすべての方法を確認してください。 最後に、データベースオブジェクトを文字列に変換し、標準出力に記録しました。

次に、 generateserver スクリプトpackage.json ファイルに追加します。

  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "generate": "node ./server/generate.js > ./server/database.json",
    "server": "json-server --watch ./server/database.json"
  },

次に、コマンドラインインターフェイスに戻り、次のコマンドを使用して generate スクリプトを実行します。

$ npm run generate

最後に、次のコマンドを実行して REST API サーバーを実行します。

$ npm run server

通常の REST API サーバーと同じように、サーバーに HTTP リクエストを送信できるようになりました。 サーバーは http://localhost:3000/ アドレスから利用できます。

これらは、 JSON REST API サーバーを介して使用できる API エンドポイントです。

  • GET /products 製品取得
  • GET /products/<id> 製品取得 id 別
  • POST /products 製品新規作成
  • PUT /products/<id> 製品更新 id 毎
  • PATCH /products/<id> 製品部分更新 id 毎
  • DELETE /products/<id> 製品削除 id 毎

_page および _limit パラメーターを使用して、ページ分割されたデータを取得できます。 リンクヘッダーには、 最初最後リンク が表示されます。

例:

データの最初のページを取得するには GET /products?_page=1 、 データの最初のページの最初の5つの製品を取得するには、 GET /products?_page=1&_limit=5

注:フィルター、ソート、順序付けなどの他の機能を使用できます。 詳細については、ドキュメントをご覧ください。

JSON REST API サーバーを実行したままにして、次の手順のコマンドを入力するための新しいコマンドラインインターフェイスを開きます。

これまでの作業の概要として、 Angular CLI をインストールし、最新の Angular 9 バージョンに基づいて新しいプロジェクトを初期化しました。 次に、 JSON ファイルに基づいて json-server を使用して REST API を作成しました。 Angular 9 チュートリアルの次のステップでは、 Angular 9 プロジェクトで HttpClient を設定する方法を学びます。

ステップ04 — サンプルプロジェクトで Angular HttpClient v9 を設定する

このステップでは、この例の HttpClient モジュールのセットアップに進みます。

HttpClient は別の Angular モジュールにあるため、使用する前にメインアプリケーションモジュールにインポートする必要があります。

コードエディターまたはIDEでサンプルプロジェクトを開きます。 Visual Studio Code を使用します。

次に、 src/app/app.module.ts ファイルを開き、HttpClientModule をインポートして、次のようにモジュールの imports 配列に追加します。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

以上で、プロジェクトで HttpClient サービスを使用する準備が整いましたが、その前にいくつかのコンポーネント(ホームコンポーネントコンポーネント)を作成する必要があります。 これは、次のステップで行うことを学ぶものです。

ステップ05 — Angular 9 コンポーネントの作成

このステップでは、アプリケーション UI を制御する Angular コンポーネントの作成に進みます。

新しいコマンドラインインターフェイスに戻り、次のコマンドを実行します。

$ cd ~/angular-httpclient-example
$ ng generate component home

これはコマンドの出力です:

CREATE src/app/home/home.component.html (19 bytes)
CREATE src/app/home/home.component.spec.ts (614 bytes)
CREATE src/app/home/home.component.ts (261 bytes)
CREATE src/app/home/home.component.css (0 bytes)
UPDATE src/app/app.module.ts (467 bytes)

CLI は、コンポーネント用に4つのファイルを作成し、 src/app/app.module.ts ファイルの declarations 配列に追加しました。

次に、次のコマンドを使用してaboutコンポーネントを作成しましょう。

$ ng generate component about

次に、 src/app/about/about.component.html を開き、次のコードを追加します。

<p style="padding: 13px;">
An Angular 9 example application that demonstrates how to use HttpClient to consume REST APIs
</p>

次の手順でホームコンポーネントを更新します。

Angular 9 チュートリアルの次のステップでは、これらのコンポーネントルーターに追加します。

ステップ06 — Angular 9 ルーティングを追加する

このステップでは、例にルーティングを追加します。

ルーティング構成用に Angular CLI によって自動的に作成された src/app/app-routing.module.ts ファイルに戻り、コンポーネントをインポートして、次のようにルートを追加します。

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full'},
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

最初にhome と about コンポーネントについてインポートし、次に空のパスをホームコンポーネントにリダイレクトするためのルートを含む 3 つのルートを追加しました。これにより、ユーザーがアプリにアクセスすると、ホームページにリダイレクトされます。

この例の次のステップでは、UIスタイルを設定するためにプロジェクトに Angular Material を設定します。

ステップ07 — Angular Material v9 を使用して UI をスタイル設定する

Angular 9 チュートリアルのこの手順では、 Angular Material をプロジェクトに追加し、アプリケーション UI のスタイルを設定します。

Angular Material は、開発者がプロフェッショナルな UI を作成できる Material Design コンポーネントを提供します。 Angular CLI v7 + の新しい ng add コマンドを使用すると、プロジェクトで Angular Material を簡単に設定できます。

コマンドラインインターフェイスに戻り、プロジェクトのルートから次のコマンドを実行します。

$ ng add @angular/material

テーマを選択するよう求められます。 Indigo/Pink を選択します。

その他のオプション—ジェスチャー認識用に HammerJS をセットアップしますか? Angular Material のブラウザアニメーションを設定しますか? キーボードの Enter キーを押すだけで、デフォルトの回答を選択できます。

次に、 src/styles.css ファイルを開き、テーマを追加します。

@import "~@angular/material/prebuilt-themes/indigo-pink.css";

各 Angular Material コンポーネントには、コンポーネントを使用する前にインポートする必要がある個別のモジュールがあります。 src/app/app.module.ts ファイルを開き、次のインポートを追加します。

import { MatToolbarModule,
  MatIconModule,
  MatCardModule,
  MatButtonModule,
  MatProgressSpinnerModule } from '@angular/material';

次のモジュールをインポートしました。

  • MatToolbar ヘッダー、タイトル、またはアクションのコンテナーの提供
  • MatCard 単一の件名のコンテキストでテキスト、写真、およびアクションのコンテンツコンテナーを提供
  • MatButton マテリアルデザインのスタイリングとインクの波紋で強化されたネイティブの <button> または <a> 要素を提供
  • MatProgressSpinner 進行状況とアクティビティの循環インジケータを提供

次に、これらのモジュールを imports 配列に含める必要があります。

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AboutComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatToolbarModule,
    MatIconModule,
    MatButtonModule,
    MatCardModule,
    MatProgressSpinnerModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

次に、 src/app/app.component.html ファイルを開き、次のように更新します。

<mat-toolbar color="primary">
  <h1>
    ngStore 
  </h1>
  <button mat-button routerLink="/">Home</button>
  <button mat-button routerLink="/about">About</button>
</mat-toolbar>
<router-outlet></router-outlet>

ホームとコンポーネントに関する2つのナビゲーションボタンを備えたトップバーを含むアプリケーションのシェルを作成しました。

チュートリアルのこの時点までに行ったことの概要として、プロジェクトに HttpClient と Angular Material v9 をセットアップし、ホームとコンポーネントについて作成し、ルーティングを構成し、最後にナビゲーション付きのトップバーを含むアプリケーションのシェルを追加しました。

チュートリアルの次のステップでは、 HttpClient v9 を使用して REST API サーバーから JSON データを取得する方法を学習します。

ステップ08 — Angular HttpClient v9 で JSON REST API を使用する

このステップでは、サンプルアプリケーションの REST API サーバーから JSON データを使用します。

REST API サーバーからのデータの消費を処理するコードをカプセル化するために、 Angular サービスを作成する必要があります。

サービスは、 Angular 依存性注入を使用して他のサービスおよびコンポーネントによって注入できるシングルトンです。

ソフトウェアエンジニアリングでは、依存性注入は、あるオブジェクトが別のオブジェクトの依存性を提供する手法です。 ソース

次に、 JSON REST API と連動する Angular サービスを生成します。 コマンドラインインターフェイスに戻り、次のコマンドを実行します。

$ ng generate service data

次に、 src/app/data.service.ts ファイルを開き、次のように HttpClient をインポートして注入します。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private REST_API_SERVER = "http://localhost:3000";

  constructor(private httpClient: HttpClient) { }

}

HttpClient サービスをプライベート httpClient インスタンスとしてインポートおよび注入しました。 また、 REST API サーバーのアドレスを保持する REST_API_SERVER 変数を定義しました。

次に、 GET 要求を REST API エンドポイントに送信して JSON データを取得する sendGetRequest() メソッドを追加します。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private REST_API_SERVER = "http://localhost:3000";

  constructor(private httpClient: HttpClient) { }

  public sendGetRequest(){
    return this.httpClient.get(this.REST_API_SERVER);
  }
}

このメソッドは、単に HttpClientget() メソッドを呼び出して、 GET 要求を REST API サーバーに送信します。

次に、ホームコンポーネントでこのサービスを使用する必要があります。 src/app/home/home.component.ts ファイルを開き、次のようにデータサービスをインポートして注入します。

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  products = [];

  constructor(private dataService: DataService) { }

  ngOnInit() {
    this.dataService.sendGetRequest().subscribe((data: any[])=>{
      console.log(data);
      this.products = data;
    })  
  }
}

コンポーネントコンストラクターを使用して、プライベート DataService インスタンスとして dataService をインポートおよび注入しました。

次に、変数 products を定義し、 JSON REST API サーバーからデータを取得するためにサービスの sendGetRequest() メソッドを呼び出しました。

sendGetRequest() メソッドは、RxJS Observable である HttpClient.get() メソッドの戻り値を返すため、返された Observable にサブスクライブして、実際に HTTP GET 要求を送信し、 HTTP 応答を処理します。

データを受信後、 products 配列に追加しました。

次に、 src/app/home/home.component.html ファイルを開き、次のように更新します。

<div style="padding: 13px;">
  <mat-spinner *ngIf="products.length === 0"></mat-spinner>
  <mat-card *ngFor="let product of products" style="margin-top:10px;">
    <mat-card-header>
      <mat-card-title>{{product.name}}</mat-card-title>
      <mat-card-subtitle>{{product.price}} $/ {{product.quantity}}
      </mat-card-subtitle>
    </mat-card-header>
    <mat-card-content>
      <p>
        {{product.description}}
      </p>
      <img style="height:100%; width: 100%;" src="{{ product.imageUrl }}" />
    </mat-card-content>
    <mat-card-actions>
      <button mat-button> Buy product</button>
    </mat-card-actions>
  </mat-card>
</div>

products の配列の長さがゼロに等しい場合、つまり REST API サーバーからデータを受信しない前に、ロードスピナーを表示するために <mat-spinner> コンポーネントを使用しました。

次に、 products の配列を反復処理し、マテリアルカードを使用して各製品の名前価格数量説明画像を表示しました。

これは、JSON データが取得された後のホームページのスクリーンショットです。

次に、サービスにエラー処理を追加する方法を確認します。

ステップ09 — RxJS catchError() および HttpClient を使用した HTTP エラー処理の追加

この手順では、サンプルアプリケーションにエラー処理を追加します。

Angular の HttpClient メソッドは、エラーをキャッチして処理するための pipe() メソッドを介して Observables を返すため、RxJSの catchError() 演算子で簡単に使用できます。 サービス内のエラーを処理するメソッドを定義するだけです。

フロントエンドアプリケーションには 2 種類のエラーがあります。

  • ネットワークの問題、 JavaScript 構文およびタイプエラーなどのクライアント側エラー。 これらのエラーは ErrorEvent オブジェクトを返します。
  • サーバーのコードエラーやデータベースアクセスエラーなどのサーバー側エラー。 これらのエラーは HTTP エラー応答を返します。

そのため、エラーが適切に処理できるように、エラーのタイプを取得するには、エラーが ErrorEventインスタンスであるかどうかを確認するだけです。

それでは、例を見てみましょう。 src/app/data.service.ts ファイルを開き、それに応じて更新します。

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private REST_API_SERVER = "http://localhost:3000/products";

  constructor(private httpClient: HttpClient) { }

  handleError(error: HttpErrorResponse) {
    let errorMessage = 'Unknown error!';
    if (error.error instanceof ErrorEvent) {
      // Client-side errors
      errorMessage = `Error: ${error.error.message}`;
    } else {
      // Server-side errors
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    window.alert(errorMessage);
    return throwError(errorMessage);
  }
  public sendGetRequest(){
    return this.httpClient.get(this.REST_API_SERVER).pipe(catchError(this.handleError));
  }
}

ご覧のとおり、これはアプリケーション内の各サービスに対して行う必要があります。この例では 1 つのサービスしか含まれていませんが、アプリケーションがエラーをスローする可能性のある多くのサービスで成長し始めると、代わりに、より良いソリューションを使用する必要があります。 エラーが発生しやすい各サービスごとに handleError メソッドを使用します。 1 つの解決策は、 HttpClient interceptors を使用して、 Angular アプリケーションでエラーをグローバルに処理することです。

これは、サーバーに到達できない場合のコンソール上のエラーのスクリーンショットです。

次のステップでは、失敗した HTTP リクエストの送信を自動的に再試行することにより、データサービスを改善する方法を確認します。

ステップ10 — RxJS retry() および HttpClient を使用して失敗した HTTP リクエストを再試行する

Angular 9 チュートリアルのこのステップでは、 HttpClient で RxJS の retry() 演算子を使用して、返された Observable を自動的に resubscribing し、失敗した HTTP リクエストを再送信する方法を説明します。

多くの場合、エラーは一時的なものであり、ネットワークの状態が悪いため、再試行するだけで自動的に消えます。 たとえば、モバイルデバイスではネットワークの中断が頻繁に発生するため、ユーザーが再試行すると、成功した応答が返される場合があります。 ユーザーに手動で再試行させるのではなく、サンプルアプリケーションで自動的に再試行する方法を見てみましょう。

RxJS ライブラリには、いくつかの retry 演算子が用意されています。 その中には、指定した回数だけ RxJS Observable に自動的に再サブスクライブできる retry() があります。 HttpClient メソッドから返されたObservable を re-subscribe すると、サーバーに HTTP リクエストが再送信されるため、ユーザーは操作を繰り返したり、アプリケーションをリロードしたりする必要がありません。

エラーハンドラーの前に HttpClient メソッドから返された Observable に( pipe() メソッドを使用して)パイプすることにより、RxJSの retry() を使用できます。

src/app/data.service.ts ファイルに移動して、 retry() をインポートします。

import { retry, catchError } from 'rxjs/operators';

次に、 sendGetRequest() メソッドを次のように更新します。

  public sendGetRequest(){
    return this.httpClient.get(this.REST_API_SERVER).pipe(retry(3), catchError(this.handleError));
  }

これにより、失敗した HTTP 要求の送信が3回再試行されます。

次のステップでは、サンプルのホームコンポーネントで RxJS Observables の unsubscribe する方法を確認します。

ステップ11 — RxJS takeUntil() を使用した HttpClient Observablesからの Unsubscribing

Angular 9 チュートリアルのこのステップでは、 takeUntil() を使用して、コードで Observables が必要な理由と unsubscribe する方法について学習します。

まず、 HttpClient メソッドによって返される Observables から unsubscribe する必要がありますか?

通常、 Angular コンポーネントのサブスクライブされた RxJS Observables を手動で unsubscribing してメモリリークを回避する必要がありますが、 HttpClient の場合、これは HTT P応答の受信時に unsubscribe することにより、 Angular によって自動的に処理されます。 ただし、ユーザーがコンポーネントを離れようとしているときに保留中のリクエストをキャンセルするなど、手動で unsubscribe する必要がある場合があります。

コンポーネントngOnDestroy() ライフサイクルメソッドの subscribe() メソッドによって返される Subscription オブジェクトから unsubscribe() メソッドを呼び出すだけで、 Observable からサブスクライブを解除できます。

また、 takeUntil() を使用して、 Observables を unsubscribe または完了するより良い方法があります。

takeUntil() は、通知オブジェクト Observable が値を発行するまで、ソース Observable が発行した値を発行します。

コンポーネントが破棄されたときにこの演算子を使用して Observables を完了する方法を見てみましょう。

保留中のすべての HTTP リクエストの angular 4+を cancel / unsubscribe する方法をご覧ください。

src/app/home/home.component.ts ファイルを開き、次のように更新します。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { DataService } from '../data.service';
import {  takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit, OnDestroy {

  products = [];
  destroy$: Subject<boolean> = new Subject<boolean>();

  constructor(private dataService: DataService) { }

  ngOnInit() {
    this.dataService.sendGetRequest().pipe(takeUntil(this.destroy$)).subscribe((data: any[])=>{
      console.log(data);
      this.products = data;
    })  
  }

  ngOnDestroy() {
    this.destroy$.next(true);
    // Unsubscribe from the subject
    this.destroy$.unsubscribe();
  }

}

最初に、 OnDestroy インターフェース、 Subject 、および takeUntil() 演算子をインポートしました。 次に、 OnDestroy インターフェイスを実装し、コンポーネントngOnDestroy() ライフサイクルフックを追加しました。

次に、我々は takeUntil() 演算子の通知として使用されるブール値(値のタイプが実際にこの例では重要ではない)を放出することができるテーマのインスタンスを作成しました。

次に、 ngOnInit() ライフサイクルフックで、データサービスの sendGetRequest() を呼び出し、返された Observable の pipe() メソッドを呼び出して takeUntil() 演算子をパイプ処理し、結合された Observable にサブスクライブします。 subscribe() メソッドの本体に、取得した HTTP 応答のデータを products 配列に入れるロジックを追加しました。

takeUntil() オペレーターは、通知オブザーバブルから値が発行されるまで、通知された Observable が値を発行できるようにします。

Angularはコンポーネントを破棄するときに、 OnDestroy ライフサイクルメソッドを呼び出します。この場合、このメソッド はnext() メソッドを呼び出して値を発行し、RxJS がすべての subscribe 済み Observable を完了するようにします。

それでおしまい。 このステップでは、 HTTP 応答を受信する前にユーザーがコンポーネントから移動することを決定した場合に、返された Observable から unsubscribing して保留中の HTTP 要求をキャンセルするロジックを追加しました。

Angular 9 チュートリアルの次のステップでは、 HttpClientget() メソッドで URL クエリパラメーターを使用する方法について説明します。

ステップ12 — HttpClient get() メソッドに URL クエリパラメーターを追加する

このステップでは、サンプルアプリケーションにページネーションを実装するためのロジックの追加を開始します。 fromString および HttpParams を介して URL クエリパラメーターを使用して、ページ分割されたデータを取得するためのJSON REST APIサーバーの /products エンドポイントの _page および _limit パラメーターに適切な値を提供する方法について説明します。

src/app/data.service.ts ファイルを開き、 HttpParams の次のインポートを追加して開始します。

import { HttpClient, HttpErrorResponse, HttpParams } from "@angular/common/http";

次に、 sendGetRequest() メソッドを次のように更新します。

  public sendGetRequest(){
    // Add safe, URL encoded_page parameter 
    const options = { params: new HttpParams({fromString: "_page=1&_limit=20"}) };
    return this.httpClient.get(this.REST_API_SERVER, options).pipe(retry(3), catchError(this.handleError));
  }

HttpParamsfromString を使用して、 _page=1&_limit=20 文字列からHTTPクエリパラメーターを作成しました。 これにより、20個の products の最初のページが返されます。

これで、 sendGetRequest() を使用してデータの最初のページを取得します。 受信した HTTP 応答には、データページの最初、前、次、および最後のリンクに関する情報を含むリンクヘッダーが含まれます。

リンクヘッダーには、最初、前、次、最後のリンクが表示されます。 次のステップでは、完全な HTTP 応答を解析してこれらのページネーションリンクを抽出する方法を確認します。

ステップ13 — Angular HttpClient v9 で完全な HTTP レスポンスを取得する

このサイトでは、 JSON REST API サーバーから受信した HTTP 応答に含まれる Link ヘッダーからページネーション情報を取得するロジックを実装することから始めます。

デフォルトでは、 HttpClient は応答本文のみを提供しますが、この場合、ページネーションリンクのリンクヘッダーを解析する必要があるため、 observe オプションを使用して完全な HttpResponse が必要であることを HttpClient に伝える必要があります。

HTTPのLinkヘッダーにより、サーバーは、関心のあるクライアントを、要求されたリソースに関するメタデータを含む別のリソースに向けることができます。 Wikipedia

src/app/data.service.ts ファイルに移動し、RxJS tap() 演算子をインポートします。

import { retry, catchError, tap } from 'rxjs/operators';

次に、次の文字列変数を定義します。

  public first: string = "";
  public prev: string = "";
  public next: string = "";
  public last: string = "";

次に、 Link ヘッダーを解析し、それに応じて前の変数を設定する parseLinkHeader() メソッドを定義します。

  parseLinkHeader(header) {
    if (header.length == 0) {
      return ;
    }    let parts = header.split(',');
    var links = {};
    parts.forEach( p => {
      let section = p.split(';');
      var url = section[0].replace(/<(.*)>/, '$1').trim();
      var name = section[1].replace(/rel="(.*)"/, '$1').trim();
      links[name] = url;    });    this.first  = links["first"];
    this.last   = links["last"];
    this.prev   = links["prev"];
    this.next   = links["next"]; 
  }

次に、 sendGetRequest() を次のように更新します。

  public sendGetRequest(){
      // Add safe, URL encoded _page and _limit parameters
      return this.httpClient.get(this.REST_API_SERVER, {  params: new HttpParams({fromString: "_page=1&_limit=20"}), observe: "response"}).pipe(retry(3), catchError(this.handleError), tap(res => {
          console.log(res.headers.get('Link'));
          this.parseLinkHeader(res.headers.get('Link'));
        }));
  }

ヘッダー付きの完全な HTTP 応答を取得できるように、get() メソッドの options パラメーターに response 値を持つ observe オプションを追加しました。 次に、RxJS tap() 演算子を使用して Link ヘッダーを解析し、最後の Observable を返します。

sendGetRequest() が完全な HTTP 応答で Observable を返すようになったため、次のように src/app/home/home.component.ts ファイルを開いて HttpResponse をインポートするようにホームコンポーネントを更新する必要があります。

import { HttpResponse } from '@angular/common/http';

次に、 subscribe() メソッドを次のように更新します。

  ngOnInit() {
    this.dataService.sendGetRequest().pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<any>)=>{
      console.log(res);
      this.products = res.body;
    })  
  }

これで、受信した HTTP 応答の body オブジェクトのデータにアクセスできます。

次に、 src/app/data.service.ts ファイルに戻り、次のメソッドを追加します。

  public sendGetRequestToUrl(url: string){
    return this.httpClient.get(url, { observe: "response"}).pipe(retry(3), catchError(this.handleError), tap(res => {
      console.log(res.headers.get('Link'));
      this.parseLinkHeader(res.headers.get('Link'));
    }));
  }

このメソッドは sendGetRequest() に似ていますが、 HTTP GET リクエストを送信する必要がある URL を取得する点が異なります。

src/app/home/home.component.ts ファイルに戻り、次のメソッドを定義して追加します。

  public firstPage() {
    this.products = [];
    this.dataService.sendGetRequestToUrl(this.dataService.first).pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<any>) => {
      console.log(res);
      this.products = res.body;
    })
  }
  public previousPage() {    if (this.dataService.prev !== undefined && this.dataService.prev !== '') {
      this.products = [];
      this.dataService.sendGetRequestToUrl(this.dataService.prev).pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<any>) => {
        console.log(res);
        this.products = res.body;
      })
    }
  }
  public nextPage() {
    if (this.dataService.next !== undefined && this.dataService.next !== '') {
      this.products = [];
      this.dataService.sendGetRequestToUrl(this.dataService.next).pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<any>) => {
        console.log(res);
        this.products = res.body;
      })
    }
  }
  public lastPage() {
    this.products = [];
    this.dataService.sendGetRequestToUrl(this.dataService.last).pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<any>) => {
      console.log(res);
      this.products = res.body;
    })
  }  

最後に、 src/app/home/home.component.html ファイルを開いて追加し、次のようにテンプレートを更新します。

<div style="padding: 13px;">
  <mat-spinner *ngIf="products.length === 0"></mat-spinner>
    <mat-card *ngFor="let product of products" style="margin-top:10px;">
    <mat-card-header>
      <mat-card-title>#{{product.id}} {{product.name}}</mat-card-title>
      <mat-card-subtitle>{{product.price}} $/ {{product.quantity}}
      </mat-card-subtitle>
    </mat-card-header>
    <mat-card-content>
      <p>
        {{product.description}}
      </p>
      <img style="height:100%; width: 100%;" src="{{ product.imageUrl }}" />
    </mat-card-content>
    <mat-card-actions>
      <button mat-button> Buy product</button>
    </mat-card-actions>
  </mat-card>
</div>
<div>
  <button (click) ="firstPage()" mat-button> First</button>
  <button (click) ="previousPage()" mat-button> Previous</button>
  <button (click) ="nextPage()" mat-button> Next</button>
  <button (click) ="lastPage()" mat-button> Last</button>
</div>

これは、アプリケーションのスクリーンショットです。

ステップ14 — Angular HttpClient v9 で型指定された HTTP 応答を要求する

この手順では、サンプルアプリケーションで型指定された HTTP 応答を使用する方法について説明します。

Angular HttpClient を使用すると、要求オブジェクトで応答オブジェクトのタイプを指定できるため、応答を簡単かつ簡単に使用できます。 これにより、コンパイル時に型アサーションも有効になります。

まず、必要なプロパティを備えた TypeScript インターフェースを使用してカスタムタイプを定義します。

コマンドラインインターフェイスに戻り、プロジェクトのルートから次のコマンドを実行します。

$ ng generate interface  product

次に、 src/app/product.ts ファイルを開き、次のように更新します。

export interface Product {
  id: number;
  name: string;
  description: string;
  price: number;
  quantity: number;
  imageUrl: string;
}

次に、データサービスで HttpClient.get() 呼び出しの type パラメーターとして Product インターフェースを指定します。 src/app/data.service.ts ファイルに戻って、 Product インターフェースをインポートします。

import { Product } from './product';

次:

  public sendGetRequest() {
    return this.httpClient.get<Product[]>(this.REST_API_SERVER, { params: new HttpParams({fromString: "_page=1&_limit=20"}), observe: "response"}).pipe(retry(3), catchError(this.handleError), tap(res => {
      console.log(res.headers.get('Link'));
      this.parseLinkHeader(res.headers.get('Link'));
    }));
  }

  public sendGetRequestToUrl(url: string) {
    return this.httpClient.get<Product[]>(url, { observe: "response"}).pipe(retry(3), catchError(this.handleError), tap(res => {
      console.log(res.headers.get('Link'));
      this.parseLinkHeader(res.headers.get('Link'));
    }));
  }  

次に、 src/app/home/home.component.ts ファイルを開き、 Product インターフェイスをインポートします。

次に、 Product 配列のタイプを次のように変更します。

export class HomeComponent implements OnInit, OnDestroy {
  products: Product[] = [];

次に、 sendGetRequest() 呼び出しで HTTP 応答のタイプを変更します。

  ngOnInit() {
    this.dataService.sendGetRequest().pipe(takeUntil(this.destroy$)).subscribe((res: HttpResponse<Product[]>) => {
      console.log(res);
      this.products = res.body;
    })
  }

他の firstPage()previousPage()nextPage()lastPage() メソッドについても同じことを行う必要があります。

ステップ15 — Angular 9 アプリケーションを Firebase Hosting にビルドおよびデプロイする

このステップでは、 Angular 8.3+ で利用可能な ng deploy コマンドを使用して、サンプルアプリケーションをビルドして Firebase ホスティングにデプロイする方法を見ていきます。

疑似の JSON サーバーなしでフロントエンドアプリケーションをデプロイする方法のみを見ていきます。

Angular CLI 8.3+ では、プロジェクトに関連付けられた deploy CLI ビルダーを使用して、 Angular アプリケーションを以前より簡単にデプロイできる新しい ng deploy コマンドが導入されました。 さまざまなプラットフォームに展開機能を実装するサードパーティビルダーが多数あります。 ng add コマンドを実行して、プロジェクトにそれらを追加できます。

展開パッケージを追加すると、選択したプロジェクトの展開セクションでワークスペース構成(つまり、 angular.json ファイル)が自動的に更新されます。 その後、 ng deploy コマンドを使用して、そのプロジェクトをデプロイできます。

プロジェクトを Firebase ホスティングに展開することで、例を見てみましょう。

コマンドラインインターフェイスに戻り、 Angular プロジェクトのルートフォルダー内にいることを確認して、次のコマンドを実行します。

$ ng add @angular/fire

これにより、 Firebase 展開機能がプロジェクトに追加されます。

このコマンドは、次のセクションを追加して、プロジェクトの package.json も更新します。

  "deploy": {
    "builder": "@angular/fire:deploy",
    "options": {}
  }

CLI は、ここに認証コードを貼り付けるように求めます。デフォルトの Web ブラウザーを開き、 Firebase アカウントを管理するための Firebase CLI 権限を付与するように求めます。

Firebase アカウントに関連付けられた Google アカウントでサインインすると、認証コードが付与されます:

次に、プロンプトが表示されます:プロジェクトを選択してください:(矢印キーまたはタイプを使用して検索します)。 前に Firebase プロジェクトを作成しておく必要があります。

CLIfirebase.json および .firebaserc ファイルを作成し、それに応じて angle.json ファイルを更新します。

次に、次のコマンドを使用して、アプリケーションを Firebase にデプロイします。

$ ng deploy

このコマンドは、アプリケーションの最適化されたビルド( ng deploy --prod コマンドと同等)を生成し、実稼働アセットを Firebase ホスティングにアップロードします。

まとめ

この Angular 9 チュートリアルを通して、最新バージョンを使用した完全な Angular アプリケーションの実例を作成しました。

要約すると、 HttpClient を設定し、 HttpClient.get() メソッドを使用してパラメーターを指定して HTTP GET リクエストを送信する方法、 RxJS throwError() および catchError() 演算子を使用して HTTP エラーを処理する方法、 takeUntil() 演算子を使用してキャンセルされた HTTP リクエストの RxJS Observables から、 retry() 演算子で失敗したリクエストを再試行し、最後に Angular 8.3+ から利用可能な最新の ng deploy 機能を使用してアプリケーションを Firebase ホスティングにデプロイする方法

著者について

Ahmed Bouchefra は、5年以上の経験を持つ Web 開発者であり、ソフトウェア開発の工学学位を持つ技術著者です。 上記のリンクをクリックして彼を雇うか、LinkedIn アカウントから彼に連絡することができます。 彼は、SitePoint、Smashing、DigitalOcean、RealPython、freeCodeCamp、JScrambler、Pusher、Auth0などの業界をリードするWebサイトの技術コンテンツを作成しました。 彼はまた、 AmazonLeanpub から入手できる最新の Web 開発に関するさまざまな本を共著しています。

当初、2019年12月5日に https://www.techiediaries.com で公開されました。

itnext.io

itnext.io

Use Angular Route-Guards to Secure Angular Pages — By allow, deny or redirect to other page-view. の翻訳

mediumUse Angular Route-Guards to Secure Angular Pages — By allow, deny or redirect to other page-view. の翻訳です。

ルートガードを使用してAngularページを保護するのは非常に簡単です。

f:id:ic_lifewood:20200103214717p:plain

ルートガードは、ユーザーがログインしているかどうかに基づいて、何らかのロジックに基づいてルートページへのユーザーアクセスを許可または拒否する、Angular Routerの重要な機能です。

  • ログイン/ログアウトのシナリオがあるアプリケーションでは、ルートガードは非常に重要です。
  • 通常、ユーザーがログインしていて、ページにアクセスする権限があるかどうかを確認するために使用されます。
  • ログインしているユーザーとログインしていないユーザーに許可するページを簡単に管理できます。

ルートガードの実装

@angular/router パッケージから利用可能な CanActivate インターフェースを実装することでルートガードを追加し、ルートへのアクセスを許可または拒否するロジックを保持する canActivate() メソッドを拡張します。

たとえば、次のガードは userLoggedIn の値をチェックし、それに応じてルートへのアクセスを許可します。 ( コードについては心配しないでください-すべてを詳細に理解します。

class AuthGuardService implements CanActivate {
  userLoggedIn = false;canActivate() {
    if (this.userLoggedIn) {
     return true;
    } else {
     return false;
    }
  }
}

canActivate 属性を使用して、ガードでルートを保護できるようになりました。

const routes: Routes = [
  {
    path: 'user/:id', 
    component: UserDetailComponent,
    canActivate:[AuthGuardService] 
  }
];

上記のコードは、「 Angular コンポーネントのルーティング」に関するものです。ここをクリック👆して、 Angular-Routing の詳細をご覧ください。

「ルートガード」をアプリの認証領域、またはアクセスするために特別な権限を必要とする管理セクションに適用できます。 次のコードサンプルでは、ルートガードの非常に単純な実装を確認します。

ガードを作成する

最初にサービスを作成しますが、Guardを作成するには、 canActivate を実装する必要があります。 ターミナル/コマンドプロンプトで次のコマンドを実行して AuthGuardService を作成しましょう。

$ ng g s service/AuthGuard

このコマンドは2つの TypeScript ファイルを生成します—以下をご覧ください👇

f:id:ic_lifewood:20200103220914p:plain

#1 AuthGuardServiceを作成する

次に、src/app/service/auth-guard.service.ts ファイルを開き、次のように更新します(このコードで AuthService をインポートして使用しました👇👇 AuthService の詳細についてはここをクリックしてください👆)

gist.github.com

#2 AuthGuardServiceを登録する

これで、この AuthGuardService を Angular ルート定義に登録できます。 src/app/app-routing.module.ts ファイルを開き、次のように更新します: (「 path 」と「 component 」の値を適宜変更してください)

gist.github.com

注:クライアント側ではセキュリティは意味がありません。 むしろ、ルートガード(またはその他のメカニズム)を使用するのは、ユーザーが入ることが許可されていないエリアに入らないようにするため、すべてUX機能です。 ただし、最終的なセキュリティチェックは常にサーバー側で行う必要があります。

ブロックは不十分です。

true または false を返すだけでは、実際には十分ではありません。 何が起こったのか、なぜ彼らがページに入ることを許可されなかったのかをユーザーに伝える必要があります。 通知を表示するか、ほとんどの場合、他のページビューにリダイレクトします。

これを行うには、ルーターAuthGuard に挿入し、他のページビューにリダイレクトします。 こちらをご覧ください:👇👇

#3 AuthGuardService の変更

gist.github.com

(「 Observable タイプ」と「 Angular でサブスクリプションを管理する」の詳細-ここをクリック👆)

このガードをルートにアタッチすると、 canActivate() メソッドは、ルートがアクティブになる前、つまり実際の パス を開く前、または実際の コンポーネント をロードする前に起動します。

const routes: Routes = [
  {
    path: 'user/:id', 
    component: UserDetailComponent,
    canActivate:[AuthGuardService] 
  }
];
  • ロジックはまずユーザーが有効かどうかを確認し、有効でない場合はログインルートに移動します。
  • また、現在のURLを取得し、クエリパラメーターとして設定するため、/login?return=%2Fusers%2Fabc123 のようになります(URLはエンコードされます)。 これは、 /users/abc123 のようにユーザーにアクセスしようとしている場合で、 canActivate が不正ユーザーを検出します。

まとめ

1) AuthGuardServiceを作成する 2) AuthGuardServiceを登録する 3) AuthGuardService の変更

できた🤩! routeルートガードを使用してページを保護するのは簡単です。 またね👋👋

コメントボックスにコメントしてください。何かを見逃した場合や何かが間違っている場合、または何かが機能しない場合は:)

より多くの記事のために接続を維持: https://medium.com/@AnkitMaheshwariIn

助かったので拍手👏 👏 してもかまいませんが、 他の人が記事を見つけられるように助けてください。

f:id:ic_lifewood:20200103224145g:plain

いつも拍手して…

2019年12月28日に https://www.codewithchintan.com で公開されました。

medium.com

medium.com

Integrating Google APIs with Angular の翻訳

Angular In DepthIntegrating Google APIs with Angular の翻訳です。

f:id:ic_lifewood:20200103001443p:plain

💡動機

タスク:プライベート Google カレンダーのイベントにアクセス/表示する必要があります。
問題:プライベートカレンダーを iframe に入れたり、 API キーだけを使用してそのイベントをクエリしたりすることはできません。 要件:Angularと互換性があり、 TypeScript サポート(サービスラッパー/クラスおよびデータモデルタイプ)
解決策:必要なものすべてを提供する google-api-nodejs-client があります

Google APIにアクセスするためにGoogleが公式にサポートしているNode.jsクライアントライブラリ。 OAuth 2.0、APIキー、およびJWTによる承認と認証のサポートが含まれています。

次に Node.js パーツを Angular に置き換える方法を見つけます。

🛠️統合

残念ながら、このライブラリは NodeJS 用であり、"Webpackビルドアプリ" に統合する際にわずかな問題があり、ブラウザには NodeJS の一部に依存するため、 Angular が含まれます。 回避策があります(ここで説明します)ので、私たちを止めることはできません。

まず、 Webpack ビルドを拡張する必要があります。

$ npm i -D @angular-builders/custom-webpack

次に、 angular.json プロジェクトアーキテクト構成ファイルのビルダーを置き換える必要があります。また、オプションにカスタム Webpack 構成へのパスを含めます。

"architect": {
  "build": {
    "builder": "@angular-builders/custom-webpack:browser",
    "options": {
      "customWebpackConfig": {
        "path": "./extra-webpack.config.js"
      },
      ...
    },
    ...
  },
  "serve": {
    "builder": "@angular-builders/custom-webpack:dev-server",
    ...
  },
}

説明は、 Angular のビルダードキュメントにあります。

🔨“ハック”

さて、実際の「ハック」とは何ですか? この NodeJS ライブラリに必要なこれらすべてのことをブラウザーに存在するように振る舞います。

  1. グローバルやバッファーなどの NodeJS ランタイム内部の一部をシミュレートします。
  2. ランタイム fschild_processhttps-proxy-agent などいくつかライブラリのモックが必要です。

global および Buffer のフォールバックを提供する

src/polyfills.ts のアプリケーションインポートの下に次のポリフィルを追加します。

import * as process from 'process';
(window as any).process = process;

import { Buffer } from 'buffer';
(window as any).Buffer = Buffer;

パッケージ npm i -D process buffer インストールすることを忘れないでください。

これを index.html <head> タグに追加します。 global にアクセスすることに関連するエラーは、 window で置き換えられるため、削除されます。

<script>
  if (global === undefined) {
    var global = window;
  }
</script>

ライブラリのモック

const path = require('path');module.exports = {
  resolve: {
    extensions: ['.js'],
    alias: {
      fs: path.resolve(__dirname, 'src/mocks/fs.mock.js'),
      child_process: path.resolve(
        __dirname,
        'src/mocks/child_process.mock.js'
      ),
      'https-proxy-agent': path.resolve(
        __dirname,
        'src/mocks/https-proxy-agent.mock.js',
      ),
    },
  },
};

何が起こっているのかという説明は、あるインポート(ファイル)を別のインポート(ファイル)に置き換えるようWebPackに指示しているということです。
すべての “mock” ファイルを src/mock に配置しているので、プロジェクトで作業している同僚にとってこれらのファイルが何であるかを簡単に理解できます。

これらのモック内のコードはかなり単純です。 使用されるが必須ではないメソッドをいくつか追加するまで、何も「実行」しません。
fschild_process は両方ともこのようになります。

module.exports = {
  readFileSync() {},
  readFile() {},
};

https-proxy-agent はさらに単純で、 module.exports = {}; のみです。

🔑アクセスの設定

  1. 新しい GCP プロジェクトを作成するか、既存の GCP プロジェクトを使用します。
  2. GCP コンソールでプロジェクトを選択し、[ライブラリ]タブに移動して、使用するAPIを有効にします(この場合は Google カレンダーと分析)
  3. OAuth 同意画面のカスタマイズ(名前、制限など)
    • 必要な Scopes for Google APIs を設定します(カレンダー、分析など)
  4. OAuth 認証情報を作成する
    • プライベートデータ(カレンダーイベントや分析など)にアクセスする場合に必要
  5. 認証に進み、公開および秘密の OAuth キーを使用します

🔓認証

API キーを使用すると、 API から簡単に多くの公開データにアクセスできます。 パブリックカレンダーのようなものですが、プライベートデータ(プライベートカレンダーなど)が必要な場合は、認証する必要があります。 これは、 OAuth クライアントを介して実行できます。

app.module.ts 内のプロバイダー配列で GoogleOAuth2Client を提供します。 次のようになります。

{
  provide: OAuth2Client,
  useValue: new OAuth2Client( // You get this in GCP project credentials
    environment.G_API_CLIENT_ID,
    environment.G_API_CLIENT_SECRET, // URL where you'll handle succesful authentication
    environment.G_API_REDIRECT,),
},

リダイレクトベースの認証を使用するため、次は認証 URL を生成します。

window.location.href = this.oauth2Client.generateAuthUrl({

  // 'offline' also gets refresh_token  
  access_type: 'offline',// put any scopes you need there, 

  scope: [
    // in the first example we want to read calendar events
    'https://www.googleapis.com/auth/calendar.events.readonly',
    'https://www.googleapis.com/auth/calendar.readonly',

    // in the second example we read analytics data
    'https://www.googleapis.com/auth/analytics.readonly',
  ],
});

refresh_token のおかげで、OAuthClient はトークンの有効期限が切れた後でもトークン交換を処理できるようになるため、トークンの有効期限が切れてから1時間ごとに Google の認証画面を表示する必要がなくなります。

️⌨️使用例

ドキュメントを探索したい場合は、google-apis docs にアクセスするか、以下の例で使用されているカレンダーをご覧ください。

📅Calendar Service SDKの使用

Permissions

使用しているアカウントが、イベントを読み取りたいカレンダーにアクセスできることを確認してください。

コードサンプル

Calendar クラスにデフォルトの認証メソッドを提供します。この場合は OAuth です。
これで app.module.ts 内のプロバイダー配列を拡張します。

{
  provide: calendar_v3.Calendar,
  useFactory: 
    (auth: OAuth2Client) => new calendar_v3.Calendar({ auth }),
  deps: [OAuth2Client],
},

これで、完全に型指定された SDK インターフェイスを使用して、 Google カレンダー API 機能の完全なセットにアクセスできます。
他の Angular サービスと同じようにカレンダーを取得し、コンストラクターパラメーターとして使用すると、依存関係の注入によってカレンダーが提供されます。

constructor(
  private calendar: calendar_v3.Calendar,
) {}

特定のカレンダーのイベントのリストを取得する方法の例を次に示します。
また、「今日」で削除/キャンセルされていないイベントのみをフィルタリングします。

this.calendar.events.list({
  // required, it is an email, or email like id of a calendar
  calendarId: CALENDAR_ID,

// optional, arguments that let you filter/specify wanted events
  timeMin: startOfDay(today).toISOString(),
  timeMax: endOfDay(today).toISOString(),
  showDeleted: false,
  singleEvents: true,
}),

イベントの作成などの他のタスクを実行することもできますが、認証で適切な範囲の要求を忘れないでください。

📊Analytics SDKの使用

permissions の設定

⮕ Analytics Console ⮕ Admin ⮕ Account column ⮕ User Management ⮕
⮕ Select the user ⮕ Activate the "Read & Analyze" checkbox

"View ID" の取得

⮕ Analytics Console ⮕ Admin ⮕ View column ⮕ View Settings ⮕
⮕ Copy the "View ID" number

コードサンプル

前の例と同じように、プロバイダーが必要です。Analytics クラスにデフォルトの認証方法を提供します。 app.module.ts 内のプロバイダー配列を拡張します。

{
  provide: analytics_v3.Analytics,
  useFactory:
    (auth: OAuth2Client) => new analytics_v3.Analytics({ auth }),
  deps: [OAuth2Client],
},

繰り返しますが、 DI によって任意の注入可能クラスに注入する準備ができています。

constructor(
  private analytics: analytics_v3.Analytics,
) {}

この例では、目的の時間範囲の指定されたメトリックを取得します。 この場合、過去30日間の合計ページビューが表示されます。

this.analytics.data.ga.get({
  ids: 'ga:xxxxxxxxx', // replace xxxxxxxxx with your view ID
  'start-date': '30daysAgo',
  'end-date': 'today',
  metrics: 'ga:pageviews',
})

📋まとめ

API の完全に型指定された SDK を持つことは、ドキュメント、特にデータモデルですべてを見つける必要があることと比較して大きな違いです。 問題の Auth の部分も非常に便利に処理されるため、その方法がわからない、またはそれを管理したくない人のためのショーストッパーではありません。 全体として、プロジェクト環境とツールを適切に設定すると、機能を作成するのがはるかに簡単になります。

・・・・・・

詳細や更新情報については、こちらまたは Twitter でフォローしてください。 質問がある場合は、お気軽にご連絡ください。

medium.com

How to Create a Service with HttpClient and Injectable in Angular 9/8 の翻訳

mediumHow to Create a Service with HttpClient and Injectable in Angular 9/8 の翻訳です。

このチュートリアルでは、 HttpClient を使用して、 Angular アプリケーションを REST API サーバーに接続するためのサービスを構築する方法を学習します。

Angular サービスを実装して、REST API サーバーからのデータの取得を処理するコードをカプセル化する方法について説明します。

f:id:ic_lifewood:20200102001855p:plain

Angular サービスは、Angular 依存関係インジェクターを使用して他のサービスまたはコンポーネントに挿入できる単なる TypeScript クラスです。

前提条件

Node 、NPM 、Angular CLI が必要で、Angularプロジェクトを初期化する必要があります。

ステップ1 — HttpClient モジュールのインポート

src/app/app.module.ts ファイルを開き、次のように更新します。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

ステップ2 — Angular Service の作成

新しいターミナルを開き、次のコマンドを実行します。

$ ng generate service backend

ステップ3 — HttpClient のインポートと注入

src/app/backend.service.ts ファイルを開き、次のように HttpClient をインポートして注入します。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class BackendService {
  constructor(private httpClient: HttpClient) { }
}

HttpClient をインポートし、サービスの constructor を介して注入します。

ステップ4 — HTTPリクエストを送信するメソッドの定義

次に、データを取得するためにサーバーにGETリクエストを送信する get() メソッドを定義します。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class BackendService {

  constructor(private httpClient: HttpClient) { }

  public get(){
    return this.httpClient.get("http://server.com/endpoint");
  }
}

HttpClientget() メソッドを呼び出して、GET 要求を REST API サーバーに送信します。

ステップ5 — Angular コンポーネントの作成

端末に戻り、次のコマンドを実行してhomeという名前のコンポーネントを生成します。

$ ng generate component home

ステップ6 — Angular Service の注入

src/app/home/home.component.ts ファイルに移動し、次のようにバックエンドサービスをインポートして注入します。

import { Component, OnInit } from '@angular/core';
import { BackendService } from '../backend.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  data= [];

  constructor(private backendService: BackendService) { }

}

ステップ7 — サービスメソッドの呼び出し

最後に、次のように、サービスの get() メソッドを呼び出して GET リクエストを送信できます。

  ngOnInit() {
    this.backendService.get().subscribe((ret: any[])=>{
      console.log(ret);
      this.data = ret;
    })  
  }

ステップ8 — ngFor を使用したデータの表示

<div>
  <ul>
    <li *ngFor="let item of data">
      {{item.name}}
    </li>
  </ul>
</div>

ここでは、データ要素に名前属性があると仮定します。

他の Angular チュートリアル をご覧ください。

個人の Web サイトである TwitterLinkedIn 、および Github を介して著者に連絡するか、著者をフォローできます。

まとめ

この投稿では、 Angular でサービスを作成し、 HttpClient を使用して HTTP リクエストを REST API バックエンドに送信し、 ngFor ディレクティブを使用して API から返されたデータを最終的に表示する方法を説明しました。

itnext.io

itnext.io