環境構築:webpackを拡張

2020-03-06 21:25

まだまだ環境構築は続く・・・か。口癖になりそう・・・

昨日インストールしたwebpackを自分の環境に併せて拡張していきます。

ディレクトリ構造

自分の開発環境のディレクトリ構造は大体下記の感じです。

. # ドキュメント・ルート
└─ nananomae.xyz # バーチャルホストに設定したドキュメント・ルート
    ├─ dev
    │  ├─ js
    │  │  └─ # JavaScriptファイル群
    │  └─ scss
    │     └─ # SCSSファイル群
    ├─ node_modules
    │  └─ # webpackが使用するモジュール群
    ├─ package.json
    ├─ public
    │  ├─ index.html
    │  └─ assets
    │     ├─ js
    │     │  └─ # 出力されるJavaScript群
    │     └─ css
    │        └─ # 出力されるCSS群
    └─ webpack.config.js

実行環境

webpack.config.jsを編集

上記した通りの構造で開発を進めていくにあたって、webpack.config.jsを編集します。

重要なのは、エントリポイントを複数持つということです。

webpack.config.js
// output.pathに絶対パスを指定する必要があるため、pathモジュールを読み込む const path = require('path'); module.exports = { entry: { index: './dev/js/index.js', blog: './dev/js/blog.js', ... }, output: { path: path.join( __dirname, 'public/assets/js' ), filename: '[name].js' } };

entry

エントリポイントとは、モジュール間の依存関係の解析を開始するポイントのこと。

output

出力するパスやファイル名を指定する。
filename:の値[name]はエントリポイントで指定したオブジェクトのキーになります。

package.jsonを編集

$ webpackコマンドを実行する際にモードを切り替えれるように設定します。

package.json
"scripts": { "test": "echo "Error: no test specified" && exit 1", - "build:dev": "webpack --mode=development", + "build": "webpack --mode=production", + "build:dev": "webpack --mode=development --watch" },

$ npm run buildコマンドは公開モードとして実行し、$ npm run build:devコマンドは開発モードとして実行し、ターミナルを抜けるまで関連するファイルが変更されるたびに$ webpackコマンドが実行されるようにします。

Loaderを導入

Babel Loader

ECMAScript 2015+を使えるようにするためBabel Loaderを下記のコマンドで必要なパッケージをインストールします。

$ npm install babel-loader @babel/core @babel/preset-env --save-dev

+ @babel/core@7.8.7
+ babel-loader@8.0.6
+ @babel/preset-env@7.8.7
added 126 packages from 40 contributors and audited 7137 packages in 6.675s

無事にインストールが完了したらwebpack.config.jsBabel Loaderの設定を追加します。

webpack.conig.js
... // ローダーの設定 module: { rules: [ { test: /¥.js$/, exclude: /node_modules/, use: [ loader: 'babel-loader', options: { presets: [ '@babel/preset-env' ] } ] }, ] }

上記の設定で、$ webpackコマンドを実行すれば、ECMSScript2015+で書かれたJavaScriptをどのブラウザでも動作するように変換してくれます。

Sass Loader

中間言語Sassを使えるようにするためSass Loaderを下記のコマンドでインストールします。

$ npm install sass-loader sass style-loader css-loader --save-dev

+ css-loader@3.4.2
+ sass-loader@8.0.2
+ style-loader@1.1.3
+ sass@1.26.2
added 22 packages from 51 contributors and audited 9446 packages in 3.594s

無事にインストールが完了したらwebpack.config.jsSass Loaderの設定を追加します。

webpack.conig.js
... // ローダーの設定 module: { rules: [ ... { test: /¥.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { url: false, importLoaders: 2 } }, { loader: 'sass-loader', options: { sourceMap: true, } } ] }, ] }

上記の設定で.scssファイルに対して、use配列で指定したLoaderが後ろから順番に適用されます。

Loaderを使用してSassを読み込むには、エントリポイント内でimport文で下記のように記述します。

index.js
import '../scss/style.scss'; ...

ただ、この状態で$ webpackコマンドを実行しても、スタイルシートのベンダープレフィックスは付与されていません。

PostCSS Loader

AndroidやIE 11等への対応を考えると、ベンだープレフィックスは必須です。webpack単体で弁だープレフィックスを付与する機能はないため、PostCSS Loaderを下記のコマンドでインストールします。

$ npm install postcss-loader autoprefixer --save-dev

+ autoprefixer@9.7.4
+ postcss-loader@3.0.0
added 20 packages from 22 contributors and audited 9545 packages in 3.961s

無事にインストールが完了したらwebpack.config.jsPostCSS Loaderの設定を追加します。

webpack.conig.js
... devtool: "source-map", // ローダーの設定 module: { rules: [ ... { test: /¥.scss$/, use: [ ... { loader: 'postcss-loader', options: { sourceMap: true, plugins: [ require('autoprefixer')({}) ] } }, ... ] }, ] }

上記の設定で、CSSにベンダープレフィックスが付与されるようになります。

ただ、この状態で$ webpackコマンドを実行しても、出力されるファイルは.jsファイルのみです。

Pluginを導入

MiniCssExtractPlugin

次に、出力されるファイルは.jsファイルと.cssファイルに分割したいので、MiniCssExtractPluginを下記コマンドでインストールします。

$ npm install mini-css-extract-plugin --save-dev

+ mini-css-extract-plugin@0.9.0
added 7 packages from 3 contributors and audited 9472 packages in 3.221s

無事にインストールが完了したらwebpack.config.jsMiniCssExtractPluginの設定を追加/置き換えます。

webpack.conig.js
... const MiniCssExtractPlugin = require('mini-css-extract-plugin'); ... // ローダーの設定 module: { rules: [ ... { test: /¥.(sa|sc|c)ss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { url: false, importLoaders: 2 } }, { loader: 'postcss-loader', options: { sourceMap: true, plugins: [ require('autoprefixer')({}) ] } }, { loader: 'sass-loader', options: { sourceMap: true, } } ] }, ] }, plugins: [ new MiniCssExtractPlugin({ filename: '../css/styles.css' }) ]

上記の設定で.jsファイルと.cssファイルを別々に出力できるようになりました。

Vueの導入

Vue.jsの導入は別記事「Instagramの写真埋め込みスクリプトをVueにしてみました。」で説明済みなのでそちらを参考に。