electronの勉強をしているとReactなどのSPAの知識が必要になり、 javaScriptの開発には今やwebpackなどのトランスパイルは必須技術。

jsの開発については全然勉強してこなかったので、急がば回れでwebpackの基本的な使い方についてまとめます。

webpackとは

WebAppに必要なリソースの依存関係を解決し、配布物を生成するビルドツール。 複数のjsファイルを一つにまとめたり、TypeScriptやCoffeeScript、css、画像などを扱ったり、 ESLintやBabelなどと組み合わせて文法チェックやトランスパイルを行ったりできる。 最近のjavascriptの開発では主流となっている。

webpackのインストール

$ cd /path/to/yourproject
$ npm init -y
$ npm install webpack --save-dev
$ export PATH=$PATH:./node_modules/.bin

フォルダ構成

今回のフォルダ構成はこのようになります。

├── package.json
├── public
│   ├── index.html
│   └── js
│       └── bundle.js
├── src
│   └── js
│       ├── app.js
│       └── modules
│           ├── add_calc.js
│           └── tax_calc.js
└── webpack.config.js
ファイル・フォルダ名 機能
publicフォルダ ビルドされたファイルが格納される
srcフォルダ 開発用フォルダ。ビルド前のファイルが格納される
public/index.html bundle.jsを読み込んでいるhtmlファイル。
public/js/bundle.js ビルドされたjsファイル。webpackにより、app.js, add_calc.js, tax_calc.jsが一つのファイルとしてまとめられる。
src/js/app.js エントリーポイント。このファイルがビルドの開始地点となる。
src/js/modules/* app.jsで呼ばれているモジュール。モジュール単位でファイルが分かれているので、開発が進めやすい。

webpackでビルドを行うと、js/bundle.jsが作成され、index.htmlはそのjsファイルを読み込むようになっています。 それぞれのファイルは、以下のように記述しました。

public/index.html

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>webpack build test</h1>
    <script type="text/javascript" src="js/bundle.js" charset="utf-8"></script>
  </body>
</html>

このようにjs/bundle.jsを読み込む想定。

webpack.config.js

// output.pathに絶対パスを指定する必要があるため、pathモジュールを読み込んでおく
const path = require('path');

module.exports = {
  // エントリーポイントの設定
  entry: './src/js/app.js',
  // 出力の設定
  output: {
    // 出力するファイル名
    filename: 'bundle.js',
    // 出力先のパス
    path: path.join(__dirname, 'public/js')
  }
};

entryで設定されたjsファイルが最初に読み込まれ、 依存関係などを解決しつつコンパイルされていき、 outputで設定されたパス・ファイル名でビルド結果のjsが作成されます。

src/js/app.js

import add_calc from './modules/add_calc'
import tax_calc from './modules/tax_calc'

var apple_price = 100;
var orange_price = 150;
var tax_num = 1.08;

var total_price = add_calc(apple_price, orange_price);
var result = tax_calc(total_price, tax_num);

console.log(result);

importでmodules/のadd_calcとtax_calcが読み込まれている。

src/js/modules/add_calc.js

/**
 * 引数の足し算の結果を返す
 * @param {number} number1 - 数値1 
 * @param {number} number2 - 数値2
 */
export default function addCalc(number1, number2) {
  return number1 + number2;
}

src/js/modules/tax_calc.js

/**
 * 引数の数値をかけ算の結果を返す
 * @param {number} number - 数値1 
 * @param {number} tax - 数値2
 */
export default function taxCalc(number, tax) {
  return Math.round(number * tax);
}

ビルド

$ webpack
Hash: 271a83ef9e49d47dec01
Version: webpack 3.8.1
Time: 113ms
    Asset     Size  Chunks             Chunk Names
bundle.js  3.77 kB       0  [emitted]  main
   [0] ./src/js/app.js 274 bytes {0} [built]
   [1] ./src/js/modules/add_calc.js 172 bytes {0} [built]
   [2] ./src/js/modules/tax_calc.js 172 bytes {0} [built]

$PATHに./node_modules/.bin/を追加しているので、webpackだけで実行できます。

ビルド結果

ビルド後のpublic/js/bundle.jsの中身(一部省略)です。

$ cat public/js/bundle.js
var apple_price = 100;
var orange_price = 150;
var tax_num = 1.08;

var total_price = Object(__WEBPACK_IMPORTED_MODULE_0__modules_add_calc__["a" /* default */])(apple_price, orange_price);
var result = Object(__WEBPACK_IMPORTED_MODULE_1__modules_tax_calc__["a" /* default */])(total_price, tax_num);

console.log(result);

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = addCalc;
/**
 * 引数の足し算の結果を返す
 * @param {number} number1 - 数値1 
 * @param {number} number2 - 数値2
 */
function addCalc(number1, number2) {
  return number1 + number2;
}

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = taxCalc;
/**
 * 引数の数値をかけ算の結果を返す
 * @param {number} number - 数値1 
 * @param {number} tax - 数値2
 */
function taxCalc(number, tax) {
  return Math.round(number * tax);
}

app.js, add_calc.js, tax_calc.jsが一つのjsファイルにまとめられました。

実行

index.htmlを開いてみると、以下のように表示されましたでしょうか。 Consoleを見ると、app.jsのconsole.log(result); の計算結果も表示されてます。

webpackの基本的な使い方

簡易サーバで開発をする場合

webpack-dev-serverをインストールすると、簡易的なwebサーバをたてれます。

npm install webpack-dev-server --save-dev

webpack.config.js

const path = require("path");

module.exports= {
  entry : "./src/js/app.js",
  output : {
    filename : "bundle.js",
    path : path.join(__dirname, "public/js")
  },
  devServer: {
    contentBase: __dirname + '/public',
    port: 8080,
    publicPath: '/js/'
  }
};

devServerの追記をしました。

実行

$ webpack-dev-server
Project is running at http://localhost:8080/
webpack output is served from /js/
Content not from webpack is served from /Users/Shared/drive/develop/js_dev_test/public
Hash: 4369ffda4cc1d1604b5f
Version: webpack 3.8.1
Time: 671ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  325 kB       0  [emitted]  [big]  main
   [2] multi (webpack)-dev-server/client?http://localhost:8080 ./src/js/app.js 40 bytes {0} [built]
   [3] (webpack)-dev-server/client?http://localhost:8080 7.95 kB {0} [built]
   [4] ./node_modules/url/url.js 23.3 kB {0} [built]
  [11] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
  [12] ./node_modules/ansi-regex/index.js 135 bytes {0} [built]
  [13] ./node_modules/loglevel/lib/loglevel.js 7.74 kB {0} [built]
  [14] (webpack)-dev-server/client/socket.js 1.05 kB {0} [built]
  [15] ./node_modules/sockjs-client/dist/sockjs.js 181 kB {0} [built]
  [16] (webpack)-dev-server/client/overlay.js 3.73 kB {0} [built]
  [17] ./node_modules/ansi-html/index.js 4.26 kB {0} [built]
  [21] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
  [23] (webpack)/hot/emitter.js 75 bytes {0} [built]
  [25] ./src/js/app.js 274 bytes {0} [built]
  [26] ./src/js/modules/add_calc.js 172 bytes {0} [built]
  [27] ./src/js/modules/tax_calc.js 172 bytes {0} [built]
    + 13 hidden modules
webpack: Compiled successfully.

アクセス

http://localhost:8080

ビルド結果に対し、localhostでブラウザからアクセスできるようになりました。

まだまだwebpackには機能があるみたいですが、ひとまずはこれで。 次回はESlintやbabelについて記事をまとめようと思います。

参考

以下のサイトの情報が非常に参考になりました。 ありがとうございます。