Maison > interface Web > js tutoriel > le corps du texte

Exemple détaillé de configuration d'optimisation Webpack pour restreindre la portée de la recherche de fichiers

小云云
Libérer: 2017-12-25 16:37:12
original
1373 Les gens l'ont consulté

Une fois Webpack démarré, il démarrera à partir de l'entrée configurée, analysera les instructions d'importation dans le fichier, puis les analysera de manière récursive. Cet article présente principalement les connaissances pertinentes sur l'optimisation de Webpack en réduisant la portée de la recherche de fichiers. L'article présente les moyens d'optimiser plus en détail. Les amis qui en ont besoin peuvent s'y référer.

Lorsqu'il rencontre une instruction d'importation, Webpack fera deux choses :

1. Recherchez le fichier correspondant à importer en fonction de l'instruction d'importation. Par exemple, le fichier correspondant à l'instruction d'importation require('react') est ./node_modules/react/react.js, et le fichier correspondant à require('./util') est ./util.js.

2. Utilisez le Loader dans la configuration pour traiter le fichier en fonction du suffixe trouvé du fichier à importer. Par exemple, les fichiers JavaScript développés avec ES6 doivent être traités à l'aide de babel-loader.

Bien que les deux choses ci-dessus soient très rapides pour traiter un fichier, lorsque le projet devient volumineux, le nombre de fichiers deviendra très important et le problème de la vitesse de construction lente sera exposé.

Bien que les deux choses ci-dessus ne puissent être évitées, elles doivent être minimisées pour augmenter la vitesse.

Ce qui suit présentera les moyens de les optimiser une par une.

Optimiser la configuration du chargeur

L'opération de conversion des fichiers par Loader prenant du temps, il est nécessaire de permettre au moins de fichiers possible d'être traités par Loader.

Dans le module 2-3, nous avons introduit que lors de l'utilisation de Loader, vous pouvez utiliser les trois éléments de configuration tester, inclure et exclure pour accéder aux fichiers auxquels Loader souhaite appliquer des règles.

Afin de permettre au moins de fichiers possible d'être traité par Loader, vous pouvez utiliser include pour cibler uniquement les fichiers qui doivent être traités.

Prenons un projet utilisant ES6 comme exemple. Lors de la configuration de babel-loader, vous pouvez faire ceci :

module.exports = {
 module: {
  rules: [
   {
    // 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能
    test: /\.js$/,
    // babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启
    use: ['babel-loader?cacheDirectory'],
    // 只对项目根目录下的 src 目录中的文件采用 babel-loader
    include: path.resolve(__dirname, 'src'),
   },
  ]
 },
};
Copier après la connexion

Vous pouvez ajuster la structure des répertoires du projet de manière appropriée pour faciliter la configuration de. le chargeur est inclus pour réduire la plage de frappe.

Optimiser la configuration de solve.modules

Introduit dans 2-4 Resolve, solve.modules est utilisé pour configurer les répertoires que Webpack recherche pour les modules tiers.

La valeur par défaut de solve.modules est ['node_modules'], ce qui signifie qu'il faut d'abord aller dans le répertoire ./node_modules dans le répertoire actuel pour trouver le module que vous recherchez. S'il n'est pas trouvé, accédez à. le répertoire supérieur ../ Recherchez dans node_modules, sinon, recherchez dans ../../node_modules, et ainsi de suite. Ceci est très similaire au mécanisme de recherche de module de Node.js.

Lorsque les modules tiers installés sont placés dans le répertoire ./node_modules du répertoire racine du projet, il n'est pas nécessaire de rechercher couche par couche de la manière par défaut. Vous pouvez spécifier le chemin absolu pour stocker le. module tiers. Pour réduire les recherches, la configuration est la suivante :

module.exports = {
 resolve: {
  // 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
  // 其中 __dirname 表示当前工作目录,也就是项目根目录
  modules: [path.resolve(__dirname, 'node_modules')]
 },
};
Copier après la connexion

Optimiser la configuration de solve.mainFields

Introduit dans 2-4 Resolve, solve.mainFields est utilisé pour configurer lequel Le fichier d’entrée est utilisé par des modules tiers.

Le module tiers installé aura un fichier package.json utilisé pour décrire les propriétés du module. Certains champs sont utilisés pour décrire où se trouve le fichier d'entrée. solve.mainFields est utilisé pour configurer quel champ se trouve. utilisé comme description du fichier d’entrée.

La raison pour laquelle il peut y avoir plusieurs champs décrivant le fichier d'entrée est que certains modules peuvent être utilisés dans plusieurs environnements en même temps et que différents codes doivent être utilisés pour différents environnements d'exploitation.

Prenons l'exemple d'isomorphic-fetch, qui est une implémentation de l'API fetch mais peut être utilisée à la fois dans les environnements de navigateur et Node.js.

Il y a 2 champs de description de fichier d'entrée dans son package.json :

