2017.3.15
2017.6.6

webpackで開発と本番用の設定ファイルを切り替える

Angular2のQuickStart環境をそのまま実行すると、以下のようなログがブラウザのコンソールに吐き出されます。

Angular is running in the development mode. Call enableProdMode() to enable the production mode.

ログの内容は、開発モードで実行されているので、本番用に実行するならenableProdMode()メソッドを呼んでね、という感じです。切り替えることでなにが変わるのかは分からないのですが、開発と本番で呼び出すサービスのURLを変えたかったこともあり、webpackの設定ファイルを利用してenableProdMode()メソッドを呼び出すとともに、サービスのURLを開発と本番モードを切り替えるようにしました。

やることは以下の通り。

  • webpack-mergeのインストール
  • 設定ファイルの作成(webpack.common.js、webpack.dev.js、webpack.prod.js)
  • 設定ファイルを切り替える(package.json)
  • モジュール側の環境設定用ファイルの作成(environment.ts)
  • TypeScript用の型定義ファイル(.d.ts)の作成
  • ENV(開発、本番モード)の利用

環境は、Angular2のQuickStartをベースにして、こちら(AngularClass/angular2-webpack-starter)を参考...というか、必要そうなところを抜き出したものになります。

以下、設定方法です。

目次

  • webpack-mergeのインストール
  • ディレクトリ構成とファイルの格納場所
  • 設定ファイルの作成
  • 設定ファイルを切り替える
  • モジュール側の環境設定用ファイルの作成
  • TypeScript用の型定義ファイル(.d.ts)の作成
  • ENV(開発、本番モード)の利用

webpack-mergeのインストール

まず、webpackの設定ファイル切替用に「webpack-merge」をインストールします。


npm install webpack-merge --save-dev

ディレクトリ構成とファイルの格納場所

以下、今回関係あるファイルの格納場所です。

project
├ package.json
├ config
│  ├ webpack.common.js
│  ├ webpack.dev.js
│  └ webpack.prod.js
├ dist
│  ├ bundle.js
│  └ index.html
├ node_modules
└ src
    ├ custom-typings.d.ts
    ├ entry.js
    └ app
        ├ app.module.ts
        ├ app.service.ts
        └ environment.ts

設定ファイルの作成

続いて、トップにconfigフォルダを作成して、その下に、共通、開発用、本番用のwebpack設定ファイルを作成します。

webpack.common.js(共通)


module.exports = function () {
  return {
    entry: './src/entry.js',
    output: {
      path: './dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    module: {
      rules: [
        ...
      ],
      loaders: [
        ...
      ],
    },
    resolve: {
      extensions: ['.js', '.css']
    },
  };
}

webpack.dev.js(開発用)


const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ENV = 'development';

module.exports = webpackMerge(commonConfig(), {
  plugins: [
    new DefinePlugin({
      'ENV': JSON.stringify(ENV),
    }),
  ]
});

webpack.prod.js(本番用)


const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ENV = 'production';

module.exports = webpackMerge(commonConfig(), {
  plugins: [
    new DefinePlugin({
      'ENV': JSON.stringify(ENV),
    }),
  ]
});

webpackの設定ファイルから「DefinePlugin」というプラグインを使うことで、設定値等の値をモジュールで参照できるようになります。

詳しくはこちら(Webpackを使ってJSでも.envしたい)を参照。

設定ファイルを切り替える

webpack設定ファイルの切替は「package.json」の「scripts」で行うので、開発、本番それぞれのwebpack設定ファイルを読み込むscriptsを用意します。


{
  ...
  "scripts": {
    "webpack:prod": "webpack --config config/webpack.prod.js",
    "webpack:dev": "webpack --config config/webpack.dev.js",
  },
  ...
}

モジュール側の環境設定用ファイルの作成

モジュール側でenableProdMode()メソッドを呼び出すためのファイルを用意します。

environment.ts(appフォルダ直下に作成)


import { enableProdMode } from '@angular/core';

let PROVIDERS: any[] = [
];

if ('production' === ENV) {
  enableProdMode();

  PROVIDERS = [
    ...PROVIDERS,
  ];
} else {
  
  PROVIDERS = [
    ...PROVIDERS,
  ];
}

export const ENV_PROVIDERS = [
  ...PROVIDERS
];

上記で作成したファイルを「app.module.ts」で呼び出します。


import { ENV_PROVIDERS } from './environment';
@NgModule({
  ...
  providers: [ 
    ENV_PROVIDERS 
  ],
  ...
})
export class AppModule { 
}

TypeScript用の型定義ファイル(.d.ts)の作成

上記の対応だけではコンパイルエラー「Cannot find name 'ENV'.」が発生してしまいます。何が必要なのか探していたら、どうやら型定義のファイル「~~~.d.ts」が必要みたいでした。

「custom-typings.d.ts」ファイルをsrcフォルダ直下に作成して、内容は以下のようにします。(拡張子さえ「.d.ts」ならファイル名はなんでもいいみたいです)


declare var ENV: string;

型定義ファイルについて詳しくはこちら(Visual StudioとTypeScriptでJavaScriptライブラリを活用する)を参照してください。拡張子を見てわかる通り、TypeScript独自のファイルです。

ENV(開発、本番モード)の利用

以上で変数「ENV」に開発(development)、本番(production)モードの情報が格納されるようになるので、以下のように利用します。


export class AppService {
  private serviceUrl = "";

  constructor() { 
    if('production' === ENV){
      this.serviceUrl = "/example";
    }else{
      this.serviceUrl = "http://localhost/example";
    }
  }
}

最初はなにやっているかさっぱりなAngular2のスターターキットでしたが、ちゃんと見ていけば、なんとなくですが分かるかるものなんですね。

Angular】関連記事