在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 ];
위의 예에서는 dist 폴더에 lib.js 및 lib.node.js 파일을 생성합니다
HMR(핫 모듈 교체) 기능은 애플리케이션이 실행되는 동안 모듈을 교체합니다. 페이지를 다시 로드하지 않고도 모듈을 사용할 수 있습니다. 이를 통해 독립 모듈을 변경한 후 전체 페이지를 새로 고치지 않고도 모듈을 업데이트할 수 있어 개발 시간이 크게 단축됩니다
【앱 측면에서】
1. 앱 코드에서 업데이트 확인을 위해 HMR 런타임이 필요합니다.
2. HMR 런타임(비동기)이 업데이트를 다운로드한 후 앱 코드에 업데이트가 가능함을 알립니다.
3. 앱 코드에서 업데이트를 적용하려면 HMR 런타임이 필요합니다.
4. HMR 런타임(비동기)이 업데이트를 적용합니다.
이 프로세스가 자동으로 업데이트를 실행하도록 HMR을 설정할 수도 있고, 사용자 상호작용 후에 업데이트를 요구하도록 선택할 수도 있습니다
【컴파일러(웹팩)의 관점에서】
일반적인 리소스 외에 컴파일러(컴파일러) )는 이전 버전을 새 버전으로 업데이트할 수 있도록 "업데이트"를 실행해야 합니다. "업데이트"는 두 부분으로 구성됩니다: 1. 업데이트할 매니페스트(JSON) 2. 업데이트할 하나 이상의 청크(JavaScript)
매니페스트에는 업데이트할 새 컴파일 해시와 모든 청크 디렉터리가 포함됩니다.
업데이트될 각 청크에는 업데이트되는 모든 모듈에 해당하는 청크에 대한 코드(또는 모듈이 제거될 것임을 나타내는 플래그)가 포함됩니다.
컴파일러는 이러한 빌드 간에 모듈 ID와 청크 ID가 일관되도록 보장합니다. 일반적으로 이러한 ID는 메모리에 저장되지만(예: webpack-dev-server를 사용하는 경우) JSON 파일에 저장하는 것도 가능합니다
【모듈 관점에서】
HMR은 선택 기능이며 영향을 미칩니다. HMR 코드가 포함된 모듈. 예를 들어, style-loader를 통해 스타일 스타일에 패치를 추가합니다. 추가 패치를 실행하기 위해 스타일 로더는 HMR을 통해 업데이트를 받으면 이전 스타일을 새 스타일로 바꿉니다.
마찬가지로 HMR 인터페이스를 모듈에 구현하면 모듈이 업데이트되면 어떤 일이 발생하는지 설명할 수 있습니다. 그러나 대부분의 경우 모든 모듈에서 HMR 코드를 강제로 적용할 필요는 없습니다. 모듈에 HMR 핸들러가 없으면 업데이트가 발생합니다. 이는 간단한 처리 기능으로 전체 모듈 트리를 처리할 수 있음을 의미합니다. 이 모듈 트리의 단일 모듈이 업데이트되면 전체 모듈 트리가 다시 로드됩니다(마이그레이션되지 않고 다시 로드만 됨).
【HMR 런타임 관점에서】
모듈 시스템의 런타임을 위해 상위 및 하위 추적 모듈에 추가 코드가 전송됩니다.
관리 측면에서 런타임은 확인 및 적용 두 가지 방법을 지원합니다.
1. 확인은 매니페스트를 업데이트하기 위해 HTTP 요청을 보냅니다. 요청이 실패하면 업데이트를 사용할 수 없습니다. 요청이 성공하면 업데이트할 청크가 현재 로드된 청크와 비교됩니다. 로드된 각 청크에 대해 업데이트할 해당 청크가 다운로드됩니다. 업데이트할 모든 청크가 다운로드되면 준비 상태로 전환할 준비가 된 것입니다.
2. Apply 메소드는 업데이트된 모든 모듈을 유효하지 않은 것으로 표시합니다. 유효하지 않은 각 모듈의 경우 모듈이나 해당 상위 모듈에 업데이트 핸들러가 있어야 합니다. 그렇지 않으면 유효하지 않은 태그가 표시되고 상위 태그도 유효하지 않은 것으로 표시됩니다. 각 버블링은 애플리케이션 진입점이나 업데이트 핸들러가 있는 모듈 중 먼저 도달할 때까지 계속됩니다. 진입점에서 버블링이 시작되면 프로세스가 실패합니다.
이후 모든 유효하지 않은 모듈은 처리 핸들러 기능을 통해 처리되고 언로드됩니다. 그런 다음 현재 해시가 업데이트되고 모든 "accept" 핸들러가 호출됩니다. 런타임은 유휴 상태로 다시 전환되고 모든 것이 평소대로 계속됩니다.
HMR은 개발 프로세스 중에 LiveReload를 대체하여 사용할 수 있습니다. webpack-dev-server는 전체 페이지를 다시 로드하기 전에 HMR을 사용하여 업데이트를 시도하는 핫 모드를 지원합니다
일부 로더는 핫 업데이트할 수 있는 모듈을 생성했습니다. 예를 들어 스타일 로더는 페이지의 스타일 시트를 교체할 수 있습니다. 이러한 모듈의 경우 특별한 처리가 필요하지 않습니다
위 내용은 webpack 모듈 예제 튜토리얼의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!