ホームページ > 記事 > ウェブフロントエンド > Webpack を使用して構成ファイルを最適化する方法
今回は、Webpack設定ファイルを最適化する方法と、Webpack最適化設定ファイルの注意事項を紹介します。実際のケースを見てみましょう。
Webpack が開始されると、設定されたエントリから開始され、ファイル内のインポート ステートメントが解析され、再帰的に解析されます。 Webpack は import ステートメントに遭遇すると 2 つのことを行います: 1. import ステートメントに従って、インポートする対応するファイルを見つけます。たとえば、require('react') import ステートメントに対応するファイルは ./node_modules/react/react.js で、require('./util') に対応するファイルは ./util.js です。 2. インポートするファイルの見つかったサフィックスに基づいて、設定内のローダーを使用してファイルを処理します。たとえば、ES6 を使用して開発された JavaScript ファイルは、babel-loader を使用して処理する必要があります。
上記 2 つはファイルの処理としては非常に高速ですが、プロジェクトが大きくなるとファイル数が非常に多くなり、ビルド速度が遅いという問題が露呈します。 上記 2 つは避けることはできませんが、速度を上げるためには最小限に抑える必要があります。 次に、それらを最適化する方法を 1 つずつ紹介します。ローダー構成を最適化する
ローダーのファイル変換操作には時間がかかるため、ローダーで処理できるファイルの数をできるだけ少なくする必要があります。 2-3 モジュールでは、ローダーを使用するときに、テスト、インクルード、除外の 3 つの構成項目を使用して、ローダーがルールを適用したいファイルをヒットできることを紹介しました。 ローダーによって処理されるファイルをできるだけ少なくするために、 include を使用して、処理する必要があるファイルのみを対象にすることができます。 ES6 を使用するプロジェクトを例に挙げると、babel-loader を設定するときに次のようにすることができます:module.exports = { module: { rules: [ { // 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能 test: /\.js$/, // babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启 use: ['babel-loader?cacheDirectory'], // 只对项目根目录下的 src 目录中的文件采用 babel-loader include: path.resolve(dirname, 'src'), }, ] }, };プロジェクトの
ディレクトリ構造 を適切に調整して、Loader を構成するときに include を通じてヒット範囲を絞りやすくすることができます。
resolve.modules 構成を最適化する
2-4 解決で紹介したように、resolve.modules は、Webpack がサードパーティ モジュールを検索するディレクトリを構成するために使用されます。 solve.modules のデフォルト値は です。つまり、まず現在のディレクトリの ./node_modules ディレクトリに移動して、探しているモジュールが見つからない場合は、上位レベルのディレクトリ ../node_modules に移動して見つけます。見つからない場合は、.. /../node_modules などに移動します。これは、Node.js のモジュール検索メカニズムとよく似ています。 ['node_modules']
module.exports = { resolve: { // 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤 // 其中 dirname 表示当前工作目录,也就是项目根目录 modules: [path.resolve(dirname, 'node_modules')] }, };
resolve.mainFields 構成を最適化する
2-4 Resolve で導入された、resolve.mainFields は、サードパーティ モジュールに使用するエントリ ファイルを構成するために使用されます。
インストールされたサードパーティ モジュールには、モジュールのプロパティを記述するための package.json ファイルが存在します。一部のフィールドは、エントリ ファイルの場所を記述するために使用されます。resolve.mainFields は、どのフィールドを記述として使用するかを構成するために使用されます。エントリーファイル。 エントリ ファイルを記述するフィールドが複数存在する可能性がある理由は、一部のモジュールは複数の環境で同時に使用でき、動作環境ごとに異なるコードを使用する必要があるためです。 たとえば、isomorphic-fetch はフェッチ API の実装ですが、ブラウザーと Node.js 環境の両方で使用できます。 package.json には 2 つのエントリ ファイル説明フィールドがあります:{ "browser": "fetch-npm-browserify.js", "main": "fetch-npm-node.js" }Isomorphic-fetch は、フェッチ API の実装メカニズムが異なるため、ブラウザーのネイティブ フェッチまたは XMLHttpRequest と Node.js の http モジュールを通じて実装されます。 solve.mainFields のデフォルト値は、現在のターゲット構成に関連しており、対応する関係は次のとおりです。 ターゲットが Web または Webworker の場合、値は ["browser", "module", "main"] になります
以 target 等于 web 为例,Webpack 会先采用第三方模块中的 browser 字段去寻找模块的入口文件,如果不存在就采用 module 字段,以此类推。
为了减少搜索步骤,在你明确第三方模块的入口文件描述字段时,你可以把它设置的尽量少。
由于大多数第三方模块都采用 main 字段去描述入口文件的位置,可以这样配置 Webpack:
module.exports = { resolve: { // 只采用 main 字段作为入口文件描述字段,以减少搜索步骤 mainFields: ['main'], }, };
使用本方法优化时,你需要考虑到所有运行时依赖的第三方模块的入口文件描述字段,就算有一个模块搞错了都可能会造成构建出的代码无法正常运行。
优化 resolve.alias 配置
在 2-4 Resolve 中介绍过 resolve.alias 配置项通过别名来把原导入路径映射成一个新的导入路径。
在实战项目中经常会依赖一些庞大的第三方模块,以 React 库为例,安装到 node_modules 目录下的 React 库的目录结构如下:
├── dist
│ ├── react.js
│ └── react.min.js
├── lib
│ ... 还有几十个文件被忽略
│ ├── LinkedStateMixin.js
│ ├── createClass.js
│ └── React.js
├── package.json
└── react.js
可以看到发布出去的 React 库中包含两套代码:
一套是采用 CommonJS 规范的模块化代码,这些文件都放在 lib 目录下,以 package.json 中指定的入口文件 react.js 为模块的入口。
默认情况下 Webpack 会从入口文件 ./node_modules/react/react.js 开始递归的解析和处理依赖的几十个文件,这会时一个耗时的操作。
通过配置 resolve.alias 可以让 Webpack 在处理 React 库时,直接使用单独完整的 react.min.js 文件,从而跳过耗时的递归解析操作。
相关 Webpack 配置如下:
module.exports = { resolve: { // 使用 alias 把导入 react 的语句换成直接使用单独完整的 react.min.js 文件, // 减少耗时的递归解析操作 alias: { 'react': path.resolve(dirname, './node_modules/react/dist/react.min.js'), } }, };
除了 React 库外,大多数库发布到 Npm 仓库中时都会包含打包好的完整文件,对于这些库你也可以对它们配置 alias。
但是对于有些库使用本优化方法后会影响到后面要讲的 使用 Tree-Shaking 去除无效代码 的优化,因为打包好的完整文件中有部分代码你的项目可能永远用不上。
一般对整体性比较强的库采用本方法优化,因为完整文件中的代码是一个整体,每一行都是不可或缺的。
但是对于一些工具类的库,例如 lodash ,你的项目可能只用到了其中几个工具函数,你就不能使用本方法去优化,因为这会导致你的输出代码中包含很多永远不会执行的代码。
优化 resolve.extensions 配置
在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在。
在 2-4 Resolve 中介绍过 resolve.extensions 用于配置在尝试过程中用到的后缀列表,默认是:
extensions: ['.js', '.json']
也就是说当遇到 require('./data') 这样的导入语句时,Webpack 会先去寻找 ./data.js 文件,如果该文件不存在就去寻找 ./data.json 文件,如果还是找不到就报错。
如果这个列表越长,或者正确的后缀在越后面,就会造成尝试的次数越多,所以 resolve.extensions 的配置也会影响到构建的性能。
在配置 resolve.extensions 时你需要遵守以下几点,以做到尽可能的优化构建性能:
后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中。
相关 Webpack 配置如下:
module.exports = { resolve: { // 尽可能的减少后缀尝试的可能性 extensions: ['js'], }, };
优化 module.noParse 配置
在 2-3 Module 中介绍过 module.noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析处理,这样做的好处是能提高构建性能。
原因是一些库,例如 jQuery 、ChartJS, 它们庞大又没有采用模块化标准,让 Webpack 去解析这些文件耗时又没有意义。
在上面的 优化 resolve.alias 配置 中讲到单独完整的 react.min.js 文件就没有采用模块化,让我们来通过配置 module.noParse 忽略对 react.min.js 文件的递归解析处理,
相关 Webpack 配置如下:
const path = require('path'); module.exports = { module: { // 独完整的 `react.min.js` 文件就没有采用模块化,忽略对 `react.min.js` 文件的递归解析处理 noParse: [/react\.min\.js$/], }, };
注意被忽略掉的文件里不应该包含 import 、 require 、 define 等模块化语句,不然会导致构建出的代码中包含无法在浏览器环境下执行的模块化语句。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がWebpack を使用して構成ファイルを最適化する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。