LoginSignup
10
8

More than 5 years have passed since last update.

Angular7でwebpack configを調整してバンドルサイズや挙動を自在に操る(ag-Grid入門付き!)

Last updated at Posted at 2019-02-07

lovedと申します。
Qiitaコントリビューターの皆様、いつも大変ありがとうございます。

TL;DR

Angular7では、Angular6で使用できたng ejectコマンドが廃止されました。
そこで今回はAngular7でAngular-CLI開発をする時のwebpack詳細設定の仕方を紹介します。
angular.jsonを編集した上で、webpack拡張設定ファイルを作成してビルドする方法です。

対象読者

・Angular7でデフォルトのビルド設定でカバーできない要件があり、
Angularの内部で動いているwebpack部分のconfigを調整する必要がある方。
・前準備でAngular7環境での初期構築を行っていますので、Angular7(とag-Grid)をこれから使用する/学ぶ予定がある方にもお楽しみいただけるかと思います。

環境


 >> ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 7.3.0
Node: 9.3.0
OS: win32 x64
Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.13.0
@angular-devkit/core         7.3.0
@angular-devkit/schematics   7.3.0
@schematics/angular          7.3.0
@schematics/update           0.13.0
rxjs                         6.3.3
typescript                   3.2.2


・・・Nodeのバージョンが古いですが、気にしないでください。

今回はag-gridのチュートリアルを借りつつ手順を紹介します。
ag-gridはコミュニティエディション無料のgridモジュールです。
https://www.ag-grid.com/angular-getting-started/

手順

ではやっていきましょう。
前準備は上述チュートリアルページとほぼ同一です。
理解度の高い方は飛ばして頂いて問題ありません。

前準備



// インストールとプロジェクトの作成
npm install -g @angular/cli
ng new my-app --style scss --routing false
cd my-app
// ag-gridのインストール
npm install --save ag-grid-community ag-grid-angular

// プロジェクト内 app.module.tsを編集
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { AgGridModule } from 'ag-grid-angular';// ←追加

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AgGridModule.withComponents([])],// ←追加
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

// styles.scssを編集
@import "~ag-grid-community/dist/styles/ag-grid.css";
@import "~ag-grid-community/dist/styles/ag-theme-balham.css";

// app.component.ts 編集
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'my-app';

      columnDefs = [
        {headerName: 'Class', field: 'class' },
        {headerName: 'Name', field: 'name' },
        {headerName: 'Power', field: 'power'}
    ];

    rowData = [
        { class: 'Berserker', name: 'Nightingale', power: 35000 },
        { class: 'Assassin', name: 'Carmilla', power: 32000 },
        { class: 'Avenger', name: 'Jeanne alter', power: 72000 }
    ];
}
// app.component.html を以下に置き換え
<ag-grid-angular 
    style="width: 500px; height: 200px;" 
    class="ag-theme-balham"
    [rowData]="rowData" 
    [columnDefs]="columnDefs"
    >
</ag-grid-angular>
// トップページにgridが表示されていればOK。

本題

上記で作ったwebアプリをビルドしたいとします。
要件の1つに「1つのバンドルファイルのサイズが1MB未満であること」
があったとします。
さっそくng build --prodしましょう。



>> ng build --prod

Date: 2019-02-07T15:49:28.086Z
Hash: 817914fa2637c6d3b8aa
Time: 66877ms
chunk {0} runtime.a5dd35324ddfd942bef1.js (runtime) 1.41 kB [entry] [rendered]
chunk {1} es2015-polyfills.12eccedba99646c7daca.js (es2015-polyfills) 56.4 kB [initial] [rendered]
chunk {2} main.00849e0d189f184e52e5.js (main) 1.01 MB [initial] [rendered]
chunk {3} polyfills.407a467dedb63cfdd103.js (polyfills) 41 kB [initial] [rendered]
chunk {4} styles.eb752abcca03cc6fe597.css (styles) 115 kB [initial] [rendered]

おやおや。バンドルされたmain.jsのサイズが1MBを超えてしまいました・・・
(ここのサイズを強調したかったがためにag-Gridのimportを挟みました。
実際は多くのベンダーライブラリをimportしますから、さらに大きくなりますね)

じゃあ --vendorChunk オプションをつけてビジネスロジックとベンダー切り分ければいいだろ!
そうですね。ということでつけてみます。(茶番)



>> ng build --prod --vendorChunk

Date: 2019-02-07T15:58:37.946Z
Hash: 63108113a0539a610fb7
Time: 58052ms
chunk {0} runtime.a5dd35324ddfd942bef1.js (runtime) 1.41 kB [entry] [rendered]
chunk {1} es2015-polyfills.12eccedba99646c7daca.js (es2015-polyfills) 56.4 kB [initial] [rendered]
chunk {2} main.dda08de101eb4da8c253.js (main) 6.04 kB [initial] [rendered]
chunk {3} polyfills.407a467dedb63cfdd103.js (polyfills) 41 kB [initial] [rendered]
chunk {4} styles.eb752abcca03cc6fe597.css (styles) 115 kB [initial] [rendered]
chunk {5} vendor.4d52dd9a82dee508d6a2.js (vendor) 1.01 MB [initial] [rendered]

うーん。結局vendor側が1MBを超えてしまいました。
Angular-CLIの設定だけでどうにかするのは厳しそうです。
そこで今回紹介する方法を試してみましょう。(やっと本題に・・・)


// 使用する拡張モジュールをインストール
 npm -D install @angular-builders/custom-webpack
 npm -D install ngx-build-plus //←1行目のモジュールだけで動かなかったら入れてみて下さい
 npm -D install webpack //←上に同じ。

// angular.json を編集
     //"builder": "@angular-devkit/build-angular:browser",
          "builder": "@angular-builders/custom-webpack:browser", //←に変更
          "options": {
            "customWebpackConfig": {//←追加
              "path": "./extra-webpack.config.js"//←追加
            }, //←追加
            "outputPath": "dist/my-app",
            "index": "src/index.html",
            "main": "src/main.ts",
       //....
// 上で指定した場所(今回ならangular.jsonと同階層)にextra-webpack.config.jsを作成し、
// 追加のwebpack詳細設定を記載する。
// 記載した部分のみがangularのbuilderに追加で反映される
// 今回はmaxSizeを1MB未満にすることでチャンクファイルのサイズ上限を調整した。
const webpack = require('webpack');

module.exports = {
    output: {
        filename: "[name].js" // name of the generated bundle
    },
    optimization: {
        splitChunks: {
            chunks: 'async',
            minSize: 50000,
            maxSize: 900000,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '.',
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    }
};

いいですね。再度ビルドしましょう。



>> ng build --prod

Date: 2019-02-07T17:06:48.049Z
Hash: bbabf25c9a51d613d39a
Time: 41291ms
chunk {0} runtime.js (runtime) 1.41 kB [entry] [rendered]
chunk {1} es2015-polyfills.d0ae3f07.js (es2015-polyfills.d0ae3f07) 56.4 kB [initial] [rendered]
chunk {2} main.31ecd969.js (main.31ecd969) 29.7 kB [initial] [rendered]
chunk {3} main.54813583.js (main.54813583) 278 kB [initial] [rendered]
chunk {4} main.65932fe3.js (main.65932fe3) 33.8 kB [initial] [rendered]
chunk {5} main.88436b06.js (main.88436b06) 191 kB [initial] [rendered]
chunk {6} main.8ff27ea1.js (main.8ff27ea1) 238 kB [initial] [rendered]
chunk {7} main.bc2eed23.js (main.bc2eed23) 29.9 kB [initial] [rendered]
chunk {8} main.d0ae3f07.js (main.d0ae3f07) 2.73 kB [initial] [rendered]
chunk {9} main.defd55b6.js (main.defd55b6) 238 kB [initial] [rendered]
chunk {10} polyfills.d0ae3f07.js (polyfills.d0ae3f07) 41 kB [initial] [rendered]
chunk {11} styles.d0ae3f07.eb752abcca03cc6fe597.css, styles.d0ae3f07.js (styles.d0ae3f07) 115 kB [initial] [rendered]

要件達成です!!おめでとうございます~
もちろんバンドルサイズの変更だけでなく、webpackでのみ設定できる項目なら、
先ほどの拡張configファイルに記載することで反映させることができます。
ビルドコマンドが特に変わらずng build --prodだけで済むのがいいですね。

まとめ

必要なモジュールをインストールした後、しかるべき設定ファイルを編集するだけです。
個人的にはng ejectよりは楽だと思います。
Angularはバージョンアップに伴い、平気で手順変わってくるのでつらいですね。
Angular4での手順が全く役に立たなかったりとかはザラですし。寂しいですね。

Angular7の日本語ドキュメント充実に貢献出来たら幸いです。
御観覧頂きまして、ありがとうございました。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8