###はじめに
この記事はwebpackの導入未経験の筆者がYoutube動画【CodeMafia】プログラミング学習 フロントエンド開発(webpack編)の内容を参考に(動画内webpack4)をwebpack5で実装したことをまとめています。動画内の方が細かい説明もたくさんして下さってますのでぜひ見てみてください。
Babel7に関してはBabel 7 の主な変更点まとめも参考にさせていただきました。
###開発環境
- Visual Studio Code: v1.56.2
- Node.js: 16.0.0
- Webpack: v5.38.1
- Babel: 7.14.5
- yarn
- npm
#Webpackを導入
プロジェクトフォルダを作成してエディターで開たらまずpackage.json初期化
yarn init -y
root直下にsrcフォルダを作成し、その中に
- index.html
- imagesフォルダ
- app.js
- sub.js
を作成する
次にwebpackを使えるようにする
yarn add webpack webpack webpack-cli --dev
root直下にwebpack.config.jsファイルを作成する
もしwebpack.example.jsというファイルで使用したい場合は下記のようにconfigオプションでフォルダを指定することで呼び出せる
yarn run webpack --mode development --config .\webpack.example.js
エントリーポイントの指定
module.exports = {
mode: "development",
devtool: false,
entry: "./src/app.js",
// エントリーポイントが複数ある場合
// お互い依存関係がないファイルは並列に指定
// entry: ["./src/app.js", "./src/sub.js"]
// エントリーポイントも出力先も別で設定したい場合(本記事ではこちらで進めていきます)
entry: {
app: "./src/app.js",
sub: "./src/sub.js",
}
}
出力先の指定
const path = require("path");
module.exports = {
mode: "development",
devtool: false,
entry: "./src/app.js",
output: {
path: path.resolve(__dirname, "public"), // __dirnameは現在のディレクトリのパス、第二引数は作成されるフォルダ名
filename: "bundle.js",
},
};
出力先が複数ある場合は[name]
という変数で指定する
(変数を指定するとentryで定義したkeyが割り振られる)
const path = require("path");
module.exports = {
mode: "development",
devtool: false,
entry: {
app: "./src/app.js",
sub: "./src/sub.js",
},
output: {
path: path.resolve(__dirname, "public"), // __dirnameは現在のディレクトリのパス
filename: "[name].js",
},
};
これでpublicフォルダにapp.jsとsube.jsを作成されます
#styleローダーの設定
loaderをインストール
yarn add --dev sass sass-loader css-loader style-loader
webpack.config.jsにloaderを設定
const path = require("path");
module.exports = {
mode: "development",
devtool: false,
entry: { app: "./src/app.js" },
output: {
path: path.resolve(__dirname, "public"),
filename: "[name].js",
},
module: { // ここから追加
rules: [
{
test: /\.scss$/,
use: [
"style-loader", // loaderの記載は下から読まれるので各順番に注意
"css-loader",
"sass-loader",
],
},
],
},
};
ベンダープレフィックスの設定
postcss-loader autoprefixerを入れる
yarn add postcss-loader autoprefixer --dev
root直下にpostcss.config.jsファイル作成して以下を記入
module.exports = {
plugins: [require("autoprefixer")],
};
webpack.config.jsにpostcss-loaderを追加
...省略
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
'postcss-loader', // 追加
"sass-loader",
],
...省略
#画像ローダー設定
file-loaderをインストール
yarn add file-loader --dev
webpack.config.jsにfile-loader設定
下記で使用している[name]の他に使える変数リスト
// ...省略
module: {
rules: [
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
// ここから
{
test: /\.(jpe?g|gif|png|svg|woff2?|ttf|ept)$/, // 使用する拡張子を全て記入。webfontも使用されている場合は記入する必要がある
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]", // [name]を変えることでpublicPahをhashにしたりできる
outputPath: "images",
publicPath: "images", // developer toolsのstyle などで表示されるurl
},
},
],
},
// ここまで
// ...省略
#Babel設定
babelをインストール
yarn add babel-loader @babel/core @babel/preset-env --dev
webpack.config.jsにbabel-loader設定
// ...省略
module: {
rules: [
// ここから
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/, // node_moduleは元からトランスパイルされているので除外
},
// ここまで
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
},
// ...省略
root直下に.babelrcファイル作成して以下を記入(jsで書く場合はbabelrcファイルは作成しない)
{
"presets": ["@babel/preset-env"]
}
.babelrcではなくjsファイルで書く場合(こっちの方が関数を使った複雑な設定ができる)
root直下にbabel.config.js作成
module.exports = (api) => {
api.cache(true); // 設定しておくと2回目以降キャッシュが走ってビルド時間短縮できる
return {
presets: [
[
"@babel/preset-env",
{
targets: [ // 対応させるブラウザの指定
"last 1 version", // 指定の仕方(https://github.com/browserslist/browserslist)
"> 1%",
"maintained node versions",
"not dead",
],
},
],
],
};
};
トランスパイルを行う際に古いブラウザが持っていない機能を補う必要があるため以下のモジュール追加
yarn add core-js@3 regenerator-runtime
上記のモジュールは直接importして使うとファイルサイズが大きくパフォーマンスが悪くなるのでbabel.config.jsで以下のように設定
module.exports = (api) => {
api.cache(true);
return {
presets: [
[
"@babel/preset-env",
{
targets: [
"last 1 version",
"> 1%",
"maintained node versions",
"not dead",
],
useBuiltIns: "usage", // 追加 regenerator-runtimeの必要な機能だけimportする
corejs: { version: 3, proposals: true }, // 追加
},
],
],
};
};
Eslint設定
loaderをインストール
(以下、説明のためスクラッチで書いていくが yarn run eslint --init
を使う方法もある)
yarn add eslint eslint-loader babel-eslint --dev
root直下に.eslintrc作成し以下を記入
{
"env": { // env設定ドキュメント(https://eslint.org/docs/user-guide/configuring/#specifying-environments)
"browser": true,
"es2017": true
},
"extends": "eslint:recommended", // recommendedはeslintがおすすめしているルールが自動で適用
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module" // es6で導入されたmodule単位で管理
// defaltではscript管理になっている
},
"globals": { // globalから使用されるpackageを記入
"jQuery": "readonly",
"$": "readonly"
},
"rules": {
// ここに記入したルールが優先される
// ESLintルールリスト(https://eslint.org/docs/rules/)
}
}
webpack.config.jsにloaderの設定
// ...省略
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
},
// ここから追加
{
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, // lintに引っかかったところを自動でルールの形に整形する
},
},
// ここまで
// ...省略
#Pluginを使う
###MiniCssExtractPluginを設定
MiniCssExtractPluginはjsファイルをバンドルする際にcssを分離して生成することで、変更がない場合はキャッシュを利用してくれる
MiniCssExtractPluginをinstall
yarn add mini-css-extract-plugin --dev
webpack.config.jsに追加
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 追加
module.exports = {
mode: "development",
devtool: false,
entry: {
app: "./src/app.js",
sub: "./src/sub.js",
},
output: {
path: path.resolve(__dirname, "public"),
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true,
},
},
{
test: /\.scss$/,
use: [
// "style-loader", <- 削除
MiniCssExtractPlugin.loader, // 追加
"css-loader",
"postcss-loader",
"sass-loader",
],
},
{
test: /\.(jpe?g|gif|png|svg|woff2?|ttf|ept)$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "images",
publicPath: "images",
},
},
],
},
],
},
// ここから追加
plugins: [
new MiniCssExtractPlugin({
filename: `[name].css`,
}),
],
// ここまで
};
###HtmlWebpackPluginを設定
HtmlWebpackPluginはindex.htmlに自動でscriptタグをインジェクトする
html-webpack-pluginをinstall
yarn add html-webpack-plugin --dev
webpack.config.jsに追加
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 追加
// ...省略
plugins: [
new MiniCssExtractPlugin({
filename: `[name].css`,
}),
// ここから追加
new HtmlWebpackPlugin({
template: "./src/index.html",
inject: "body",
}),
//ここまで
],
};
###HTML内の画像を抽出する
html内の画像もバンドルするためにhtml-loaderを設定する
html-loaderは先ほど設定したHtmlWebpackPluginがないと機能しません。
loaderをinstall
yarn add --dev html-loader
webpack.config.jsにhtml-loader追加
// ...省略
test: /\.(jpe?g|gif|png|svg|woff2?|ttf|ept)$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "images",
publicPath: "images",
},
},
],
},
// ここから追加
{
test: /\.html$/,
use: ["html-loader"],
},
// ここまで
],
// ...省略
webpack5設定②に続く