[Angular] build時のError: initial exceeded maximum budget の解消方法

Angular 11 buid error: Index html generation failed.Inlining of fonts failed. An error has occurred while retrieving https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap over the internet.

  • Angular 11で有効化されたフォント最適化機能について
  • プロキシ環境下で開発をしている場合、ng buildでプロキシエラーが発生してしまう

発生した事象

  • Anular11 へのアップデート後に、ng buildで以下のエラーが発生する
    1
    2
    3
    4
    5
    6
    7
    > ng build --prod
    √ Browser application bundle generation complete.
    √ ES5 bundle generation complete.
    √ Copying assets complete.
    × Index html generation failed.
    Inlining of fonts failed. An error has occurred while retrieving https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap over the internet.
    connect ETIMEDOUT

原因

  • Angular 11からインラインフォントへの新機能が追加されている
  • プロキシ環境下で開発を行っている場合は、build時にプロキシを通過できずエラーが発生してしまう
    • 正しくHTTP_PROXY/http_proxyの環境変数を設定していても無視されてしまう

回避策

  • 幾つかGitのissueに同様の事象が挙がっていたが、以下が結論であった

    1
    ビルドサーバーはファイアウォールの外にはアクセスできません。それをオフにするのが唯一の選択肢だと思います。
  • font optimizationをオフにする方法

要約

  • 設定ファイル(angular-pj/angular.json)でbuildの設定を変更することで解決可能

  • デフォルトの設定

    • “optimization”: trueとなっている
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      "projects": {
      "app_name": {
      ...
      "architect": {
      "build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
      ...
      },
      "configurations": {
      "production": {
      "fileReplacements": [
      {
      "replace": "src/environments/environment.ts",
      "with": "src/environments/environment.prod.ts"
      }
      ],
      "optimization": true,
  • angular.jsonの各項目について

    • “architect”
      • コンパイルやテスト実行などの複雑なタスクを実行するためにCLIが使用するツール
      • ターゲットの設定に従って、指定されたタスクを実行するために指定されたビルダーを実行するシェル
    • “build”
    • “configurration”
      • このセクションでは、異なる目的地のための代替構成を定義し、名前を付ける。このセクションには、それぞれの設定のためのセクションがあり、その環境でのデフォルトのオプションを設定する。
    • “optimization”
      • より細かい設定を行うために、ブール値かオブジェクトのいずれかを指定できる。このオプションを使用すると、ビルド出力のさまざまな最適化が可能になる
      • fonts
        1
        2
        フォントの最適化を有効にします。
        注意: これにはインターネットへのアクセスが必要です
      • fonts optimsization options
        • inline
          1
          2
          アプリケーションの HTML インデックス ファイル内の外部の Google フォントとアイコンの CSS 定義をインライン化することで、レンダリング ブロック要求を減らします。
          注意:これにはインターネットへのアクセスが必要です。
  • 以下に変更

    1
    2
    3
    "optimization": { 
    "fonts": true
    }
  • 以上でbuildが問題なく実行できた

    1
    2
    3
    4
    5
    > ng build --prod
    √ Browser application bundle generation complete.
    √ ES5 bundle generation complete.
    √ Copying assets complete.
    √ Index html generation complete.

同様の事象はgitのissueで複数確認できたが、無効化する以外の解決策は見つけられなかった。

参考

関連記事

その他

[Angular] ng build時のエラー --aotについて

  • Angular 9以降でデフォルト化されたAOTについてのメモ
    • 8以前のバージョンからアップデートした際に注意すべきポイント

発生する事象

  • Angularのバージョンアップ後、build実行時にエラーが発生する
    • –aot オプションが必要になる
      1
      ng build --aot

原因/AOT

  • Angular9 以降ではahead-of-time (AOT)コンパイラがデフォルトに採用されている

  • Ahead-of-time (AOT) コンパイラ

    • 引用
      1
      2
      3
      Angular の ahead-of-time (AOT) コンパイラ は、ブラウザがそのコードをダウンロードして実行する前に、
      ビルドフェーズ中にAngular HTML コードと TypeScript コードを効率的な JavaScript コードに変換します。
      ビルドプロセス中にアプリケーションをコンパイルすると、ブラウザでのレンダリングが速くなります。
  • Angularには、アプリケーションをコンパイルする2つの方法がある

    • Just-in-Time (JIT)
      • 実行時にブラウザ内でアプリケーションをコンパイルします。This was the default until Angular 8.
    • Ahead-of-Time (AOT)
      • ビルド時にアプリとライブラリをコンパイルします。This is the default since Angular 9.
  • ng build (build only)またはng serve (build and serve locally)のCLIコマンドを実行すると、
    コンパイルの種類(JITかAOTか)は、angular.jsonで指定したビルド設定のaotプロパティの値に依存する

    • Angular 8以前で開始した場合はデフォルトでtrueではない

これらの要因により今回のエラーが発生したと思われる

aotの有効化

  • 設定を変更することで、buildの度にオプション(–aot)を付与せずともエラーを回避可能になる

  • 以下の設定ファイルでbuildの設定を変更することで解決できる

    • aotをtrueとするだけ
  • angular-pj/angular.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
    "outputPath": "dist/reacq-pj",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "tsconfig.app.json",
    "aot": true, //こちらを変更

参考

関連記事

その他

[Angular] An unhandled exception occurred: Port 4200 is already in use の解決策

ng serve実行時のエラーについてのメモ

Error

  • 以下のエラーが出る
    1
    2
    > ng serve
    An unhandled exception occurred: Port 4200 is already in use. Use '--port' to specify a different port.

解決策

Port 4200のプロセスをkillする

  • ポートが:4200と表示されているプロセスを探す
    1
    2
    3
    > netstat -a -n -o
    プロトコル ローカル アドレス 外部アドレス 状態 PID
    TCP 127.0.0.1:62279 127.0.0.1:4200 ESTABLISHED 18492
  • pidを指定してプロセスをkill
    1
    2
    > taskkill -f /pid 8464
    成功: PID 18492 のプロセスは強制終了されました。
  • 以上でserve 可能になる
    1
    > ng serve

参考

関連記事

その他

[Angular x AWS SDK for JavaScript] SPAからAWSのデータを取得する際の待ち合わせ処理(非同期処理)

  • SPAのプラットフォームにAWSを採用した際によく書くロジックについてのメモ

    • ex. クライアントからs3 bucketのobjectを取得して画面に表示
  • AWS SDKでデータを取得するまではディベロッパーガイドを見れば容易だが、待ち合わせ処理の書き方が少し面倒

前提知識


実装例

AWS SDK for JavaScript

  • 想定する状況

    • Angularのコンポーネント生成時(画面遷移時)に自動でAWS(S3)から情報を取得して画面に表示する
  • AWSからデータを取得して値を取り出すまでを待ち合わせ処理にする例

    1. ComponentからServiceのロジックを呼び出す
    2. Service内でAWSからデータを取得
      • 変数 = new Promise() の形式で、AWSへ問い合わせるロジックを書く
        • resolve(data)で変数に返り値を格納
      • 各関数間の待ち合わせ処理は async/await で実現する
    3. Promise型の返り値をComponentへ返す
    4. Component側で forkJoin().subscribe を使って受け取る
      .then()で受け取ってもOK (Angularでは基本subscribeが推奨されている)

書き方は他にもあるかも

AWS SDKを導入するまで

sampleの構成

  • request.service.ts

    • AWSとの通信用のService
  • sample.component.ts

    • Serviceを呼び出し、返り値を受け取るComponent
  • sample.component.html

    • 取得したデータを表示する

AWSへリクエストするService

以下の様に書かないと、データが帰ってくる前にcomponentにundefinedを返してしまう

  • AWSへのリクエストからの待ち合わせで返り値を取り出す方法

    • Promiseの中でリクエストする
    • GETしたデータをresolve()で返す
    • resolveで返された値をreturn
  • async/await でService内の各関数間の待ち合わせ処理を実現する

  • Service記載例 (request.service.ts)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    import { Injectable } from '@angular/core';

    // aws-sdkを変数AWSとしてimportする必要がある
    import * as AWS from 'aws-sdk'

    @Injectable({
    providedIn: 'root'
    })

    export class requestService {
    constructor() { }

    // 1. Componentから呼び出される関数
    async getAwsData() {
    return await this.requestData();
    }

    // 2. AWSに対してリクエストする関数
    async requestData() {

    // 変数requestに返り値を格納 待ち合わせのためにPromiseを用いる
    const request = new Promise((resolve, reject) => {

    // AWS SDKサービスのオブジェクトを宣言
    let bucket = new AWS.S3(({params: {Bucket: 'myBucket'}});

    // リクエストを実行 基本的に以下の様にdataに返り値が入る
    bucket.listObject(({}, (err, data ) => {
    if (err) {
    let errorMessage = String(err);
    alert(errorMessage);
    }
    else {
    // resolveでPromiseの処理を終了させる
    resolve(data); // データ加工が必要であれば、ここで関数を呼び出す
    }
    });
    });

    // エラーハンドリング
    request.catch((error) => {alert(error); } );
    // リクエスト結果を返す
    return request;
    }

    }
  • s3のデータの扱い方についてはディベロッパーガイドを参照。ここではあくまで共通した待ち合わせ処理の記法のみ


データを受け取るComponent側

  • Component側の受け取り方は2パターンある

    1. .then()
    2. .subscribe()
  • Component側の実装例(sample.component.ts)

    • serviceを呼び、データを受け取る
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//rxjs 待ち合わせ処理に必要
import { forkJoin } from 'rxjs';

let awsData; //データ受取用の変数を宣言

// 起動時に取得 → ngOnInitから呼び出す
ngOnInit() {
getData();
}

getData() {

// Credential認証 Service側でもいいかも
AWS.config.credentials = new AWS.Credentials("<access key>","<secret key>")

// thenで受け取る例
this.requestService.getAwsData().then(response =>{
console.log(response);
this.awsData = response; // 取得データを代入
});

// subscribeで受け取る例 Promise型のため、forkJoinが必要
forkJoin(this.grequestService.getAwsData()).subscribe(result => {
this.awsData = result[0]; // 取得データを代入
});
}
  • sample.compoent.html 取得したデータを画面に表示
    1
    {{getAwsData}}

参考

関連記事

その他

@EventEmitter @Input @Output @ViewChild ACM AMP API Gateway AR AR.js AR.js Studio AWS AWS Amplify AWS Budgets AWS Cost Explorer AWS SDK for JavaScript AddThis Adobe XD Alexa Amazon CloudWatch Amazon Honycode Amazon SNS Android Angular Angular Material AngularFire AppSync Augury C CDN CI/CD Cloud Craft Cloud9 CloudFormation CloudFront CloudTrail Cognito Cost Anomaly Detection Cubase ai Cubasis LE DTM Disqus DynamoDB Elgato HD 60S Firebase Firebase Hosting Former2 Github Github Actions Github.com GithubEnterprise GithubPages Google Chrome Google Cloud Shell GraphQL Hexo Hosting IAM Ionic JSON JavaScript LadioCast Logging LowCode MFA MS Authentication MacBook Pro 16 Mind Node NETDUETTO Netflix Party Netlify Network NoCode Observable PO PdM Promise RPA ReactiveForm Recognition Route53 S3 SAM(Serverless Application Model) SAR SSL SYNCROOM Schematics ScrumInc Serverless Service Siri Sitemap Spark AR Steinberg UR44C Teams Touch Cast Studio Treetable TypeScript UI UI Bakery WAF WAFv2 WEB Page Dev WEB会議 WebAR WebSocketAPI Webhook Windows Power Automate Wireshark aot async/await aws config cloud9 display.land draw.io e2e test filter() forkJoin() google search console hexo-generator-amp iOS iPad Pro iPhone icarus map() mat input mat tree mat-checkbox mat-input mat-selection-list mmhmm ngFor plantUML popIn Aladdin2 then() vscode ”global is not defined” らくがきAR アジャイル アジャイル開発 クロスプラットフォーム ショートカット スクラム スクラム開発 テレワーク ファイル操作 ブラウザ型IDE プロダクトオーナー プロダクトマネージャー プロトタイピング リモートセッション 共同開発 双方向データバインディング 待ち合わせ処理 認定スクラムマスター 静的WEB Hosting 静的WEBサイトHosting
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×