BrowserifyからWebpack(バージョン2.2.1)に移行してみた
目次
今までのプロジェクトで、ずっとフロントの開発環境としてBrowserifyを使ってきたけど、gulpの記述が悪いのか、
とにかく重たいのでWebpackを試してみることにした。
1 Webpackの特徴
事前に調べてみた範囲では以下のような特徴があるとのこと。
- JSの依存関係を解決できる。
- JS以外のファイルもまとめて扱える。
- gulpを置き換えることもできる。
- ビルド結果を複数にすることが容易。
- トランスパイラ機能あり(Sass、TypeScript、Babel)
- 全ファイルをjsにするので、cssなどを別扱いにするなら、gulpと組み合わせる方が良い。
2 今回やりたいこと
- JavaScriptファイルを複数の単位でまとめる。
- JSONもマージしたい。
- 難読化、minifyする。
- ソースマップを作る。
- watchも機能させる。
3 インストール方法
- webpackをnpmインストールする。(以下ではnpm iの代わりにyarn addを使用)
$ yarn [global] add webpack $ yarn [global] add ***-loader # ***の部分はbabelやsass、ts、jsonなど。読み込みたいファイルに対応したloaderをインストールする。
- 開発用サーバをインストールする。(任意)
$ yarn add webpack-dev-server # node 4.7以上が必要。
- webpack.config.jsを作成する。
- コマンドを打つなり、gulpに組み込むなりで動かす。
4 動かし方
4-1 コマンドで動かす方法
- webpackを実行する。
$ webpack
- watchを実行する。
$ webpack --progress --colors --watch
- serverを起動する。
$ webpack-dev-server --progress —colors
4-2 gulpで動かす方法
- 「webpack-stream」をnpmインストールする。
- 以下のようなgulpタスクを作成する。
import webpackStream from 'webpack-stream'; import webpack from 'webpack'; import webpackConfig from '../webpack.config'; // webpack.config.jsのパスを指定する。 gulp.task('webpack', () => { webpackConfig.watch = true; // watchをしたい場合は必要。webpack.config.jsに直接書いてもOK。 return webpackStream(webpackConfig, webpack) .on('error', function handleError() { // watch中のエラーで死なないようにする。 this.emit('end'); }) .pipe(gulp.dest(config.sources.dest)); });
- gulpを実行する。
5 webpack.config.jsの書き方
5-1 最低限必要な内容
const config = { // メインとなるJavaScriptファイル(エントリーポイント) entry: './app/js/index.js', // ファイルの出力設定 output: { filename: 'bundle.js', } }
5-2 難読化、最適化してみる。
- webpack.config.jsに以下を追記。
plugins: [ new webpack.optimize.UglifyJsPlugin({ minimize:true }), new webpack.optimize.OccurrenceOrderPlugin() ]
UglifyJsPluginは、gulp-uglifyと同じく難読化とminifyを行ってくれるプラグイン。
OccurrenceOrderPluginは、Uglifyされたスクリプト中に出てくるIDの桁数を短くするプラグイン(らしい)。
5-3 ソースマップを使う。
- UgilifyJsPluginの引数のオブジェクトに「sourceMap: true」を追加する。
- webpack.config.jsに以下を追記。
devtool: 'inline-source-map'
5-4 作成するファイルを複数に分割する。(browserifyとの大きな違い)
- entryをオブジェクトで記述する。
- 配列を使うと、マージする順番を指定できる。(GoogleAnalyticsをファイルの最後に追加するなど)
- outputのfilenameに[name]をつける。
5-5 共通処理を1つのJSファイルにまとめる。
- webpack.optimize.CommonsChunkPluginを使う。
5-6 JSONもコンパイル対象にする。(同様に画像やCSSもコンパイルできる)
5-7 CDNの外部ライブラリを使ってみる。
externalsを定義することで、CDNで取得した外部ライブラリを、import無しで使用可能となる。
externals: { '$': 'jQuery', 'jquery-ui': 'jquery-ui', },
5-8 一部のローカルライブラリのimportでエラーが出る場合
今回Amchartsを使おうとしたところ、名前が解決できないというエラーが出てしまった。 webpack.config.jsに以下のようにresolve.aliasを書くと解消できた。
resolve: { alias: { amcharts3$: path.resolve(__dirname, 'app/js/lib/amcharts/amcharts.js') } }
6 webpack.config.jsのサンプル
最終的に作って見たwebpack.config.jsはこんな感じ。
const webpack = require('webpack'); const path = require('path'); const env = process.env.NODE_ENV; const config = { // メインとなるJavaScriptファイル(エントリーポイント) entry: { 'bundle': path.resolve(__dirname, '../app/js/index.js'), 'chart': path.resolve(__dirname, '../app/js/chart.js'), }, // ファイルの出力設定 output: { filename: '[name].js', }, // amcharts3のimport失敗への対応 resolve: { alias: { amcharts3$: path.resolve(__dirname, '../app/js/lib/amcharts/amcharts.js') } }, externals: { '$': 'jQuery', 'jquery-ui': 'jquery-ui', }, module: { rules: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.json$/, loader: 'json-loader' }, ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(env) }), new webpack.optimize.OccurrenceOrderPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: 'commons', filename: 'commons.js', minChunks: Infinity }) ] }; if (env === 'production') { config.plugins.push(new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })); } else { config.plugins.push( new webpack.optimize.UglifyJsPlugin({ sourcemap: true, minimize: true }) ); config.devtool = 'source-map'; } module.exports = config;