はじめに
フロントエンドエンジニアとして仕事をしているもののあまり触れる機会がないものの一つがWebpackではないでしょうか。
おおよそのケース、プロジェクトが始まるタイミングで定義されてしまっているためそんなに頻繁に扱う機会はない。
しかし稀にパッケージのバージョンアップや新しいディレクトリに作成したコードや画像などのアセットがビルドに含まれないなどのトラブルで見る必要が出てくることがあります。
そんな私もWebpack 4から5にバージョンアップをつい先日行いまして非常に苦労しました。
webpackの基礎的な内容を理解してきたるべき日に備えるそんな記事となっております。
webpack公式サイト
webpackは様々な環境で使うことができる便利なツールで今回の記事で全て書くのが難しいためReact、TypeScriptを使った環境については別の記事としてご紹介しています。
今回のゴール
簡単なHTML, JavaScript, CSSを書いてWebpackでバンドル(まとめる)し、ブラウザで正しく表示されることを確認します。
ファイルを一つずつ追加しながらWebpackで動作確認を行うようにしており、Webpackの設定方法の雰囲気が掴めるチュートリアルとなっております。
webpackとは
webpackは、モジュールバンドラというツールで、主にJavaScriptのコードやその他のリソース(CSS、画像、フォントなど)を1つのバンドルファイルにまとめるために使われます。
これにより、ウェブアプリケーションを効率的に配信できるようになります。
具体的には、Webpackは以下のことを行います:
-
モジュールバンドリング
複数のJavaScriptファイルを1つの大きなファイルや複数の小さなファイル(チャンク)にまとめます。これにより、複数のリソースを読み込む回数が減り、パフォーマンスが向上します。 -
トランスパイル
ES6+のコードやTypeScript、さらにはJSX(Reactで使われる)などを、ブラウザでサポートされている形式に変換します。 -
アセットの管理
画像、フォント、スタイルシートなどの非JavaScriptリソースも処理できます。これらは適切な形式に変換されたり、URLが自動で変更されたりします。 -
コード分割
アプリケーションの異なる部分(ページごとなど)を異なるファイルとして出力することができ、最初に読み込む必要のないコードは後から必要に応じて読み込まれます。 -
プラグインとローダー
Webpackではプラグインやローダーを使って、コードの最適化や、リソースの処理方法をカスタマイズすることができます。ローダーはファイルを変換するために使用され、プラグインはビルドのプロセスを拡張します。
最小構成でwebpackを始める
ということで早速webpackを使いながら少しずつwebpackの良さを理解していきましょう。
webpack-tutorial
というディレクトリを作成しNode.jsのプロジェクトとして初期化します。
npm init
途中いろいろ聞かれますがEnter
連打で問題ありません。
webpackのインストール
下記コマンドでwebpackをインストールします。
npm i -D webpack webpack-cli
CLIから使うのでwebpack-cli
も一緒にインストールしておきました。
サンプルのコードの準備
Javascriptのサンプルコードをsrc/index.js
として用意します。
function component(name) {
const element = document.createElement('div');
element.innerHTML = `Hello ${name}`
return element;
}
document.body.appendChild(component('World'));
続けてそれを読み込むHTMLファイルを作成しプロジェクトトップに保存します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>webpack tutorial</title>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>
作成したらindex.htmlファイルをブラウザで開いて、Hello World
と表示されることを確認します。
webpackでJavaScriptファイルのバンドル
サンプルのコードが用意できましたので早速webpackでバンドルしてみます。
npx webpack
すると新しくファイルが/dist/main.js
として作成されました。
ファイルを確認してみましょう。
整形前
document.body.appendChild(function(){const e=document.createElement("div");return e.innerHTML="Hello World",e}());
整形後
document.body.appendChild(
(function () {
const e = document.createElement('div');
return (e.innerHTML = 'Hello World'), e;
})()
);
サンプルのコードと書き方は違えど同じ処理のコードが生成されています。
それではこのコードが動くのか念のため確かめるべくHTMLファイルの読み込むjsファイルを変更して確認します。
/dist/index.html
と保存先のディレクトリをプロジェクトトップから変更した上で、jsファイルの読み込み先を修正。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>webpack tutorial</title>
</head>
<body>
- <script src="./src/index.js"></script>
+ <script src="./main.js"></script>
</body>
</html>
再びブラウザで確認します。
Hello World
と表示されてますのでwebpackでバンドルしたファイルが正常に動くことを確認できました。
ここまでwebpackに関する設定なく動きました。
webpack単体で扱う分には実はそれほど難しくない仕組みではあります。
しかし、これだけで実務で使っていくには厳しいかと思いますので少しずつwebpackを掘り下げていきます。
ファイルの変更検知
webpackにはファイルの変更を検知して自動的に再バンドルするwatch
モードがあります。
npx webpack --watch
こうしておくことでjsファイルを書き換えた際に再バンドルしブラウザでも変更内容がすぐ反映されます。
- document.body.appendChild(component('World'));
+ document.body.appendChild(component('Test'));
古いブラウザへの対応
Babelは、JavaScriptのコンパイラ(トランスパイラ)で、最新のJavaScriptコードを古いブラウザでも動作する形に変換するためのツールです。
主にモダンなJavaScript機能を使用したコードを、互換性のないブラウザ向けに変換するために使われます。
-
トランスパイル(変換)
- ES6+(ECMAScript 2015以降)の新しい構文や機能を、ES5(古いブラウザがサポートするバージョン)に変換します。
- 例: constやletをvarに変換、arrow functions(アロー関数)を通常の関数に変換。
-
Polyfillの提供
- 新しいJavaScript機能が古い環境で動作しない場合、Babelはcore-jsや@babel/polyfillを通じてその機能を再現するコードを追加できます。
- 例: PromiseやArray.includesなど。
-
ReactやTypeScriptのサポート
- JSX(Reactで使われる特殊な構文)を通常のJavaScriptに変換できます。
- TypeScriptコードもBabelを使ってJavaScriptに変換可能です(ただし型チェックは行いません)。
-
プラグインとプリセット
- Babelは拡張可能な仕組みを持ち、プラグインやプリセットを通じて変換内容をカスタマイズできます。
- プリセット: 一連のプラグインをまとめたもの(例: @babel/preset-env)。
- プラグイン: 特定の変換を担当するモジュール(例: @babel/plugin-transform-arrow-functions)。
Babel公式
先ほどのコードではconst
が使われておりこれはES6から対応している機能となります。
そのためES5までしか動かないブラウザのバージョンでは問題となります。
そこでBabelを使いES5へ変換を行います。
webpackによるバンドルももちろん行うためBabelとwebpackの連携も必要となってきます。
Babelの導入
下記のコマンドでBabel
をインストールします。
npm i -D @babel/core @babel/preset-env
@babel/preset-env
はES6 -> ES5に変換する際に必要となります。
.babelrc
ファイルをプロジェクト直下に作成し先ほどインストールしたプリセットを指定します。
{
"presets": ["@babel/preset-env"]
}
webpackとの連携
webpackではローダーと呼ばれるプログラムを利用して変換に関する設定を行なっていきます。
ES6 -> ES5に変換するローダーとしてbabel-loader
を使うためインストールします。
npm i -D babel-loader
webpackのコンフィグでローダーを設定します。
/** @type {import('webpack').Configuration} */
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
},
],
},
};
今回の設定では.js
ファイルに関してはbabel-loader
で変換を行います。
Babelの動作確認
設定完了しましたのでwebpack
でバンドルします。
npx webpack
すると今度は出力されたjsファイルがこれまでと異なっていることがわかります。
const
も使われなくなりました。
(() => {
var e;
document.body.appendChild((((e = document.createElement('div')).innerHTML = 'Hello '.concat('Test')), e));
})();
ES5の形式でjsファイルが作られることを確認でき古いブラウザでも動くようになりました。
CSSをバンドルする
jsファイルのバンドルと古いブラウザへの対応方法について見てきました。
次はCSSをwebpackで取り扱えるようにしていきます。
ローダーのインストール
JavaScriptコードの中でCSSをインポートし、それをHTMLの<style>タグとして適用する場合に2つのローダーが必要となります。
-
css-loader
CSSファイルをWebpackが認識してバンドルに含めます。 -
style-loader
CSSをHTMLの<style>タグに挿入します。
npm i -D style-loader css-loader
webpackにローダーの設定
2つのローダーを.css
ファイルの時に扱うよう設定します。
/** @type {import('webpack').Configuration} */
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
},
+ {
+ test: /\.css$/,
+ use: ["style-loader", "css-loader"],
+ },
],
},
};
配列でローダーを定義する場合、配列の最後尾から順に適用されます。
css-loader
-> style-loader
の順で動くこととなります。
サンプルコードの準備
CSSファイルを/src/styles.css
に作成します。
body {
padding: 40px;
color: blue;
}
JavaScriptファイルでCSSファイルを読み込みます。
+ import './styles.css'
動作確認
設定完了しましたのでwebpack
でバンドルします。
npx webpack
ブラウザで確認すると文字が青になっておりCSSが正しく適用されていることがわかります。
webpackのモード
これまでwebpackの実行時に警告が出ていました。
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
modeオプションが設定されていません。そのため、Webpackはこの値をproductionにフォールバックします。
developmentまたはproductionを設定することで、各環境に適したデフォルト設定を有効にできます。
これまではproduction
としてバンドルされていました。
webpack 5では3種類設定できるようです。
- development
- production
- none
試しにdevelopment
モードでwebpackを実行してみましょう。
npx webpack --mode=development
/dist/main.js
をみてみると先ほどとは違いコメントが書かれています。
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _styles_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./styles.css */ \"./src/styles.css\");\n\nfunction component(name) {\n var element = document.createElement('div');\n element.innerHTML = \"Hello \".concat(name);\n return element;\n}\ndocument.body.appendChild(component('Test'));\n\n//# sourceURL=webpack://webpack-tutorial/./src/index.js?");
index.jsのバンドル結果だというのがコメントから確認できます。
production
モードにはなかったコメントなどが入るようになり開発段階では役に立ちそうです。
さいごに
ここまでwebpackの基本的な使い方や設定方法についてご紹介しました。
webpackは非常に多機能で強力なツールですが、その分設定が少し複雑に感じることもあります。
しかし、少しずつ学んでいくことで、アプリケーションのパフォーマンス向上や開発効率を大きく改善することができます。
今回紹介した内容を参考に、自社のプロジェクトに必要な設定を追加し、webpackの力を存分に活用していきましょう。
おすすめの記事
React + TypeScriptの環境をWebpackでビルドする記事をご紹介します。
関連する技術ブログ
WebpackでReactとTypeScriptをセットアップするステップガイド
ReactとTypeScriptを使ったアプリケーション開発を、Webpackを使って効率的にセットアップする方法を詳しく解説します。バンドル環境の構築から、実際の開発まで役立つステップを紹介します。
shinagawa-web.com
React のリファクタリング完全ガイド:モジュール化・レンダリング最適化・設計パターン適用でコードを改善
フロントエンド開発において、可読性が低いコードやパフォーマンスの課題を抱えていませんか?本記事では、React を用いたフロントエンドのリファクタリング手法を具体的なコード例とともに解説します。命名規則の統一や関数分割による可読性向上、共通処理のモジュール化によるコードの整理、関心の分離に基づいたコンポーネント設計の最適化を実践。また、useMemo / useCallback / React.memo を活用したレンダリングの最適化、Promise.all や useQuery の適切な適用による非同期処理の最適化など、パフォーマンス改善にも焦点を当てます。さらに、クリーンアーキテクチャやリポジトリパターンの導入、TypeScript による型安全性の強化、依存関係の整理まで幅広くカバー。リファクタリングを計画的に進める方法も紹介し、スムーズな適用を支援します。より読みやすく、保守しやすいコードへと進化させるための実践的なアプローチをご紹介します。
shinagawa-web.com
Chakra UI・ShadCN・Material UIを活用したデザインシステムの構築と運用
デザインシステムの要件定義から適用ガイドラインの策定、UIコンポーネントの設計・実装、レスポンシブ対応、アクセシビリティ強化まで、幅広い観点で解説。Chakra UI・ShadCN・Material UIなどのUIフレームワークを活用しながら、カラーパレットやタイポグラフィの統一、コードスタイルの整備、開発者・デザイナー向けのドキュメント作成、プロトタイピング、ユーザビリティ向上のためのテスト戦略までを包括的に取り上げます。
shinagawa-web.com
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要なSaaSの乱立、開発工数の増加――これらの課題に悩んでいませんか?本サービスでは、クラウドコストの最適化、開発効率向上、技術選定の最適化 を通じて、単なるコスト削減ではなく、ROIを最大化する最適解 をご提案します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
開発生産性を最大化するための支援サービス
開発チームの生産性向上、コードの品質管理、インフラの最適化まで、様々な側面からサポートします。コードベースのリファクタリングから、テスト自動化、オンボーディング強化まで、プロジェクトの成功に必要なすべての支援を提供。御社の開発現場が効率的に機能するように、技術的な障害を取り除き、スムーズな開発を実現します。
shinagawa-web.com
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
Webアプリのセキュリティ強化支援
Webアプリの脆弱性対策からインフラのセキュリティ強化まで、包括的なセキュリティ支援を提供。OWASP Top 10対策、JWT認証の最適化、APIのアクセス制御、依存パッケージの監査、セキュアコーディングの標準化など、実践的なアプローチで開発現場の安全性を向上させます。
shinagawa-web.com
目次
お問い合わせ