blog

Webpack設定ファイルの基本を解説する

webpackは最新のアプリケーションのための静的モジュールパッカーです。...

Jul 15, 2020 · 11 min. read
シェア
**webpack**は、モダンなJavaScriptアプリケーションのための**静的モジュールパッカー**です。 webpackはアプリケーションを処理するとき、アプリケーションが必要とするすべてのモジュールを含む依存関係グラフ**を**再帰的に構築し、それらのすべてのモジュール**を1つまたは複数のバンドル**にパックします。

コンセプト

webpackは4つのコアコンセプトで構成されています:

  • エントリー
  • 出力
  • loader
  • プラグイン

エントリ

**** エントリーポイントは、webpackが内部の依存関係グラフを構築するための出発点としてどのモジュールを使用すべきかを示します。エントリーポイントに入ると、webpackはそのエントリーポイントがどのモジュールやライブラリに依存しているかを調べます**。**

webpack設定ファイルのentry属性で1つ以上のエントリファイルを設定できます。

webpack.config.js //デフォルトのwebpackパッケージングプロファイル
modules.export = {
 entry: './path/to/my/entry/file.js'
}

単一のポータルを設定します:

チャンクを形成し、バンドルファイルを出力するためのパッケージング。

設定は以下の方法で行います:

// 
modules.export = {
 entry: './path/to/my/entry/file.js'
}
// 
modules.export = {
 entry: {
 main:'./path/to/my/entry/file.js'
}
// 
modules.export = {
 entry: {
 app: './src/app.js',
 vendors: './src/vendors.js'
 }
};
//アプリケーションとサードパーティ・ライブラリのエントリーの分離

複数エントリーの設定方法:

1.配列:

すべてのファイルは最終的にチャンクを形成し、 バンドルファイルだけがエクスポートされます。

modules.export = {
 entry: ['./src/app.js','./src/vendors.js']
};

2.オブジェクト

複数のファイルがある場合は、複数のチャンクが形成され、複数のバンドルファイルが出力され、チャンクの名前がキーになります。

// 
modules.export = {
 entry: {
 pageOne: './src/pageOne/index.js',
 pageTwo: './src/pageTwo/index.js',
 pageThree: './src/pageThree/index.js'
 }
};
//3 独立して分離された依存関係グラフ

注意:1つのHTML文書につき1つのエントリーポイントしか使用されません。

終了

outputは**webpackがコンパイルしたファイルをどこに**出力する必要があるか、どのように名前を付けるかを**webpackに指示するものです。デフォルトは ./distディレクトリに出力されます。また、最終的にアプリケーションのコンパイル結果全体が指定した出力パスフォルダに出力されるように、outputで指定することもできます。

コンフィギュレーションで出力フィールドを指定することで、これらの処理を設定できます:

  • filename 出力ファイルに使用するファイル名。
  • ターゲット出力ディレクトリパスの絶対パス。
  • publicPath この設定は、プロジェクト内のすべてのリソースのベースパスを指定するのに役立ちます(すべてのリソースが導入する公開プレフィックスを定義するのに使用します)。
  • chunkFileName:  非エントリー・チャンクの名前
  • library: ライブラリ全体が外部に公開される変数名を定義します。

webpack.config.js

const path = require('path');
module.exports = {
 entry: './path/to/my/entry/file.js',
 output: {
 path: path.resolve(__dirname, 'dist'), //出力フォルダーのパスを指定する
 filename: 'my-first-webpack.bundle.js', //出力ファイル名を指定する
 publicPath: '/', //パブリック接頭辞を追加する
 chunkFileName: 'js/[name]_chunk.js',
 library: [name], //外部に公開する変数名。デフォルトはチャンク名となる。,
 libraryTarget: 'global' //上で定義した変数を与える方法は、変数がグローバルな
 //libraryTarget: 'commonjs' //デリゲートはcommonjs requireで導入できる。
 }
};

エントリーが複数設定されている場合

{
 entry: {
 app: './src/app.js',
 search: './src/search.js'
 },
 output: {
 filename: '[name].js',
 path: __dirname + '/dist'
 }
}
// ハードディスクに書き込む:./dist/app.js, ./dist/search.js

高度な使用法

//CDNとリソース・ハッシュを使った複雑な例
output: {
 path: "/home/proj/cdn/assets/[hash]",
 publicPath: "http://..com/assets/[hash]/"
}

loader

ローダーは**webpackが非JavaScriptファイル**を扱うことを可能にし、様々な種類のローダーを使用することで、あらゆる種類のファイルをwebpackが扱い認識できる有効なモジュールに変換し、webpackを通してパッケージ化することができます。

このステップで依存関係グラフを生成します。

基本的に、webpackローダーはあらゆる種類のファイルを受け取り、アプリケーションの依存関係グラフから直接参照できるモジュールに変換します。

ローダーの2つの属性

  • test属性:対応するローダーによって変換されるべきファイルを特定します

  • use属性:変換を実行するためにどのローダーを使うべきかを示します。

  • loader属性:単一のloaderで変換する場合

  • exclude 属性:特定のファイルを除外

  • include属性:特定のパスにあるファイルのみをチェックします。

  • enforce 属性: この属性は、同じファイルをチェックするルールが複数定義されている場合に、 ルールの実行順序を変更するために使用できます。 pre' の値は実行を優先し、'post' の値は実行を遅らせます。

  • option属性: ローダのパラメータ設定を設定します。url-loaderと同様に、option={limit:8*1024}を設定することで、8kb以下のファイルに対してbase64エンコーディングを使用するルールを表すことができます。

例: 次のルールは、require()/import ステートメントで '.txt' に解決されるパスを変換するために raw-loader を使用するルールを定義します。.css で終わるパスは css-loader を使用して変換され、.ts で終わるパスは ts-loader を使用して変換されます。

const path = require('path'); const config = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: /\.txt$/, loader: 'raw-loader', exclude: /node_modules/, //ノードを除外する_modules以下のモジュール include: resolve(_dirname, 'src'), //srcパス下のファイルだけをチェックする enforce: 'pre', //同じ種類のファイルをチェックする複数のルールを定義する場合、この属性を使って特定のルールの実行順序を変更できる。 }, { test: /\.css$/, use: ['style-loader','css-loader'] }, { test: /\.ts$/, use: 'ts-loader' }, { test: /\.(png|jpg|gif)$/, loader: 'url-loader', option:{ limit: 8*1024}} ] } }; module.exports = config;

注:ローダーはパスの連結をサポートしています。リソースにパイプラインを使用することも可能です。連鎖したloaderのセットは逆順に実行され、連鎖の最初のloaderは次のloaderに値を返し、最後のloaderはwebpackが期待するJavaScriptを返します。

loader内のuse配列は、右から左、下から上の順に実行され、前のloaderの戻り値が次のloaderに渡され実行が継続され、最後のloaderがwebpackに返されます。

例: sass-loader、css-loader、style-loader の順。

module.exports = {
 module: {
 rules: [
 {
 // SCSSファイルのサポートを追加する
 test: /\.scss/,
 // SCSS ファイルは、sass-loader、css-loader、style-loaderの順に処理される。
 use: [
 'style-loader',
 {
 loader:'css-loader',
 // 設定項目をcss-loaderに渡す
 options:{
 minimize:true, 
 }
 },
 'sass-loader'],
 },
 ]
 },
};

module.exports = {
 module: {
 rules: [
 {
 // CSSファイルのサポートを追加する
 test: /\.css/,
 // use配列内のローダーの実行順序:右から左へ、上から下へ、この順序で実行する。
 use: [
 'style-loader', //スタイル・タグを作成し、jsからスタイル・リソースをスタイル・タグに追加し、headに入れて効果を発揮させる。
 'css-loader' //cssファイルをjsモジュールに読み込む。
 ],
 },
 ]
 },
};

プラグイン

pluginsは主にwebpackの拡張機能で、ローダーが変換されたときに、変換されたモジュールの処理にプラグインを追加することができます

require() でプラグインを導入し、plugins 配列に追加します。ほとんどのプラグインはオプションでカスタマイズできます。また、プロファイル内で同じプラグインを異なる目的で複数回使用することもできます。その場合は、**new** 演算子を使用してインスタンスを作成する必要があります。

const HtmlWebpackPlugin = require('html-webpack-plugin'); // npmによるインストール
const webpack = require('webpack'); // 組み込みプラグインにアクセスする
const config = {
 module: {
 rules: [
 { test: /\.txt$/, use: 'raw-loader' }
 ]
 },
 plugins: [
 new HtmlWebpackPlugin({template: './src/index.html'}) 
 //HtmlWebpackPluginを使って出力バンドルをindexに出力する。.html 
 ]
};
module.exports = config;

モード

**modeパラメータを**に設定することで設定可能。

webpackの組み込みの最適化を適切なモードで有効にするために、開発または本番環境で使用します。

module.exports = {
 mode: 'production'
};

または、 CLI パラメータから以下を渡します。

webpack --mode=production

resolveモジュールの解析ルール

いくつかの属性があります:

  • alias: モジュールの導入を簡単にするために、import や require のエイリアスを作成します。長所:パスを省略できる、短所:パスを書くときにヒントがない

例: ファイルが長いパスを持つファイルにアクセスしたい場合、エイリアスを取ることができます。

webpac.config.js

//ディレクトリが
-src
 -utilities
 -utilities.js -templates
 -templates.js -js
 -index.js
 -css
 -index.css
Utilities: path.resolve(__dirname, 'src/utilities/'),
Templates: path.resolve(__dirname, 'src/templates/')
webpac.config.js
//-----start----//
var { resolve } = require('path');
module.exports = {
 //
 reslove:{
 alias: {
 $css: resolve(_dirname, 'src/css'), //src/cssパスのエイリアスを作成する手段,
 Utilities: path.resolve(__dirname, 'src/utilities/'),
 Utilities: path.resolve(__dirname, 'src/templates/') 
 }
 } 
}
//-----end-----//
index.js 
//-----start-----//
import '../css/index.css';
import '../utilities/utility';
import '../templates/templates';
//これらは次のように置き換えることができる。
import '$css/index.css'; //webpackはindex.htmlへのパスをエイリアス化する。
import 'Utilities/utility.js';import 'Utilities/templates.js';
  • extensions: ファイルパスが省略された場合のサフィックスを設定します。ファイル拡張子が省略されたパスは、 配列の左から右にある拡張子を補完するものとマッチします。デフォルト値は

    extensions: [".js", ".json"]
    

このオプションを使用すると、デフォルトの配列が上書きされ、webpack はデフォルトの拡張子を使用したモジュールの解析を試みなくなります。import SomeFile from "./somefile.ext"拡張子を使用してインポートされたモジュール、例えば、"*"を含む文字列を配列に含めなければ正しく解析されません。

module.exports = {
 reslove:{ alias: {
 $css: resolve(_dirname, 'src/css'), //src/cssパスのエイリアスを作成する。,
 Utilities: path.resolve(__dirname, 'src/utilities/'),
 Utilities: path.resolve(__dirname, 'src/templates/') 
 },
 //サフィックスのマッチを左から右に追加する。マッチが成功した場合、逆方向にはマッチしない。
 extensions: ['.js', 'json', '.jsx', '*']
 } }
  • modules: モジュールを解析するときに検索するディレクトリを webpack に指定します。デフォルトは

    modules:['node_modules']。

モジュール検索ディレクトリにディレクトリを追加したい場合は、このディレクトリが node_modules/ 検索よりも優先されます:

modules: [path.resolve(__dirname, "src"), "node_modules"]

devServer コンフィギュレーション

開発環境に使用されるコンフィギュレーションには、以下のプロパティがあります:

module.exports = { devServer: { //コードが実行されるディレクトリ contentBase: resolve(_dirname, 'build'), //comtentBaseディレクトリのファイルを監視し、変更されたらすぐにリロードする。 watchContentBase: true, watchOptions: { //ファイルを無視する、ノードを監視しない_modules ignored: /node_modules/ } //gzip圧縮を開始する compress: true, // port: 5000 // host: 'localhost', //自動的にブラウザーを開く open:true, //HMR機能をオンにする hot:true, //サーバー起動時のログ・メッセージを表示しない clientLogLevel: 'none', //基本的な起動情報以外は表示しない quiet: true, //何か問題が発生した場合、フルスクリーンのプロンプトを表示しない overlay: false, //サーバー・プロキシ:開発環境におけるクロスドメインの問題を解決する proxy: { //サーバーアクセスが/apiで始まるリクエストを監視すると、設定されたアドレスにリクエストを転送する。 '/api': { target: '"http://localhost:3000"', //リクエストの送信は、リクエストパスの書き換え:/api/を設定する。***--->/*** pathRewrite: { '^/api': '' } }, //デフォルトでは、無効な証明書を持つHTTPSで動作するバックエンドサーバーは受け付けられない。 //それを受け入れたい場合は、secure: falseを設定する。 "/test": { target: "https://other-..com", secure: false } } } }

externals: 設定オプションは「エクスポートされたバンドルから依存関係を除外する」方法を提供します。

**いくつかの `*import` パッケージがバンドルに **パッケージ** されるのを **防ぎます。

例えば、 jQueryパッケージ化する代わりにCDNから取り込みます:

webpack.config.js

externals: {
 jquery: 'jQuery'
}

これは、変更する必要のない依存モジュールを取り除くもので、言い換えれば、以下に示すコードでも問題なく動作します:

import $ from 'jquery'; $('.my-element').animate(...);

インデックス.html

<script
 src="https://..com/jquery-...js"
 integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
 crossorigin="anonymous">
</script>

最適化:コードの分割

いくつかの属性があります:

module.exports = { optimization: { splitChunks:{ chunks: 'all', //以下はデフォルト値であり、省略可能である。 minSize: 30*1024, //最小分割チャンクは30kb, maxSize:0, //最大分割数に制限はない, minChunks: 1,//抽出されるチャンクは少なくとも一度は参照されている。 maxAsyncRequests:3, //オンデマンド・ロード時に並行してロードするファイルの最大数 minInitialRequests:3, //エントリーjsファイルの最大並列リクエスト数 automaticNameDelimiter: '~',//名前リンカー name: true, //命名規則が使える cacheGroups: { //分割されたチャンクの配列 //node_modulesファイルはベンダー・グループのチャンクにまとめられる, ---verndors~xxx.js //上記の公開ルールを満たすこと、例えば、サイズが30kb以上であること、少なくとも1回は引用されること。 vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 // }, default: { minChunks: 2, //抽出されるチャンクの最小参照回数 priority: -20, // //現在パッケージ化されているモジュールが抽出されたモジュールと同じであれば、再パッケージ化される代わりに再利用される。 reuseExistingChunk: true } } }, //他のモジュールに記録されている現在のモジュールのハッシュ値を、別のファイルのランタイムにパックする.js //解決策:ファイルaを変更すると、ファイルbのcontenhash値が変更され、キャッシュが無効になる。 runtimeChunk: { name: entrypoint => `runtime-${entrypoint.name}` }, minimizer:{ //本番環境用の圧縮スキームを設定する:jsとcss ... } } }
Read next

HTTPプロトコルの歴史

現在のドメインアドレスを示す Host フィールドを追加し、Host の値によってサーバが異なる処理を行えるようにしました。 この問題を解決するためにチャンク転送メカニズムを導入し、サーバーはデータを任意の大きさの複数のチャンクに分割し、各チャンクは前のチャンクの長さで送信され、最終的に送信するデータとして長さゼロのチャンクを使用します...

Jul 15, 2020 · 4 min read

Js実行コンテキスト

Jul 14, 2020 · 2 min read

OpenGLベクトルと行列

Jul 14, 2020 · 4 min read

Python:データクラスを使う。

Jul 14, 2020 · 2 min read

HTTP共通ヘッダ

Jul 14, 2020 · 4 min read