Heim > Artikel > Web-Frontend > Beispiel-Tutorial für ein Webpack-Modul
在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 ];
Das obige Beispiel erstellt lib.js- und lib.node.js-Dateien im dist-Ordner
Module Hot Replacement HMR( Hot Module Die Funktion „Ersetzen“ ersetzt, fügt Module hinzu oder entfernt sie, während die Anwendung ausgeführt wird, ohne dass die Seite neu geladen werden muss. Dadurch können die Module aktualisiert werden, ohne dass die gesamte Seite aktualisiert werden muss, nachdem die unabhängigen Module geändert wurden, was die Entwicklungszeit erheblich beschleunigt
[Aus Sicht der App]
1. App-Code Anforderungen HMR Runtime sucht nach Updates
2. HMR Runtime lädt (asynchron) Updates herunter und benachrichtigt dann den App-Code, dass Updates verfügbar sind
3. Der App-Code erfordert, dass HMR Runtime Updates anwendet
4. HMR Runtime (asynchrones) Anwendungsupdate
Sie können HMR so einstellen, dass dieser Prozess automatisch Aktualisierungen auslöst, oder Sie können festlegen, dass Aktualisierungen nach Benutzerinteraktion erforderlich sind
[Von die Perspektive des Compilers (Webpack)]
Zusätzlich zu den normalen Ressourcen muss der Compiler ein „Update“ ausgeben, um die Aktualisierung der vorherigen Version auf die neue Version zu ermöglichen. „Update“ besteht aus zwei Teilen: 1. Zu aktualisierendes Manifest (JSON); 2. Ein oder mehrere zu aktualisierende Chunks (JavaScript);
Manifest enthält den neuen Kompilierungs-Hash und alle zu aktualisierenden Chunk-Verzeichnisse .
Jeder zu aktualisierende Block enthält Code für den Block, der allen zu aktualisierenden Modulen entspricht (oder ein Flag, das angibt, dass das Modul entfernt werden soll).
Der Compiler stellt sicher, dass Modul-IDs und Chunk-IDs zwischen diesen Builds konsistent sind. Diese IDs werden normalerweise im Speicher gespeichert (z. B. bei Verwendung von webpack-dev-server), es ist jedoch auch möglich, sie in einer JSON-Datei zu speichern
[aus Sicht eines Moduls]
HMR ist eine optionale Funktion und betrifft nur Module, die HMR-Code enthalten. Fügen Sie beispielsweise über den Style-Loader einen Patch zum Stil hinzu. Um zusätzliche Patches auszuführen, implementiert der Style-Loader die HMR-Schnittstelle; wenn er Updates über HMR erhält, ersetzt er die alten Styles durch die neuen Styles.
Wenn die HMR-Schnittstelle in einem Modul implementiert ist, kann sie ebenfalls beschreiben, was passiert, wenn das Modul aktualisiert wird. In den meisten Fällen ist es jedoch nicht erforderlich, HMR-Code in jedem Modul zu erzwingen. Wenn ein Modul keinen HMR-Handler hat, kommt es zu Updates. Dies bedeutet, dass eine einfache Verarbeitungsfunktion den gesamten Modulbaum verarbeiten kann. Wenn ein einzelnes Modul in diesem Modulbaum aktualisiert wird, wird der gesamte Modulbaum neu geladen (nur neu geladen, nicht migriert).
[Aus Sicht der HMR-Laufzeit]
Für die Laufzeit des Modulsystems wird zusätzlicher Code an die Eltern- und Kinder-Tracking-Module gesendet.
In Bezug auf die Verwaltung unterstützt die Laufzeit zwei Methoden zum Prüfen und Anwenden.
1. Check sendet eine HTTP-Anfrage, um das Manifest zu aktualisieren. Wenn die Anfrage fehlschlägt, sind keine Updates verfügbar. Wenn die Anfrage erfolgreich ist, wird der zu aktualisierende Chunk mit dem aktuell geladenen Chunk verglichen. Für jeden geladenen Block wird der entsprechende zu aktualisierende Block heruntergeladen. Wenn alle zu aktualisierenden Chunks heruntergeladen wurden, können sie in den Bereitschaftszustand wechseln.
2. Die Apply-Methode markiert alle aktualisierten Module als ungültig. Für jedes ungültige Modul muss ein Update-Handler im Modul oder in seinen übergeordneten Modulen vorhanden sein. Andernfalls sprudelt das ungültige Tag in die Luft und markiert auch das übergeordnete Element als ungültig. Jedes Bubbling wird fortgesetzt, bis es den Anwendungseinstiegspunkt oder das Modul mit dem Update-Handler erreicht, je nachdem, was zuerst eintritt. Wenn es am Eintrittspunkt zu sprudeln beginnt, schlägt der Prozess fehl.
Danach werden alle ungültigen Module verarbeitet (über den Dispose-Handler) und entladen. Anschließend wird der aktuelle Hash aktualisiert und alle „accept“-Handler aufgerufen. Die Laufzeit wechselt wieder in den Ruhezustand und alles läuft wie gewohnt weiter
HMR kann während der Entwicklung als Ersatz für LiveReload verwendet werden. webpack-dev-server unterstützt den Hot-Modus, der versucht,
mit HMR zu aktualisieren, bevor versucht wird, die gesamte Seite neu zu laden. Einige Loader haben Hot-Update-fähige Module generiert. Beispielsweise kann der Style-Loader das Stylesheet einer Seite austauschen. Für ein solches Modul ist keine besondere Verarbeitung erforderlich
Das obige ist der detaillierte Inhalt vonBeispiel-Tutorial für ein Webpack-Modul. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!