はじめに
webpackの名前位しか知らない状態から、以下やりたかったことができる状態にできたため、webpackの設定方法等散らばっていた情報をざっくり本記事にまとめる。
- 自身で作成したscss/tsファイルをそれぞれ1ファイル(css/js)にまとめて(バンドルして)、別のフォルダに配置
- tsファイル:自動フォーマット → jsに変換かつ es5にトランスパイル → bundle.js生成/配置
- scss/cssファイル:scssをcssに変換 → style.css生成/配置
- htmlファイル:htmlも一緒に配置
できたもの をgithubに置いているため必要あればご参照ください
※諸事情により今回はフレームワークやライブラリを使用しないため対象外
webpack 導入
npm使用
npm init -y
npm i -D webpack webpack-cli
webpack 実行(小規模サンプル)
例:app.js と user.js をまとめて dist 下に bundle.js として配置
- 実行コマンド ※面倒なら PATH を通す
.\node_modules\.bin\webpack
- webpack.config.js 設定例
// output.pathに絶対パスを指定する必要
const path = require("path");
module.exports = {
// モードの設定
mode: "development",
// エントリーポイントの設定
entry: "./src/js/app.js",
// 出力の設定
output: {
// 出力ファイル名
filename: "bundle.js",
// 出力先パス(絶対パス要)
path: path.join(__dirname, "dist/js"),
},
};
- フォルダ構成
.
├─dist
│ │ index.html
│ │
│ └─js
│ bundle.js
│
└─src
└─js
│ app.js
│
└─model
user.js
- app.js
import getUser from "./model/user";
function component() {
const element = document.createElement("div");
const user = getUser();
element.innerHTML = ["Hello", "webpack", user].join(" ");
return element;
}
document.body.appendChild(component());
- user.js
export default function getUser() {
return "user";
}
webpack.config.js
webpackの設定ファイル。自作する必要がある
module.exports = {
// 中身の主な設定項目は以下参照
};
設定項目と指定の仕方を簡単に以下にまとめる。
mode モード指定
mode: "development"; // "production" / "none"
entry エントリポイント指定
バンドル対象のメインとするファイル
・単一指定
entry: "./src/index.js",
// ↓ と解釈される
// entry : {
// main: "./src/index.js"
// }
・複数指定も可能
const { join } = require("path")
entry: {
app1: join(__dirname, "src/app1/index.js"),
app2: join(__dirname, "src/app2/index.js"),
app3: join(__dirname, "src/app3/index.js"),
}
devtool ソースマップ設定
ソースマップの追加方法等を指定
devtool: "source-map",
output バンドルファイル設定
設定項目
- filename : 出力ファイル名
- path : 出力ディレクトリ(絶対パス)
entry: "./src/index.js",
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
},
entry: "./src/index.js",
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
// → main.jsが出力される
entry: "./src/index.js",
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
// → app.jsが出力される
externals バンドル対象から除外
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
※必要なら、ライブラリをバンドル対象から外して html に直指定
module.rules モジュール適用
設定項目
- test : 適用対象にするファイル
- use : (インストールした)モジュール適用。※下から上の順番に適用される。
以下、モジュールごとの設定例をまとめる。
JavaScript
babel(es5にトランスパイル)
npm install -D babel-loader @babel/core @babel/preset-env
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", {"modules": false}],
},
},
],
},
],
},
ESlint(JS用静的検証ツール)
※JSに対するESlintは非検証。
npm install -D eslint eslint-loader
{
// enforce: 'pre'を指定することによって
// enforce: 'pre'がついていないローダーより早く処理が実行される
// 今回はbabel-loaderで変換する前にコードを検証したいため、指定が必要
enforce: 'pre',
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader'
}
TypeScript
TypeScript 使用には設定ファイル(tsconfig.json)作成要。設定項目等は以下見れば良さそう
Typescript の tsconfig.json の簡単作成方法と設定について
- tsconfig.json 簡易例
{
"compilerOptions": {
"sourceMap": true,
"target": "es5", // TSはECMAScript 5に変換
"module": "es2015" // TSのモジュールはES Modulesとして出力
}
}
awesome-typescript-loader
npm i -D typescript awesome-typescript-loader
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: "awesome-typescript-loader",
},
];
},
resolve: {
// 拡張子を配列で指定
extensions: [".ts", ".tsx", ".js"],
},
ts-loader
※ts-loader より awesome-typescript-loader の方が速いとか
npm i -D typescript ts-loader
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: "ts-loader",
},
],
},
resolve: {
// 拡張子を配列で指定
extensions: [".ts", ".js"],
},
TSLint(TS用静的検証ツール)非推奨
npm i -D tslint tslint-loader
module: {
rules: [
{
enforce: "pre",
test: /\.tsx?$/,
use: [
{
loader: "tslint-loader",
options: {
typeCheck: true,
fix: true,
},
},
],
},
];
}
ESLint
TypeScriptでもESLintの使用推奨
npm install -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier eslint-config-prettier eslint-plugin-prettier
webpackでの設定は、tslintとほぼ同じなため割愛
eslintの設定は .eslintrc.jsonに記述(以下サンプル)
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"prettier/@typescript-eslint"
],
"plugins": [
"@typescript-eslint",
"prettier"
],
"env": {
"browser": true,
"node": true,
"es6": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"project": "./tsconfig.json"
},
"rules": {
"prettier/prettier": [
"error",
{
/* format settings */
"singleQuote": true,
"semi": true,
/* lint check settings */
"max-len": [
"warning",
{
"code": 100,
"ignoreUrls": true
}
],
"quotes": [
"warning",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": false
}
]
}
],
/* lint ignore settings */
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/ban-types": 0
}
}
・ESLint+Pritter参考記事
- 脱TSLintして、ESLint TypeScript Plugin に移行する
- Prettierことはじめ
Sass/CSS
scssファイルをjsにバンドルする流れ
Sass/CSS を JS にバンドル
npm i -D sass-loader sass style-loader css-loader
・style-loader : 動的に link タグに出力
・css-loader : css を JS にバンドル。css の url()や@import 文は js の require()に変換
・sass-loader : Sassをcssに変換する
※js に使用する css を import する必要あり
// import 文を使ってstyle.cssファイルを読み込む。
import "./style.css";
- webpack.config.js
module: {
rules: [
// Sassファイルの読み込みとコンパイル
{
test: /\.scss/, // 対象となるファイル名
// ローダー名指定
use: [
"style-loader",
// CSSをバンドルする機能
{
loader: "css-loader",
options: {
// CSS内のurl()メソッドを取り込むか否か
url: false,
// ソースマップの利用有無
sourceMap: true,
// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader
importLoaders: 2,
},
},
// Sassをバンドルするための機能
{
loader: "sass-loader",
options: {
// ソースマップの利用有無
sourceMap: true,
},
},
],
},
];
}
url-loader (全画像バンドル) 使用時
module: {
rules: [
{
test: /\.scss/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
// 要true
url: true,
sourceMap: true,
importLoaders: 2,
},
},
{
loader: "sass-loader",
options: {
sourceMap: true,
},
},
],
},
{
// 対象となるファイルの拡張子
test: /\.(gif|png|jpg|eot|wof|woff|woff2|ttf|svg)$/,
// 画像をBase64として取り込む
loader: "url-loader",
},
];
}
※一部の画像をバンドルしたくない場合 (url-loader で limit)
※画像をバンドルせずそのまま配置したい場合 (file-loader)
ベンダープレフィックス自動付与したい場合
・ postcss-loader : css でネストした書き方をプレーンな css にする
・ css-loader と sass-loader の間に追加する
module: {
rules: [
{
test: /\.scss$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')({
//browsers: ["last 2 versions", "> 1%", "ie >= 10"],
grid: true,
}),
]
}
},
{
loader: 'sass-loader',
options: {
sassOptions: {
outputStyle: 'expanded',
},
},
},
]
},
]
},
※package.json or .browserslistrc に autoprefixer / babel 等を使ってコンパイルするときに対応させるブラウザを指定
{
"browserslist": ["last 2 version", "> 1%", "ie >= 10"]
}
plugins プラグイン適用
CSS を JS と分ける (MiniCssExtractPlugin)
- MiniCssExtractPlugin
- CSS のバンドルを分ける(デフォルトは js に css もバンドルされる)
- バンドルした JS から 任意のテキストを 別ファイルに出力できる
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
plugins: [
new MiniCssExtractPlugin({
filename: 'bundle.css', // 出力ファイル名
path: path.join(__dirname, 'dist'), // 出力先フォルダ
})
],
- css + mini-css-extract-plugin の場合
module: {
rules: [
{
test: /\.css$/,
use: [
// CSSファイルを書き出すオプションを有効にする
{
loader: MiniCssExtractPlugin.loader,
},
// CSSを読み込む
'css-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css', // 出力ファイル名
}),
],
- sass + mini-css-extract-plugin の場合
module: {
rules: [
{
test: /\.scss/, // 対象となるファイルの拡張子
use:
[
// CSSファイルを書き出すオプションを有効にする
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
url: false,
sourceMap: true,
// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader
importLoaders: 2,
},
},
{
loader: 'sass-loader',
options: {
// ソースマップの利用有無
sourceMap: true,
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css', // 出力ファイル名
}),
],
HTML も コンパイルして配置 (HtmlWebpackPlugin)
htmlファイルに、<script src="bundle.js">
や<link href="style.css" rel="stylesheet">
等を自動追加した上で、出力先フォルダに配置できるみたい
npm i -D html-webpack-plugin html-loader
module: {
loaders: [
{
test: /\.html$/,
loader: "html-loader"
}
]
},
plugins: [
// index
new HtmlWebpackPlugin({
template: "./html/index.html"
}),
// その他
new HtmlWebpackPlugin({
filename: "admin.html",
template: "./html/admin.html"
})
]
webpack モード指定実行
- package.json に以下指定
{
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production",
"watch": "webpack --mode development --watch --color --progress"
},
:
}
- 実行コマンド
npm run dev
npm run build
npm run watch
- webpack.config.js
※development モードの時だけソースマップを入れるようにすることでデバッグ等で原因箇所を追いやすくする
module.exports = (env, argv) => {
const isDevMode = argv.mode === "development";
return {
mode: argv.mode,
devtool: isDevMode ? "source-map" : "none",
// 設定内容省略
};
};
TypeScript フォーマッター設定 (TSLint + Prettier)
npm i -D prettier tslint tslint-loader tslint-plugin-prettier tslint-config-standard tslint-config-prettier
・tslint-config-standard : JavaScript Standard Style を使用する
・tslint-plugin-prettier : TSLint を Prettier と連携する
・tslint-config-prettier : TSLint と Prettier のルール衝突回避(Prettier のルール優先)
- tslint.json
{
"rulesDirectory": ["tslint-plugin-prettier"],
"extends": ["tslint-config-standard", "tslint-config-prettier"],
"rules": {
"prettier": [
true,
{
"singleQuote": false,
"semi": true
}
]
}
}
- webpack.config.js の内容
module: {
rules: [
{
enforce: "pre",
test: /\.tsx?$/,
use: [
{
loader: "tslint-loader",
options: {
typeCheck: true,
fix: true,
},
},
],
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: "awesome-typescript-loader",
},
{
enforce: "pre",
test: /\.js$/,
use: "source-map-loader",
},
];
}
TSLint と Prettier の衝突している設定確認したい場合
- 実行コマンド
npm run tslint-check
- package.json
{
"scripts": {
"tslint-check": "tslint-config-prettier-check ./tslint.json"
}
}
※ tsconfig.json に以下がないと、エラー「TS2307: Cannot find module 'source-map'.」が起きる
{
"compilerOptions": {
"moduleResolution": "node"
}
}
TSLint + Prettier 情報元
詳細以下に記載あったため、必要あればご参照されたし(情報元に感謝を)
TypeScript + TSLint + Prettier + Webpack 環境を作成したときのメモ
TSLint を使う TypeScript プロジェクトにコードフォーマッタ Prettier を導入する
できたもの
- srcフォルダ下は自身で作成したファイル群
- webpack実行(
npm run dev
ornpm run build
)でdistフォルダ下のファイル自動生成して配置される- tsファイル:自動フォーマット → jsに変換かつ es5にトランスパイル → bundle.js生成/配置
- scss/cssファイル:scssをcssに変換 → style.css生成/配置
- htmlファイル:
<script src="bundle.js">
,<link href="style.css">
が追加された状態のindex.html生成/配置
.
├─dist
| bundle.js
| index.html
| style.css
└─src
│ index.html
│
├─css
│ │ style.scss
│ │
│ ├─foundation
│ │ normalize.css
│ │
│ ├─layout
│ layout.scss
│
└─ts
│ app.ts
│
├─model
user.ts
参考サイト一覧
webpack の基本だけどハマりやすい entry の設定と[name]
Webpack 4 + Babel + Sass 環境を構築
最新版で学ぶ webpack 4 入門 JavaScript のモジュールバンドラ
TypeScript+webpack 4 の環境構築まとめ(React, Vue.js, Three.js のサンプル付き)