Maison > Article > interface Web > Exemple de didacticiel de module Webpack
在web存在多种支持JavaScript模块化的工具(如requirejs和r.js),这些工具各有优势和限制。webpack基于从这些系统获得的经验教训,并将模块的概念应用于项目中的任何文件。本文将详细介绍webpack的模块解析
在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块
每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易举。 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的
Node.js从最一开始就支持模块化编程。对比Node.js模块,webpack模块能够以各种方式表达它们的依赖关系
ES2015 import 语句 CommonJS require() 语句 AMD define 和 require 语句 css/sass/less 文件中的 @import 语句。 样式(url(...))或 HTML 文件(<img src=...>)中的图片链接(image url)
[注意]webpack 1需要特定的loader来转换ES 2015 import,然而通过webpack 2可以开箱即用
【支持类型】
webpack通过loader可以支持各种语言和预处理器编写模块。loader描述了webpack如何处理非JavaScript(non-JavaScript) 模块,并且在bundle中引入这些依赖。 webpack 社区已经为各种流行语言和语言处理器构建了loader,包括:
CoffeeScript TypeScript ESNext (Babel) Sass Less Stylus
总的来说,webpack提供了可定制的、强大和丰富的API,允许任何技术栈使用webpack,保持了在开发、测试和生成流程中无侵入性(non-opinionated)
resolver是一个库(library),用于帮助找到模块的绝对路径。一个模块可以作为另一个模块的依赖模块,然后被后者引用,如下:
import foo from 'path/to/module'// 或者require('path/to/module')
所依赖的模块可以是来自应用程序代码或第三方的库(library)。resolver帮助webpack找到bundle中需要引入的模块代码,这些代码在包含在每个require/import语句中。当打包模块时,webpack使用enhanced-resolve来解析文件路径
【解析规则】
使用enhanced-resolve,webpack能够解析三种文件路径:
1、绝对路径
import "/home/me/file"; import "C:\\Users\\me\\file";
由于已经取得文件的绝对路径,因此不需要进一步再做解析
2、相对路径
import "../src/file1"; import "./file2";
在这种情况下,使用import或require的资源文件(resource file)所在的目录被认为是上下文目录(context directory)。在import/require中给定的相对路径,会添加此上下文路径(context path),以产生模块的绝对路径(absolute path)
3、模块路径
import "module"; import "module/lib/file";
模块将在resolve.modules中指定的所有目录内搜索。 可以替换初始模块路径,此替换路径通过使用resolve.alias配置选项来创建一个别名
一旦根据上述规则解析路径后,解析器(resolver)将检查路径是否指向文件或目录
如果路径指向一个文件:
a、如果路径具有文件扩展名,则被直接将文件打包
b、否则,将使用 [resolve.extensions] 选项作为文件扩展名来解析,此选项告诉解析器在解析中能够接受哪些扩展名(例如 .js, .jsx)
如果路径指向一个文件夹,则采取以下步骤找到具有正确扩展名的正确文件:
a、如果文件夹中包含 package.json 文件,则按照顺序查找 resolve.mainFields 配置选项中指定的字段。并且 package.json 中的第一个这样的字段确定文件路径
b、如果package.json文件不存在或者package.json文件中的main字段没有返回一个有效路径,则按照顺序查找 esolve.mainFiles配置选项中指定的文件名,看是否能在import/require目录下匹配到一个存在的文件名
c、文件扩展名通过 resolve.extensions 选项采用类似的方法进行解析
webpack 根据构建目标(build target)为这些选项提供了合理的默认配置
【解析与缓存】
Loader解析遵循与文件解析器指定的规则相同的规则。resolveLoader 配置选项可以用来为 Loader 提供独立的解析规则。
每个文件系统访问都被缓存,以便更快触发对同一文件的多个并行或穿行请求。在观察模式下,只有修改过的文件会从缓存中摘出。如果关闭观察模式,在每次编译前清理缓存
任何时候,一个文件依赖于另一个文件,webpack就把此视为文件之间有依赖关系。这使得 webpack 可以接收非代码资源(non-code asset)(例如图像或 web 字体),并且可以把它们作为依赖提供给应用程序
webpack从命令行或配置文件中定义的一个模块列表开始,处理应用程序。 从这些入口起点开始,webpack 递归地构建一个依赖图表,这个依赖图表包含着应用程序所需的每个模块,然后将所有这些模块打包为少量的bundle(通常只有一个 )可由浏览器加载
因为服务器和浏览器代码都可以用JavaScript编写,所以webpack提供了多种构建目标(target),可以在webpack配置中设置
【用法】
要设置target属性,只需要在webpack配置中设置target的值
//webpack.config.jsmodule.exports = { target: 'node'};
在上面例子中,使用node webpack会编译为用于「类Node.js」环境(使用Node.js的require,而不是使用任意内置模块(如fs或path)来加载chunk)。
每个target都有各种部署(deployment)/环境(environment)特定的附加项,以支持满足其需求
【多个Target】
尽管webpack不支持向target传入多个字符串,可以通过打包两份分离的配置来创建同构的库
//webpack.config.jsvar path = require('path');var serverConfig = { target: 'node', output: { path: path.resolve(__dirname, 'dist'), filename: 'lib.node.js' } //…};var clientConfig = { target: 'web', // <=== 默认是 'web',可省略 output: { path: path.resolve(__dirname, 'dist'), filename: 'lib.js' } //…}; module.exports = [ serverConfig, clientConfig ];
L'exemple ci-dessus créera des fichiers lib.js et lib.node.js dans le dossier dist
Remplacement à chaud du module HMR (Module chaud Remplacement) remplace, ajoute ou supprime des modules pendant que l'application est en cours d'exécution sans recharger la page. Cela permet à ces modules d'être mis à jour sans actualiser la page entière après la modification des modules indépendants, accélérant considérablement le temps de développement
[Du point de vue de l'application]
1. Exigences du code de l'application HMR le runtime vérifie les mises à jour
2. Le runtime HMR télécharge (de manière asynchrone) les mises à jour, puis informe le code de l'application que les mises à jour sont disponibles
3. Le code de l'application nécessite le runtime HMR pour appliquer les mises à jour
4. Mise à jour de l'application HMR Runtime (asynchrone)
Vous pouvez configurer HMR pour que ce processus déclenche automatiquement les mises à jour, ou vous pouvez choisir d'exiger des mises à jour après l'interaction de l'utilisateur
[Du point de vue du compilateur (webpack)]
En plus des ressources normales, le compilateur doit émettre une "mise à jour" pour permettre la mise à jour de la version précédente vers la nouvelle version. "update" se compose de deux parties : 1. Manifeste à mettre à jour (JSON) ; 2. Un ou plusieurs fragments à mettre à jour (JavaScript)
Le manifeste inclut le nouveau hachage de compilation et tous les répertoires de fragments à mettre à jour ; .
Chaque morceau à mettre à jour comprend le code du morceau correspondant à tous les modules en cours de mise à jour (ou un indicateur pour indiquer que le module doit être supprimé).
Le compilateur garantit que les ID de module et les ID de fragment sont cohérents entre ces versions. Ces identifiants sont généralement stockés en mémoire (par exemple, lors de l'utilisation de webpack-dev-server), mais il est également possible de les stocker dans un fichier JSON
[du point de vue d'un module]
HMR est une fonctionnalité facultative et n'affectera que les modules contenant du code HMR. Par exemple, ajoutez un patch au style via style-loader. Afin d'exécuter des correctifs supplémentaires, le chargeur de style implémente l'interface HMR ; lorsqu'il reçoit des mises à jour via HMR, il remplace les anciens styles par les nouveaux styles.
De même, lorsque l'interface HMR est implémentée dans un module, elle peut décrire ce qui se passe lorsque le module est mis à jour. Cependant, dans la plupart des cas, il n’est pas nécessaire de forcer le code HMR dans chaque module. Si un module n'a pas de gestionnaire HMR, les mises à jour apparaîtront. Cela signifie qu'une simple fonction de traitement peut traiter l'arborescence complète des modules. Si un seul module de cette arborescence de modules est mis à jour, l'arborescence de modules entière sera rechargée (uniquement rechargée, non migrée).
[Du point de vue de HMR Runtime]
Pour l'exécution du système de modules, un code supplémentaire est envoyé aux modules de suivi des parents et des enfants.
En termes de gestion, le runtime prend en charge deux méthodes de vérification et d'application.
1. Check envoie une requête HTTP pour mettre à jour le manifeste. Si la demande échoue, aucune mise à jour n'est disponible. Si la requête aboutit, le chunk à mettre à jour sera comparé au chunk actuellement chargé. Pour chaque chunk chargé, le chunk correspondant à mettre à jour sera téléchargé. Lorsque tous les morceaux à mettre à jour auront été téléchargés, ils seront prêts à passer à l’état prêt.
2. La méthode apply marque tous les modules mis à jour comme invalides. Pour chaque module invalide, il doit y avoir un gestionnaire de mise à jour dans le module ou dans ses modules parents. Sinon, la balise invalide apparaît et marque également le parent comme invalide. Chaque bouillonnement continue jusqu'à ce qu'il atteigne le point d'entrée de l'application ou le module avec le gestionnaire de mise à jour, selon la première éventualité. S'il commence à bouillonner à partir du point d'entrée, le processus échoue.
Après cela, tous les modules invalides sont traités (via le gestionnaire de suppression) et déchargés. Ensuite, le hachage actuel est mis à jour et tous les gestionnaires « accepter » sont appelés. Le runtime revient à l'état inactif et tout continue comme d'habitude
HMR peut être utilisé en remplacement de LiveReload pendant le développement. webpack-dev-server prend en charge le mode chaud, qui tentera d'utiliser HMR pour mettre à jour
avant d'essayer de recharger la page entière. Certains chargeurs ont généré des modules pouvant être mis à jour à chaud. Par exemple, style-loader peut échanger la feuille de style d'une page. Pour un tel module, aucun traitement particulier n'est requis
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!