Home >Web Front-end >JS Tutorial >webpack module example tutorial

webpack module example tutorial

零下一度
零下一度Original
2017-06-26 10:13:101526browse

前面的话

  在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 ];

The above example will create lib.js and lib.node.js files in the dist folder

Module Hot Replacement

Module Hot Replacement HMR( Hot Module Replacement) feature replaces, adds, or removes modules while the application is running without reloading the page. This makes it possible to update these modules without refreshing the entire page after the independent modules are changed, which greatly speeds up the development time

[From the perspective of the App]

 1. App code requirements HMR runtime checks for updates

 2. HMR runtime (asynchronously) downloads updates, and then notifies the app code that updates are available

 3. The app code requires HMR runtime to apply updates

 4. HMR Runtime (asynchronous) application update

You can set HMR so that this process automatically triggers updates, or you can choose to require updates after user interaction

[From the perspective of the compiler (webpack)]

In addition to ordinary resources, the compiler needs to issue "update" to allow updating the previous version to the new version. "update" consists of two parts: 1. Manifest to be updated (JSON); 2. One or more chunks to be updated (JavaScript);

Manifest includes the new compilation hash and all chunk directories to be updated.

Each chunk to be updated includes code for the chunk corresponding to all modules being updated (or a flag to indicate that the module is to be removed).

The compiler ensures that module IDs and chunk IDs are consistent between these builds. These IDs are usually stored in memory (for example, when using webpack-dev-server), but it is also possible to store them in a JSON file

[Standing on the module's perspective]

 HMR is an optional feature and will only affect modules containing HMR code. For example, add a patch to the style style through style-loader. In order to run additional patches, the style-loader implements the HMR interface; when it receives updates via HMR, it replaces the old styles with the new styles.

Similarly, when the HMR interface is implemented in a module, it can describe what happens when the module is updated. In most cases, however, there is no need to force HMR code in every module. If a module does not have an HMR handler, updates will bubble up. This means that a simple processing function can process the complete module tree. If a single module in this module tree is updated, the entire module tree will be reloaded (only reloaded, not migrated).

[From the perspective of HMR Runtime]

For the runtime of the module system, additional code is sent to the parents and children tracking modules.

In terms of management, runtime supports two methods check and apply.

 1. Check sends an HTTP request to update the manifest. If the request fails, no updates are available. If the request is successful, the chunk to be updated will be compared with the currently loaded chunk. For each loaded chunk, the corresponding chunk to be updated will be downloaded. When all chunks to be updated have been downloaded, they will be ready to switch to the ready state.

 2. The apply method marks all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent modules. Otherwise, the invalid tag bubbles up and marks the parent as invalid as well. Each bubbling continues until it reaches the application entry point, or the module with the update handler, whichever comes first. If it starts bubbling from the entry point, the process fails.

After that, all invalid modules are processed (via the dispose handler) and unloaded. Then the current hash is updated and all "accept" handlers are called. The runtime switches back to the idle state and everything continues as usual

HMR can be used as a replacement for LiveReload during development. webpack-dev-server supports hot mode, which will try to use HMR to update

before trying to reload the entire page. Some loaders have generated hot-updatable modules. For example, style-loader can swap out a page's style sheet. For such a module, no special processing is required

The above is the detailed content of webpack module example tutorial. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn