はじめに
今回もwebpackネタです。色々機能がありすぎるのか自分が記事書くの遅いのか、思いの外進んでおらずもどかしいです。
まぁそんなことはおいといて、webpackの開発環境用ツールのことについて触れたいと思います。
ただ公式にもありますが、本番環境で使うのは避けてくださいとあります。絶対使っちゃいけませんよ?
今後も増えれば記事に追加していきます。もしおすすめがあれば是非教えてくださいm(__)m
inline-source-map
通常ですと、複数ファイルをbundleしてエラーが発生した場合、
ブラウザのconsoleログに出てくるのはbundle.js(bundle.jsに出力したとして)の何行目・・・
と言う情報しか出てきません。
これではデバッグしづらいです。そこでinline-source-map
を使うわけですが、これを使うとbundle前のファイルを示してくれます。
設定の追加自体はwebpack.config.jsに1行追加するだけの簡単なお仕事ですので、ここでは有り無しでの比較をしてみます。
使うソースはこちらを元にしています。
設定なしの場合
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'development'
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
src/index.jsの中でボタンを生成していて、クリックされたらsrc/print.jsのprintMe
メソッドを呼び出すソースです。
今回はわざとエラーを発生させるためにprintMeメソッドで呼び出すconsole
メソッドをcosnole
に変更しています。
import _ from 'lodash';
import printMe from './print.js';
function component() {
var element = document.createElement('div');
var btn = document.createElement('button');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
btn.innerHTML = 'Click me and check the console!';
btn.onclick = printMe;
element.appendChild(btn);
return element;
}
document.body.appendChild(component());
export default function printMe() {
cosnole.log('I get called from print.js!');
}
準備が整いましたのでyarn run build
でbundleします。
するとdist以下にindex.htmlが出力されます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>development</title>
</head>
<body>
<script type="text/javascript" src="app.bundle.js"></script><script type="text/javascript" src="print.bundle.js"></script></body>
</html>
このdist/index.htmlをブラウザで開いて、Click me and check the console!
というボタンをクリックしてみます。
※この時developer toolsを開いてconsoleログが出力される窓を開いておいてください
以下のようなログが出力されます。
app.bundle.js:74 Uncaught ReferenceError: cosnole is not defined
at HTMLButtonElement.printMe (app.bundle.js:74)
printMe @ app.bundle.js:74
出力されたログをみると、app.bundle.jsの74行目と出ています。
これだとbundleされたファイルを見ないといけません。
設定ありの場合
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
// ここのみが↑との違いです
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'development'
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
それではyarn run build
でbundleしてブラウザで見てみます。
Uncaught ReferenceError: cosnole is not defined
at HTMLButtonElement.printMe (print.js:2)
printMe @ print.js:2
と出ました。ちゃんとbundle前のファイルが示されていますね。
これでもう迷わずデバッグが捗ること間違いなしです。
inline-source-map
については以上になります。
watch
ファイルに変更があったらそれを検知して自動でコンパイルしてくれるアレです。
導入は簡単です。
{
"name": "webpack-demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack",
"watch": "webpack --watch"
},
"devDependencies": {
"clean-webpack-plugin": "^0.1.16",
"html-webpack-plugin": "^2.30.1",
"lodash": "^4.17.4",
"webpack": "^3.5.6"
}
}
yarn run watch
でwatchモードを実行します。監視状態になっているのでCtl + c
などで終了しないようにしてください。
↑でわざとエラーにしていたsrc/print.jsのprintMeメソッドを修正してみます。
terminalに以下の内容が出力されました。
Hash: 722d90ab6cb81f6745e4
Version: webpack 3.6.0
Time: 486ms
Asset Size Chunks Chunk Names
app.bundle.js 1.44 MB 0, 1 [emitted] [big] app
print.bundle.js 6.42 kB 1 [emitted] print
index.html 248 bytes [emitted]
[0] ./src/print.js 84 bytes {0} {1} [built]
+ 4 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
4 modules
実際にブラウザで開いてボタンをクリックしてみるとエラーログが出力されず、ちゃんと文字列が出力されていました。
yarn run build
をわざわざ毎回実行しなくていいのは助かります。
余談ですが、watchで実行されるコンパイルにプログレスバーを表示したり色をつけたりするには、
"scripts": {
"watch": "webpack --progress --colors --watch"
},
とすればオーケーです。この記事でやった変更ではプログレスバーの出番はありませんが、
大きくなったプロジェクトなどでは使えると思います。
おわりに
watch以外にもwebpack-dev-server
やwebpack-dev-middleware
プラグインを使ってローカルサーバーを立ち上げる方法もあります。興味ある方は深掘りしてみてください。上記プラグインは、node.jsのexpressを使ってサーバーを立ち上げています。自分のケースに限っていえばカバー範囲広げるのも辛いので一旦watchで行こうかと。