{
 "browser": "fetch-npm-browserify.js",
 "main": "fetch-npm-node.js"
}
Copier après la connexion

isomorphic-fetch utilise différents codes dans différents environnements d'exécution en raison du mécanisme d'implémentation de l'API fetch La différence. est qu'il est implémenté dans le navigateur via la récupération native ou XMLHttpRequest, et dans Node.js via le module http.

La valeur par défaut de solve.mainFields est liée à la configuration actuelle de la cible. La relation correspondante est la suivante :

  • Lorsque la cible est web ou webworker, la valeur. est ["browser", "module", "main"]

  • Lorsque la cible est d'autres situations, la valeur est ["module", "main"]

En prenant comme exemple target égal à web, Webpack utilisera d'abord le champ du navigateur dans le module tiers pour trouver le fichier d'entrée du module. S'il n'existe pas, il utilisera le module. champ, et ainsi de suite.

Afin de réduire les étapes de recherche, lorsque vous précisez le champ de description du fichier d'entrée du module tiers, vous pouvez le paramétrer le moins possible.

Étant donné que la plupart des modules tiers utilisent le champ principal pour décrire l'emplacement du fichier d'entrée, Webpack peut être configuré comme ceci :

module.exports = {
 resolve: {
  // 只采用 main 字段作为入口文件描述字段,以减少搜索步骤
  mainFields: ['main'],
 },
};
Copier après la connexion

Lors de l'optimisation à l'aide de cette méthode, vous devez prendre en compte tous les environnements d'exécution Même s'il y a une erreur dans le champ de description du fichier d'entrée du module tiers dépendant, le code construit peut ne pas s'exécuter correctement.

Optimiser la configuration de solve.alias

Introduit dans 2-4 Resolve, l'élément de configuration de solve.alias mappe le chemin d'importation d'origine à un nouveau chemin d'importation via des alias.

Dans les projets réels, nous nous appuyons souvent sur d'énormes modules tiers. En prenant la bibliothèque React comme exemple, la structure des répertoires de la bibliothèque React installée dans le répertoire node_modules est la suivante :

├── dist
│   ├── react.js
│   └── react.min.js
├── lib
│   ... 还有几十个文件被忽略
│   ├── LinkedStateMixin.js
│   ├── createClass.js
│   └── React.js
├── package.json
└── react.js

可以看到发布出去的 React 库中包含两套代码:

  • 一套是采用 CommonJS 规范的模块化代码,这些文件都放在 lib 目录下,以 package.json 中指定的入口文件 react.js 为模块的入口。

  • 一套是把 React 所有相关的代码打包好的完整代码放到一个单独的文件中,这些代码没有采用模块化可以直接执行。其中 dist/react.js 是用于开发环境,里面包含检查和警告的代码。 dist/react.min.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'),
  }
 },
};
Copier après la connexion

除了 React 库外,大多数库发布到 Npm 仓库中时都会包含打包好的完整文件,对于这些库你也可以对它们配置 alias。
但是对于有些库使用本优化方法后会影响到后面要讲的 使用 Tree-Shaking 去除无效代码 的优化,因为打包好的完整文件中有部分代码你的项目可能永远用不上。

一般对整体性比较强的库采用本方法优化,因为完整文件中的代码是一个整体,每一行都是不可或缺的。

但是对于一些工具类的库,例如 lodash ,你的项目可能只用到了其中几个工具函数,你就不能使用本方法去优化,因为这会导致你的输出代码中包含很多永远不会执行的代码。

优化 resolve.extensions 配置

在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在。

在 2-4 Resolve 中介绍过 resolve.extensions 用于配置在尝试过程中用到的后缀列表,默认是:

extensions: ['.js', '.json']
Copier après la connexion

也就是说当遇到 require('./data') 这样的导入语句时,Webpack 会先去寻找 ./data.js 文件,如果该文件不存在就去寻找 ./data.json 文件,如果还是找不到就报错。

如果这个列表越长,或者正确的后缀在越后面,就会造成尝试的次数越多,所以 resolve.extensions 的配置也会影响到构建的性能。

在配置 resolve.extensions 时你需要遵守以下几点,以做到尽可能的优化构建性能:

  • 后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中。

  • 频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程。

  • 在源码中写导入语句时,要尽可能的带上后缀,从而可以避免寻找过程。例如在你确定的情况下把 require('./data') 写成 require('./data.json') 。

相关 Webpack 配置如下:

module.exports = {
 resolve: {
  // 尽可能的减少后缀尝试的可能性
  extensions: ['js'],
 },
};
Copier après la connexion

优化 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$/],
 },
};
Copier après la connexion

注意被忽略掉的文件里不应该包含 import 、 require 、 define 等模块化语句,不然会导致构建出的代码中包含无法在浏览器环境下执行的模块化语句。

相关推荐:

Webpack实战之构建 Electron 应用实例详解

详解Webpack框架核心概念

webpack学习教程之前端性能优化总结

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal