Web制作向けwebpack
JavaScriptのBundle、TypeScriptのBundleとTranspile、CSSやSCSSのBundleとベンダープレフィックスの追加、画像の圧縮、Pugのコンパイル、JavaScriptとCSSのLint、ソースマップの出力などを行います。
ファイル構成
website
├ src
│ ├ pug
│ │ ├ index.pug
│ │ ├ sub.pug
│ │ ├ _include
│ │ └ _included.pug
│ │
│ ├ img
│ │ ├ img.jpg
│ │ ├ img.png
│ │ ├ img.svg
│ │ └ img.gif
│ │
│ ├ css
│ │ ├ style.css
│ │ └ sub.css
│ │
│ ├ scss
│ │ ├ style.scss
│ │ └ sub.scss
│ │
│ ├ ts
│ │ └ sub.ts
│ │
│ ├ js
│ │ └ sub.js
│ │
│ ├ index.js
│ └ index.ts
│
├ package.json
├ package-lock.json
│
├.gitignore
│
├ tsconfig.json
│
├ .babelrc
│
├ .browserslistrc
│
├ postcss.config.js
│
├ .eslintrc.json
├ .eslintignore
│
├ .prettierrc.json
├ .prettierignore
│
├ .stylelintrc.json
└ .stylelintignore
webpack使用の準備
package.jsonの作成
npm init -y
webpackのインストール
npm i -D webpack webpack-cli
パッケージ | 内容 |
---|---|
webpack | webpack本体 |
webpack-cli | webpackのコマンドラインツール |
package.jsonの編集
package.jsonにビルドコマンドを追記
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production",
"watch": "webpack --mode development --watch"
}
JavaScriptファイルのバンドル
webpack.config.jsの作成
webpackの設定ファイルwebpack.config.jsを作成します。
const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
}
};
バンドルするJavaScriptファイルの準備
index.jsの作成
webpackを使うにはエントリーポイントになるjsファイルが必要なので最初にindex.jsを作成します。
import { hello } from "./js/sub";
console.log("JavaScript 変換成功");
hello();
sub.jsの作成
バンドルできているか確認用に、importするjsファイルも作成します。
export function hello() {
console.log("JavaScript import成功");
}
JavaScrptを読み込むHTML(動作確認用)の準備
バンドルして生成したmain.jsを読み込む動作確認用のHTMLを作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>トップページ</title>
<!-- defer対応ブラウザの時はこちらを使う-->
<!-- <script src="../dist/js/main.js" defer></script> -->
</head>
<body>
<!-- defer非対応ブラウザの時はこちらを使う-->
<script src="../dist/js/main.js"></script>
</body>
</html>
ビルド
npm run build
JavaScriptのTranspile
旧ブラウザに対応する必要がある場合、Babelを使ってJavaScriptのバージョンを下げます。
IE11対応
Babelのインストール
npm i -D babel-loader @babel/core @babel/preset-env
パッケージ | 内容 |
---|---|
babel-loader | webpackでBabelを使えるようにする |
@babel/core | Babel本体 |
@babel/preset-env | 指定したブラウザ環境で動作するように変換するプラグイン |
Babelの設定ファイルを作成
{
"presets": ["@babel/preset-env"]
}
.browserslistrcの準備
Transpileターゲットのブラウザを指定します。
defaults
webpack.config.jsの変更
jsファイルをbabelに渡します。
const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.js"
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
//追加
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
Transpileの動作確認
今回はPolyfillの追加は扱いませんので、with IE(JavaScriptのIE11対応)を参照してください。
index.jsの変更
アロー関数でをTranspileして、IE11で動作確認してみます。
import { hello } from "./js/sub";
console.log("JavaScript 変換成功");
hello();
//追加
window.addEventListener("load", () => {
console.log("IE11で表示されたらJavaScript Transpile成功");
});
ビルド
npm run build
IE11で動作確認
IE11でsrc/index.htmlを開き、「Transpile成功」が表示されればTranspileが出来ていることが確認できました。
TypeScriptファイルのコンパイル、バンドル
今回はPolyfillの追加は扱いませんので、with IE(JavaScriptのIE11対応)を参照してください。
TypeScriptのインストール
npm i -D typescript ts-loader
パッケージ | 内容 |
---|---|
typescript | TypeScript本体 |
ts-loader | BabelでTypeScriptを読み込めるようにする |
webpack.config.jsの変更
tsファイルをts-loaderで読み込む設定を追加します。
const path = require("path");
module.exports = {
mode: "production",
//エントリーポイントをsrc/index.tsに変更
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
//追加
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
],
},
//追加 import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
tsconfig.jsonの作成
プロジェクトルートにTyppeScriptの設定ファイルのtsconfig.jsonを作成します。
{
"compilerOptions": {
"module": "commonjs",//生成するJSモジュールの形式
"target": "es5",//生成するJSのバージョン
"noImplicitAny": false,//trueの場合、暗黙的なany型を許容しない
},
"exclude": ["node_modules"] //node_modulesフォルダは除外
}
設定はこちらを参照してください。
https://www.typescriptlang.org/ja/tsconfig
TypeScriptファイルの作成
index.tsの作成
import { hello } from "./ts/sub";
console.log("TypeScript 変換成功");
hello();
window.addEventListener("load", () => {
console.log("IE11で表示されたらTypeScript Transpile成功");
});
sub.tsの作成
export function hello() {
console.log("TypeScript import成功");
}
ビルド
npm run build
CSSファイルのバンドル
npm i -D css-loader style-loader mini-css-extract-plugin
パッケージ | 内容 |
---|---|
css-loader | cssを読み込む |
style-loader | スタイルを<style> 要素としてページに反映させる |
mini-css-extract-plugin | CSSをJSにバンドルせず、別ファイルにわける |
変換するCSSファイルの準備
index.tsの変更
index.tsからcssを読み込みます。
import { hello } from "./ts/sub";
import "./css/style.css";
console.log("TypeScript 変換成功");
hello();
window.addEventListener("load", () => {
console.log("IE11で表示されたらTypeScript Transpile成功");
});
style.cssの作成
@import url("sub.css");
.example {
display: flex;
color: black;
width: 100%;
background-color: red;
}
sub.cssの作成
importしたcssがバンドルされるか確認用のcssを作ります。
body {
background-color: green;
}
webpack.config.jsの変更
背景画像などをurlで指定する場合に、エラーにならないように url: falseを指定します。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
//追加
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
],
},
],
},
//追加
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
src/index.htmlの変更
バンドルしたdist/style.cssを読み込みます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>トップページ</title>
<!-- 追加 CSSファイルの読み込み -->
<link rel="stylesheet" href="../dist/css/style.css">
<!-- defer対応ブラウザの時はこちらを使う-->
<!-- <script src="../dist/js/main.js" defer></script> -->
</head>
<body>
<!-- defer非対応ブラウザの時はこちらを使う-->
<script src="../dist/js/main.js"></script>
</body>
</html>
ビルド
npm run build
SASSファイルのコンパイル、バンドル
パッケージのインストール
npm i -D sass-loader node-sass
パッケージ | 内容 |
---|---|
sass-loader | webpackでSASSを読み込めるようにする |
node-sass | SASSを使えるようにする |
index.tsの変更
index.jsからscssを読み込むように変更
import { hello } from "./ts/sub";
//CSSからSCSSに変更
//import "./css/style.css";
import "./scss/style.scss";
console.log("TypeScript 変換成功");
hello();
window.addEventListener("load", () => {
console.log("IE11で表示されたらTypeScript Transpile成功");
});
変換するscssの準備
@import "./sub.scss";
.example {
display: flex;
color: black;
width: 100%;
background-color: red;
}
importしたSCSSがバンドルできるか確認用のSCSS
body {
background-color: green;
}
webpack.config.jsの変更
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
ビルド
npm run build
PostCSSの使用
パッケージのインストール
npm i -D postcss postcss-loader
パッケージ | 内容 |
---|---|
postcss | PostCSS本体 |
postcss-loader | webpackでPostCSSを使えるようにする |
webpack.config.jsの変更
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
//追加
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
//追加
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
CSSのプロパティにベンダープレフィックスを付ける
パッケージのインストール
npm i -D autoprefixer
postcss.config.jsファイルの作成
post-cssの設定ファイル内でautoprefixerを指定します。
AutoprefixerでIE 11対応を行うために、grid: trueを指定してみます。
module.exports = {
plugins: [
require("autoprefixer")({ grid: true })
]
};
対象ブラウザの指定
作成済みであれば不要です。
Babelの項目で.browswerslistrcを作成していないときは、新規に作成します。
ie 11
CSSのminify
devでビルドしたときもminifyします。
不要無い場合は不要です。
パッケージのインストール
npm i -D cssnano
postcss.config.jsファイルの変更
post-cssの設定ファイル内でcssnanoを追加します。
module.exports = {
plugins: [
require("autoprefixer")({ grid: true }),
require("cssnano")]
};
プロパティのソート
Stylelintでソートする場合は不要です。
パッケージのインストール
npm i -D postcss-sorting
postcss.config.jsファイルの変更
post-cssの設定ファイル内でpostcss-sortingを追加
module.exports = {
plugins: [
require("autoprefixer")({ grid: true }),
require("cssnano"),
require("postcss-sorting")({
"properties-order": ["margin", "padding", "border", "background"]
})
]
};
画像を圧縮する
パッケージのインストール
npm i -D copy-webpack-plugin imagemin-webpack-plugin imagemin-pngquant imagemin-mozjpeg imagemin-gifsicle imagemin-svgo
パッケージ | 内容 |
---|---|
copy-webpack-plugin | ファイルのコピー |
imagemin-webpack-plugin | imageminプラグイン本体 |
imagemin-pngquant | pngを圧縮 |
imagemin-mozjpeg | jpgを圧縮 |
imagemin-gifsicle | gifを圧縮 |
imagemin-svgo | svgを圧縮 |
webpack.config.jsの変更
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" },
],
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80",
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256,
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true,
}),
],
}),
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
ビルド
npm run build
src/img内の画像ファイルと、src/favicon.pngとsrc/favicon.svgがdist配下にコピー、圧縮されます。
Pugのコンパイル
パッケージのインストール
npm i -D html-webpack-plugin pug-html-loader pug-loader
パッケージ | 内容 |
---|---|
html-webpack-plugin | HTMLファイルを出力 |
pug-html-loader | PugをHTMLに変換 |
pug-loader | webpackでPugを使えるようにする |
webpack.config.jsの変更
HTMLは1ファイルにバンドルしないので、個別に指定します。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false,
},
},
"postcss-loader",
"sass-loader",
],
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true,
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" },
],
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80",
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256,
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true,
}),
],
}),
//追加
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false, //minifyしない
}),
//追加
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false,
}),
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"],
},
};
pugファイルを作成
html(lang="ja")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title トップページ
//script(src="./js/main.js" defer)
body
p トップページ
a(href="sub.html") リンク
img(src="./img/img.jpg")
script(src="./js/main.js")
include ./_include/_included.pug
html(lang="ja")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title サブページ
//script(src="./js/main.js" defer)
body
p サブページ
script(src="./js/main.js")
p Include 成功
ビルド
npm run build
コードの整形、Lint
prettier
インストール
npm i -D prettier
prettierの設定ファイルの作成
{
"printWidth": 120,
"tabWidth": 2,
"singleQuote": false,
"trailingComma": "none",
"semi": true,
"parser": "typescript",
"endOfLine": "auto"
}
eslint
インストール
npm i -D eslint eslint-loader
.eslintrc.jsonの作成
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": {
"browser": true
},
"root": true,
"rules": {
"quotes": ["error", "single"] //クォーテーションががシングルのときエラー
}
}
設定はこちらを参照してください。
https://eslint.org/docs/rules/
webpack.config.jsの変更
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
//追加
{
enforce: "pre",
test: /\.(js|ts)$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, //autofixモードの有効化
failOnError: true //エラー検出時にビルド中断
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader",
"sass-loader"
]
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" }
]
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80"
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true
})
]
}),
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false //minifyしない
}),
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false
})
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"]
}
}
Lint
//lint
npx eslint src/index.ts
//lint+自動修正
npx eslint src/index.ts --fix
//複数ファイルをlint+自動修正
npx eslint src/**/*.ts --fix
PrettierとEslintの連携
インストール
npm i -D eslint-plugin-prettier eslint-config-prettier
パッケージ | 内容 |
---|---|
eslint-plugin-prettier | ESLint上でPrettierを動かす |
eslint-config-prettier | ESLintとPrettierで競合するルールを無効にする |
.eslintrc.jsonの変更
{
//追加
"extends": ["plugin:prettier/recommended"],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": {
"browser": true
},
"root": true,
"rules": {
"quotes": ["error", "single"]//クォーテーションががシングルのときエラー
}
}
stylelint
npm i -D stylelint stylelint-webpack-plugin stylelint-scss
パッケージ | 内容 |
---|---|
stylelint | Stylelint本体 |
stylelint-webpack-plugin | ビルド時にstylelintを実行 |
stylelint-scss | SCSS用のルールセット |
webpack.config.jsの変更
webpack.config.jsにローダーを登録します。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const StyleLintPlugin = require("stylelint-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
{
enforce: "pre",
test: /\.(js|ts)$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, //autofixモードの有効化
failOnError: true //エラー検出時にビルド中断
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader",
"sass-loader"
]
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" }
]
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80"
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true
})
]
}),
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false //minifyしない
}),
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false
}),
new StyleLintPlugin({
configFile: ".stylelintrc",
fix: true //自動修正可能なものは修正
})
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"]
}
}
.stylelintrcの作成
{
"plugins": ["stylelint-scss"],
"rules": {
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"color-no-invalid-hex": true
}
}
Lint
//lint
npx stylelint src/scss/style.scss
//lint+自動修正
npx stylelint src/scss/style.scss --fix
//複数ファイルをlint+自動修正
npx stylelint src/scss/**.scss --fix
PrettierとStylelintの連携
インストール
npm i -D stylelint-prettier stylelint-config-prettier
パッケージ | 内容 |
---|---|
stylelint-prettier | Stylelint上でPrettierを動かす |
stylelint-config-prettier | StylelintとPrettierで競合するルールを無効にする |
.stylelintrcの変更
{
"plugins": ["stylelint-scss"],
"extends": [
"stylelint-prettier/recommended",
"stylelint-config-prettier"
],
"rules": {
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"color-no-invalid-hex": true
}
}
コード整形の除外
.stylelintignore、.prettierignore、.eslintignoreで、除外したいファイルやフォルダを指定できます。
書き方は.gitignoreと同じです。
git commit前にLint
インストール
npm i -D lint-staged husky
パッケージ | 内容 |
---|---|
lint-staged | ステージングされたファイルにLint |
husky | gitコマンドをきっかけにして指定したコマンドを実行 |
package.jsonの変更
"husky": {
"hooks": {
"pre-commit": "lint-staged" // コミット前に以下のコマンドが実行される
}
},
"lint-staged": {
"*.{ts,tsx}": [
"tslint --fix",
"git add"
],
"*.{css,scss}": [
"stylelint --fix",
"git add"
]
}
distフォルダ内のファイルの削除
srcフォルダ内から削除したファイルから生成したファイルがdistフォルダに残ったままになっていると事故がおこりやすいので、ビルドする度に自動で削除するようにします。
インストール
npm i -D clean-webpack-plugin
webpack.config.jsの変更
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const StyleLintPlugin = require("stylelint-webpack-plugin");
//追加
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
{
enforce: "pre",
test: /\.(js|ts)$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, //autofixモードの有効化
failOnError: true //エラー検出時にビルド中断
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader",
"sass-loader"
]
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true
}
}
]
}
]
},
plugins: [
//追加
new CleanWebpackPlugin({ verbose: true }),
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" }
]
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80"
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true
})
]
}),
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false //minifyしない
}),
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false
}),
new StyleLintPlugin({
configFile: ".stylelintrc",
fix: true //自動修正可能なものは修正
})
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"]
}
};
ソースマップの生成
webpack.config.jsの変更
devtool: "source-map"を追加すると、ビルド時にJSとCSSにソースマップが生成されます。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const StyleLintPlugin = require("stylelint-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
{
enforce: "pre",
test: /\.(js|ts)$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, //autofixモードの有効化
failOnError: true //エラー検出時にビルド中断
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader",
"sass-loader"
]
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" }
]
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80"
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true
})
]
}),
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false //minifyしない
}),
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false
}),
new StyleLintPlugin({
configFile: ".stylelintrc",
fix: true //自動修正可能なものは修正
})
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"]
}
};
ビルド
npm run build
dist/css/style.css.mapとdist/js/main.js.mapが生成されます。
webpack-dev-server
インストール
npm i -D webpack-dev-server
webpack.config.jsの変更
devServerの設定を追加します。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const ImageminMozjpeg = require("imagemin-mozjpeg");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const StyleLintPlugin = require("stylelint-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "production",
//entry: "./src/index.js",
entry: "./src/index.ts",
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/main.js"
},
module: {
rules: [
{
enforce: "pre",
test: /\.(js|ts)$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true, //autofixモードの有効化
failOnError: true //エラー検出時にビルド中断
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
url: false
}
},
"postcss-loader",
"sass-loader"
]
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: true
}
}
]
}
]
},
//追加
devServer: {
contentBase: path.resolve(__dirname, "dist"),
open: true, //起動時にブラウザを開く
overlay: true //エラーをオーバーレイ表示
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new CopyPlugin({
patterns: [
{ from: "src/img", to: "img" },
{ from: "./src/favicon.png", to: "favicon.png" },
{ from: "./src/favicon.svg", to: "favicon.svg" }
]
}),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
pngquant: {
quality: "70-80"
},
gifsicle: {
interlaced: false,
optimizationLevel: 10,
colors: 256
},
svgo: {},
plugins: [
ImageminMozjpeg({
quality: 85,
progressive: true
})
]
}),
new HtmlWebpackPlugin({
template: "./src/pug/index.pug", //変換元のPugファイルの指定
filename: "index.html", //出力するHTMLのファイル名
inject: false, //バンドルしたjsファイルを読み込むscriptタグを自動出力しない
minify: false //minifyしない
}),
new HtmlWebpackPlugin({
template: "./src/pug/sub.pug",
filename: "sub.html",
inject: false,
minify: false
}),
new StyleLintPlugin({
configFile: ".stylelintrc",
fix: true //自動修正可能なものは修正
})
],
//import文で拡張子が.tsのファイルを解決する
resolve: {
extensions: [".ts", ".js", ".json"]
}
};
dev-serverの起動
//webpack4までの場合
npx webpack-dev-server
//webpack5以降の場合
npx webpack serve