【Webpack4 備忘録】オススメ設定詰め合わせ
この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。
備忘録で作成したもの以外に入れた方がいいもののまとめ。
以前、備忘録で作成した こちら に設定を追加する。
目次
ソースマップにオリジナルのソースコードを表示する
デフォルト設定のソースマップは以下の通り。
このままだと、デバッグが捗らない。
開発環境で、ソースマップにオリジナルのソースコードを表示する設定を追加するには、webpackにdevtoolの設定を追加する必要がある。
実装
webpack.conf.jsに以下の設定を追加する。
// 中略 ... module.exports = { // 中略 ... // ソースマップの設定(オリジナルのソースコードを出力、コメントも出力される) devtool: 'eval-source-map', // 中略 ... };
変更後は、以下の通りオリジナルのソースコードが表示されるようになる。
これで多少はデバッグがしやすくなるはず。
参考
build時にhtmlファイルも生成する
以前作成したボイラープレートのままだと、build
ディレクトリにHTMLファイルは生成されない。
html-webpack-plugin
を使用することで、ビルドコマンドを実行するたびにbuild
ディレクトリにHTMLファイルを生成できるようになる。
html-webpack-plugin とは
webpackで生成したJavaScriptやCSSを埋め込んだHTMLを生成できるプラグイン。
ディレクトリごとデプロイしたい場合などに使える。
実装
プラグインをインストールする。
$ npm install -D html-webpack-plugin
webpack.config.js
でhtml-webpack-plugin
を読み込む。
const htmlWebpackPlugin = require('html-webpack-plugin'); // 中略 ... module.exports = { // 中略 ... plugins: [ // filenameで指定したJSを読み込むHTMLファイルをbuildディレクトリに生成 new htmlWebpackPlugin() ], // 中略 ... } // 中略 ...
ビルドコマンドを実行して確認する。
$ npm run build > react-ts-webpack@1.0.0 build /Users/kento/Programing/VScodeProjects/ts-react-sass-simple-boiler-v4 > webpack Hash: f56cebd02a6bb3a59a34 Version: webpack 4.38.0 Time: 2598ms Built at: 2019-12-02 18:44:16 Asset Size Chunks Chunk Names bundle.js 967 KiB main [emitted] main index.html 182 bytes [emitted] Entrypoint main = bundle.js [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loade r/src!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss 506 bytes {main} [built] [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./src/assets/img/react.png] 31.3 KiB {main} [built] [./src/assets/img/vue.png] 5.48 KiB {main} [built] [./src/index.tsx] 810 bytes {main} [built] [./src/scss-style.scss] 1.35 KiB {main} [built] + 15 hidden modules Child html-webpack-plugin for "index.html": 1 asset Entrypoint undefined = index.html [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
build
ディレクトリにHTMLファイルが生成される。
$ tree ./build ./build ├── bundle.js └── index.html 0 directories, 2 files
中身は、同階層のbundle.js
を読み込む設定で自動生成される。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Webpack App</title> </head> <body> <script type="text/javascript" src="bundle.js"></script></body> </html>
スタイルシートを要素として出力する
style-loader
とcss-loader
を使用することで、<style>
という要素を埋め込むことができるが、スタイルシートは別ファイルとして<link>
要素で埋め込むのが一般的である。
別ファイルとして読み込むためには、style-loader
ではなく extract-text-webpack-plugin
を使用する。
extract-text-webpack-pluginとは
バンドルしたリソースをファイルとして切り出すためのプラグイン。
実装
webpack用のプラグインをインストールする。
# latestバージョンでは、対応していないので @next をインストールする $ npm install -D extract-text-webpack-plugin@next
webpack.config.js
にプラグインを追加する。
const extTextPlugin = require('extract-text-webpack-plugin'); // 中略 ... const rules = [ /* Sass用設定 */ { // 対象とする拡張子を指定 test: /\.scss$/, // extract-text-webpack-plugin に use で指定しているloaderを加える use: extTextPlugin.extract([ // linkタグへの出力用 // 'style-loader', extract-text-webpack-plugin を使うので不要 // CSSのバンドル設定 { loader: 'css-loader', options: { // css内のurl()メソッドを取り込む設定 url: true, // // ソースマップの有効化 development と production で勝手に切り替わるのでコメントアウト // sourceMap: true, // sass-loader と postcss-loader を使用するので 2 を設定 // ここを参考に設定 https://github.com/webpack-contrib/css-loader#importloaders importLoaders: 2, }, }, 'postcss-loader', { loader: 'sass-loader', // options: { // // ソースマップの有効化 development と production で勝手に切り替わるのでコメントアウト // sourceMap: true, // } }, ]), }, // 中略 ... ]; module.exports = { // 中略 ... plugins: [ // 出力ファイル名を指定 new extTextPlugin('[name].css'), ], // 中略 ... } // 中略 ...
ビルドコマンドを実行して確認する。
$ npm run build > react-ts-webpack@1.0.0 build /Users/kento/Programing/VScodeProjects/ts-react-sass-simple-boiler-v5 > webpack Hash: f7c0f22ec54908cad1c7 Version: webpack 4.38.0 Time: 2071ms Built at: 2019-12-02 19:12:25 Asset Size Chunks Chunk Names bundle.js 2.29 MiB main [emitted] main index.html 221 bytes [emitted] main.css 5.68 KiB main [emitted] main Entrypoint main = bundle.js main.css [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./src/assets/img/react.png] 31.3 KiB {main} [built] [./src/assets/img/vue.png] 5.48 KiB [built] [./src/index.tsx] 1.22 KiB {main} [built] [./src/scss-style.scss] 41 bytes [built] [./src/style1.scss] 41 bytes [built] [./src/style2.scss] 41 bytes [built] + 14 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/scss-style.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss 506 bytes {0} [built] [./src/assets/img/vue.png] 5.48 KiB {0} [built] + 2 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style1.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style1.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style1.scss 169 bytes {0} [built] + 1 hidden module Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style2.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style2.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style2.scss 169 bytes {0} [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset Entrypoint undefined = index.html [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
CSSファイルが別ファイルとして切り出されていることがわかる。
$ tree ./build ./build ├── bundle.js ├── index.html └── main.css 0 directories, 3 files
./build/index.html
にもLinkタグが追加されている。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Webpack App</title> <link href="main.css" rel="stylesheet"></head> <body> <script type="text/javascript" src="bundle.js"></script></body> </html>
CSSとJSを別ファイルとすることで、並行してのダウンロードができるので、パフォーマンス改善も期待できる。
大きい画像ファイルを別ファイルとして出力する
ファビコンなどの小さい画像イメージならJSにバンドルしてもパフォーマンスに影響しないが、数百KBの画像ファイルをJSにバンドルすると、パフォーマンスが悪くなる。
file-loaderを使う
file-loaderを使うことで、一定以上の大きさの画像ファイルはそのまま画像ファイルとして保持できる。
実装
file-loader
をインストールする。
$ npm install -D file-loader
web pack.config.js
に設定を追加する。
// 中略 ... const rules = [ // 中略 ... /* 画像ファイル用設定 */ { // 対象となるファイルの拡張子を設定 test: /\.(gif|png|jpg|jpeg|svg|ttf|eot|wof|woff|woff2)$/, // 画像をBase64で取り込み loader: 'url-loader', //// ↓ 追加 // 画像ファイルに関するオプション options: { // 20KB以上を対象とする(バイナリ換算) // https://www.gbmb.org/kb-to-bytes で正確な値を調べる limit: 20480, // ファイルのアウトプット場所 名前は保持 name: "./images/[name].[ext]" } }, ]; // 中略 ...
ビルドコマンドを実行して確認する。
$ npm run build > react-ts-webpack@1.0.0 build /Users/kento/Programing/VScodeProjects/ts-react-sass-simple-boiler-v5 > webpack Hash: c6425b45d4a5dcfdf726 Version: webpack 4.38.0 Time: 2676ms Built at: 2019-12-02 19:36:26 Asset Size Chunks Chunk Names ./images/react.png 23.5 KiB [emitted] bundle.js 2.22 MiB main [emitted] main index.html 221 bytes [emitted] main.css 5.68 KiB main [emitted] main Entrypoint main = bundle.js main.css [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./src/assets/img/react.png] 62 bytes {main} [built] [./src/assets/img/vue.png] 5.48 KiB [built] [./src/index.tsx] 1.22 KiB {main} [built] [./src/scss-style.scss] 41 bytes [built] [./src/style1.scss] 41 bytes [built] [./src/style2.scss] 41 bytes [built] + 14 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/scss-style.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss 506 bytes {0} [built] [./src/assets/img/vue.png] 5.48 KiB {0} [built] + 2 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style1.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style1.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style1.scss 169 bytes {0} [built] + 1 hidden module Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style2.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style2.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style2.scss 169 bytes {0} [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset Entrypoint undefined = index.html [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
vue.png
はないが20KB以上のreact.png
は存在する。 (react.png
は約25KBの画像ファイル)
$ tree ./build ./build ├── bundle.js ├── images │ └── react.png ├── index.html └── main.css 1 directory, 4 files
ビルドのたびにbuildディレクトリをクリーンアップする
clean-webpack-plugin
を追加することで、ビルド先のディレクトリをビルド前にクリーンアップできる。(versionは3系を使用)
実装
clean-webpack-plugin
をインストールする。
$ npm install -D clean-webpack-plugin
webpack.config.js
に設定を追加する。
outputオプションで指定したディレクトリがクリーンアップ対象となる。
// 中略 ... const {CleanWebpackPlugin} = require('clean-webpack-plugin'); // 中略 ... module.exports = { // 中略 ... // 各種プラグイン plugins: [ // ここでは、buildディレクトリをビルド前にクリーンアップ new CleanWebpackPlugin(), ], // 中略 ... };
確認用にtext.txt
を配置
$ $ tree ./build ./build ├── bundle.js ├── images │ └── react.png ├── index.html ├── main.css └── test.txt ← ここ 1 directory, 5 files
ビルドコマンドを実行して確認する。
$ npm run build > react-ts-webpack@1.0.0 build /Users/kento/Programing/VScodeProjects/ts-react-sass-simple-boiler-v5 > webpack Hash: c6425b45d4a5dcfdf726 Version: webpack 4.38.0 Time: 2772ms Built at: 2019-12-03 09:38:26 Asset Size Chunks Chunk Names ./images/react.png 23.5 KiB [emitted] bundle.js 2.22 MiB main [emitted] main index.html 221 bytes [emitted] main.css 5.68 KiB main [emitted] main Entrypoint main = bundle.js main.css [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./src/assets/img/react.png] 62 bytes {main} [built] [./src/assets/img/vue.png] 5.48 KiB [built] [./src/index.tsx] 1.22 KiB {main} [built] [./src/scss-style.scss] 41 bytes [built] [./src/style1.scss] 41 bytes [built] [./src/style2.scss] 41 bytes [built] + 14 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/scss-style.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/scss-style.scss 506 bytes {0} [built] [./src/assets/img/vue.png] 5.48 KiB {0} [built] + 2 hidden modules Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style1.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style1.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style1.scss 169 bytes {0} [built] + 1 hidden module Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--5-1!node_modules/postcss-loader/src/index.js!node_modules/sass-loader/lib/loader.js!src/style2.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js!./node_modules/sass-loader/lib/loader.js!./src/style2.scss] ./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src!./node_modules/sass-loader/lib/loader.js!./src/style2.scss 169 bytes {0} [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset Entrypoint undefined = index.html [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
buildディレクトリを削除して、再作成するためtest.txt
は存在しない。
$ tree ./build ./build ├── bundle.js ├── images │ └── react.png ├── index.html └── main.css 1 directory, 4 files
プロダクション環境へのデプロイモジュールを小さくする
ビルドコマンドでproduction
を指定している場合、ソースコードは最適化されるが、一部不要なコードやCSSの最適化までは行われない。
uglifyjs-webpack-plugin
とoptimize-css-assets-webpack-plugin
で最適化できる。
uglifyjs-webpack-pluginとは
プロダクション環境で関数を除去できるプラグイン。
例えば、本番環境では、console.log()は必要ないから削除したいなど。
実装
uglifyjs-webpack-plugin
をインストールする。
$ npm install -D uglifyjs-webpack-plugin
webpack.config.js
に設定を追加する。
// 中略 ... const uglifyJsPlugin = require('uglifyjs-webpack-plugin'); // 中略 ... module.exports = { // 中略 ... // プロダクション環境での設定(minimizer) optimization: { minimizer: [ new uglifyJsPlugin({ uglifyOptions: { compress: { // console.log() console.table()等除去 drop_console: true } } }) ] }, // 中略 ... };
optimize-css-assets-webpack-pluginとは
XXX.min.cssのように改行などを削除したCSSを出力できるプラグイン。
実装
optimize-css-assets-webpack-plugin
をインストールする。
$ npm install -D optimize-css-assets-webpack-plugin
web pack.config.js
に設定を追加する。
// 中略 ... // uglifyjs-webpack-pluginは必須 const uglifyJsPlugin = require('uglifyjs-webpack-plugin'); const optimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // 中略 ... module.exports = { // 中略 ... // プロダクション環境での設定(minimizer) optimization: { minimizer: [ // 必須 new uglifyJsPlugin({ // 省略 ... }), // スタイルシートの圧縮設定 new optimizeCssAssetsPlugin({}), ] }, // 中略 ... };
変更前
$ npm run build-prod > react-ts-webpack@1.0.0 build-prod /Users/kento/Programing/VScodeProjects/ts-react-sass-simple-boiler-v5 > webpack --mode=production Hash: f2a87911c7157885324e Version: webpack 4.38.0 Time: 2916ms Built at: 2019-12-03 10:22:04 Asset Size Chunks Chunk Names ./images/react.png 23.5 KiB [emitted] bundle.js 336 KiB 0 [emitted] [big] main index.html 221 bytes [emitted] main.css 5.68 KiB 0 [emitted] main ← ここ 中略 ...
変更後
$ npm run build-prod > react-ts-webpack@1.0.0 build-prod /Users/kento/Programing/VScodeProjects/ts-react-sass-sim ple-boiler-v5 > webpack --mode=production Hash: f2a87911c7157885324e Version: webpack 4.38.0 Time: 2357ms Built at: 2019-12-03 10:20:39 Asset Size Chunks Chunk Names ./images/react.png 23.5 KiB [emitted] bundle.js 336 KiB 0 [emitted] [big] main index.html 221 bytes [emitted] main.css 5.63 KiB 0 [emitted] main ← ここ 中略 ...
変更後の方がCSSファイルのサイズが小さくなる。
ESLintとPrettierを導入する
構文解析を実装するため、ESLintとPrettierを使用する。
実装
exlint
とprettier
とその他必要なプラグインをインストールする。
$ npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier eslint-plugin-prettier eslint-config-prettier
プロジェクトルートに.eslintrc
を作成する。
{ "parser": "@typescript-eslint/parser", "extends": [ "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "prettier/@typescript-eslint" ], "rules": { "prettier/prettier": [ "error", { "singleQuote": true, "semi": true, "no-var-requires": true } ] } }
package.json
にスクリプトを追加する。
{ // 中略 ... "scripts": { // 中略 ... "lint": "eslint --fix --ext .tsx,.ts ./src", "type-check": "tsc" }, // 中略 ... }
今回作成したものは こちら