やること
ES2015(ES6)とwebpackを組み合わせて、簡単なWebアプリケーションを作ってみます。
webpack はjsやcssなど、webページで読み込まれる部品の依存関係を解決し、合成してくれるモジュールバンドラーです。
webpackはgulp,gruntなどのタスクランナーと組み合わせて使うことも多いですが、今回は使用しません。
以下の条件を満たすプロジェクトを作成します。
- classを継承する
- classをimportして使用する
- IE11が対応していない、ES6のPromiseを使う
#開発環境
- Mac OS X High Sierra
- Webpack 4.20.2
Node.jsをインストール
必要なモジュールはnpm(Node Package manager)でインストールが出来ます。
まずはNode.jsをインストールします。
brew install node
これでnpmが使えるようになります。
ディレクトリ構成
今回は以下のようなディレクトリ構成を実現します。
dist
└── main.js
lib
├── BusinessMember.js
└── Member.js
node_modules
.babelrc
index.js
index.html
package.json
webpack.config.js
プロジェクトの作成
まずは任意のディレクトリを作成し、その中で以下コマンドでプロジェクトを作成します。
-yオプションをつけないと、各種項目について都度聞かれます。
-yを付けずにそのままEnterを連打してもかまいません。
$ npm init -y
実行するとpackage.jsonが出来上がります。
後述しますが、このファイルに記載されたライブラリ全てをnpm installで
インストールできるようになりますので、他の人に配布する際に環境構築が簡単にできます。
各種モジュールのインストール
npmで必要な各種モジュールのインストールをします。
2018/10/3現在、babel-loaderの最新バージョンは8系になります。
8系と7系でコマンドやファイルの内容が異なりますので、2つのバージョンについて説明をします。
以下、バージョンについて特に記載がないものは、どちらでも使用可能です。
$ npm install --save-dev @babel/core @babel/polyfill @babel/preset-env babel-loader webpack webpack-cli
$ npm install --save-dev babel-core babel-polyfill babel-preset-env babel-loader@7 webpack webpack-cli
ビルド時には必要ですが実行時には不要なパッケージなので、--save-dev で入れます。
また、特定のバージョンをインストールしたい場合には、インストールできるバージョンの一覧が以下のコマンドで確認できますので、使用するといいでしょう。
$ npm info パッケージ名 versions --json
--save-devを付けると package.json のdevDependenciesに記載されます。
モジュールが無い状態でnpm installを実行すると、
devDependenciesに書かれたライブラリがnode_modulesにインストールされます。
そのためgit管理からはnode_modulesディレクトリは外して問題ありません。
これでライブラリのインストールが終わりました。
確認をしてみましょう。
npm ls
で確認が出来ます。--depth 0
をつけるとトップのモジュールのみが確認できます。
$ npm ls --depth 0
├── @babel/core@7.1.2
├── @babel/polyfill@7.0.0
├── @babel/preset-env@7.1.0
├── babel-loader@8.0.4
├── webpack@4.20.2
└── webpack-cli@3.1.2
HTML,jsファイルの作成
次にHTML,jsファイルを作成します。
lib/Member.js
'use strict';
export default class Member {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return this.lastName + ' ' + this.firstName;
}
get firstName() {
return this._firstName;
}
set firstName(value) {
this._firstName = value;
}
get lastName() {
return this._lastName;
}
set lastName(value) {
this._lastName = value;
}
}
lib/BusinessMember.js
'use strict';
import Member from './Member';
export default class BusinessMember extends Member{
constructor(firstName, lastName, company) {
super(firstName, lastName); // 親クラスのコンストラクタは、コンストラクタの1行目で記載する必要がある
this.company = company;
}
get company() {
return this._company;
}
set company(value) {
this._company = value;
}
getName() {
return this.lastName + ' ' + this.firstName + '/' + this.company;
}
}
index.js
'use strict';
import BusinessMember from './lib/BusinessMember';
let pro = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 500)
});
pro.then(response => {
let user = new BusinessMember('taro', 'yamada', 'G社');
console.log(user.getName());
});
index.html
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<meta charset="UTF-8">
<script src="dist/main.js"></script>
<title>ES6のテスト</title>
</head>
<body>
</body>
</html>
webpackの準備
最後にwebpackを実行するための設定ファイルを作成します。
.babelrcには、Babelの設定を記載します。
webpack.config.jsの中に書くことも出来ますが、本格的な開発では分けることが多いと思いますので、分けました。
envの指定は、よくあるbabel-preset-envの書き方です。
https://babeljs.io/docs/plugins/preset-env/
.babelrc(babel-loader8用)
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
.babelrc(babel-loader7用)
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
webpack.config.js にはwebpackコマンド実行時の設定を記載します。
webpack.config.js(babel-loader8用)
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: ['@babel/polyfill', './index.js'], // polyfill はIE11などで必要
output: {
path: `${__dirname}/dist`,
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
webpack.config.js(babel-loader7用)
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: ['babel-polyfill', './index.js'], // babel-polyfill はIE11などで必要
output: {
path: `${__dirname}/dist`,
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
webpack実行
それではwebpackを実行します。
$ npx webpack
Hash: 53476175c174b19d1a89
Version: webpack 4.20.2
Time: 2695ms
Built at: 2018/10/03 1:56:45
Asset Size Chunks Chunk Names
main.js 370 KiB main [emitted] main
main.js.map 294 KiB main [emitted] main
Entrypoint main = main.js main.js.map
[./index.js] 300 bytes {main} [built]
[./lib/BusinessMember.js] 2.95 KiB {main} [built]
[./lib/Member.js] 1.37 KiB {main} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 509 bytes {main} [built]
[0] multi @babel/polyfill ./index.js 40 bytes {main} [built]
+ 276 hidden modules
これでmain.jsが出来上がりました。
動作確認
ChromeやIE11でindex.htmlにアクセスし、コンソールに yamada taro/G社 と表示されれば成功です。
npm scriptsの編集
npm scriptsにコマンドを記載することで、簡単に処理が実行できます。
package.jsonの scripts
にコマンドを記載します。
webpackは --watch
を付けることで、対象となるファイルが更新されたときに自動でビルドを実行することが可能です。
watch
という名前で実行できるようにしましょう。
ついでに、webpack自体はbuild
という名前で実行できるようにしておきます。
〜
"scripts": {
"build": "webpack",
"watch": "webpack --watch"
},
〜
以下のようにコマンドを実行すると監視のジョブが常駐します。
jsファイルに何かしら処理の変更を加えると、ビルドが自動的に走ることが確認できます。
$ npm run watch
おまけ
Jestでテストを行う
Jestを使ってテストを書いていきます。
JestはFacebook製のJSのテストツールです。
https://facebook.github.io/jest/en/
まずはJestをインストールしましょう。
$ npm install --save-dev jest
次にテスト用のディレクトリであるtest
を作成します。
$ mkdir test
testディレクトリの中にテストを作っていきます。
'use strict';
import BusinessMember from '../lib/BusinessMember';
test('BusinessMember.getName() to be "firstName lastName/company"', function() {
let user = new BusinessMember('ken', 'sato', 'A社');
expect(user.getName()).toBe('sato ken/A社');
});
'use strict';
import Member from '../lib/Member';
test('Member.getName() to be "firstName lastName"', function() {
let user = new Member('ken', 'sato');
expect(user.getName()).toBe('sato ken');
});
それではテストを実行しましょう。
$ npx jest
PASS test/BusinessMember.test.js
PASS test/Member.test.js
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.195s
Ran all test suites.
test
という名前で npm scripts
にも記載します。
〜
"scripts": {
"build": "webpack",
"watch": "webpack --watch",
"test": "jest"
},
〜
test
というコマンドについては、npm run
のrun
は不要ですので、以下のように実行できます。
$ npm test
以下のように引数を渡せば、カバレッジを取ることも可能です。
$ npm test -- --coverage
> jest "--coverage"
PASS test/BusinessMember.test.js
PASS test/Member.test.js
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
BusinessMember.js | 100 | 100 | 100 | 100 | |
Member.js | 100 | 100 | 100 | 100 | |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.352s
Ran all test suites.