Skip to content
This repository was archived by the owner on Mar 22, 2019. It is now read-only.

loaders.cn

e-cloud edited this page Jul 12, 2016 · 2 revisions

Introduction

介绍

Loaders allow you to preprocess files as you require() or "load" them. Loaders are kind of like "tasks" are in other build tools, and provide a powerful way to handle frontend build steps. Loaders can transform files from a different language like, CoffeeScript to JavaScript, or inline images as data URLs. Loaders even allow you to do things like require() css files right in your JavaScript!

当你require()或者“加载”文件时,loader 可以对其进行预处理。loader 有点像其他构建工具的 "task" 概念,并提供了一种强大的方式来处理前端分步构建。loader 能转换其他语言的文件,如 CoffeeScript 到 JavaScript,或者 将图片以 DataUrl 的形式内联。loader 甚至可以允许你在 JavaScript require() css 文件。

To tell Webpack to transform a module with a loader, you can specify the loader in the module request, such as in a require call. 为了让 webpack 使用一个 loader 转换某个 module,你可以在__请求__模块时指定 loader,例如在调用require时。

var moduleWithOneLoader = require("my-loader!./my-awesome-module");

Notice the ! syntax separating the loader from the module path. Loaders, like modules can also be specified with a relative path (as if you were requiring it) instead of the loader name: 注意!的语法将 loader 与模块路径分离开来。loader,像模块一样可以用相对路径指定(如同在 require 它)而不一定是 loader 的名称。

require("./loaders/my-loader!./my-awesome-module");

Loaders can be also be chained together by separating loaders with the !. This is helpful for applying multiple transformations to a file in a pipeline. loader 可以通过!分割符串联使用。可用于管道式地对一个文件应用多种转换。

require("style-loader!css-loader!less-loader!./my-styles.less");

When chaining loaders, they are applied right to left (from the file, back). In the above example, my-styles.less will be transformed first by the less-loaderconverting it to css, and then passed to the css-loader where urls, fonts, and other resources are processed, and then finally passed to style-loader to be transformed into a <style> tag. 当串联 loader 时,调用顺序是从右到左(从文件开始)。上述例子中,my-styles.less首先会被less-loader转换成 css。然后被传给css-loader处理 urls、字体及其他资源。最后被传给style-loader转换到style标签。

parameters

参数

Loaders can accept query parameters: loader 可以接收查询参数:

require("loader?with=parameter!./file");

The format of the query string is up to the loader, so check the loaders documentation to find out about the parameters the loader accept, but generally most loaders support the traditional query string format. 查询字符串的格式取决于 loader 自身。所以请查看对应 loader 的文档,找出该 loader 接收的参数的相关信息。不过,大部分 loader 支持传统的查询字符串格式。

loaders by config

通过配置使用 loader

Specifying loaders in each module request can be brittle and repetitive. Webpack provides a way to specify which loaders apply to different file types in your Webpack configuration file. Specifying loaders in the configuration is the recommended approach in most cases as it doesn't add any build specific syntax to the code, making it more reusable. 在每个模块引用的时候指定 loader 是低效易变且费力的。 webpack 提供了一种方式,在 webpack configuration 文件中指定哪个 loader 应用到哪种类型的文件。在配置中指定 loader,在大部分情况下是推荐做法,因为这样不会在代码里添加任何构建相关的语法,更具可复用性。

{
	module: {
		loaders: [
			{ test: /\.coffee$/, loader: "coffee-loader" }
		],
		preLoaders: [
			{ test: /\.coffee$/, loader: "coffee-hint-loader" }
		]
	}
};

See the configuration page for more information about configuring loaders. 关于配置 loader 的更多信息参见configuration

loader order

loader 的顺序

After the file is read from the filesystem, loaders are executed against it in the following order. 在文件从文件系统读取成功后,loader 以下面的顺序依次执行

  1. preloaders specified in the configuration

  2. loaders specified in the configuration

  3. loaders specified in the request (e.g. require('raw!./file.js'))

  4. postLoaders specified in the configuration

  5. configuration中指定的preloaders

  6. configuration中指定的loaders

  7. 在请求中指定的 loader (e.g. require('raw!./file.js'))

  8. configuration中指定的postLoaders

You can also override the configuration loader order in the module request to suit special cases. 你也可以在模块引用时覆盖配置的 loader 以适应特殊场景。

  • adding ! to a request will disable configured preLoaders

  • 引用中添加!会使配置的preLoaders无效

    • require("!raw!./script.coffee")
  • adding !! to a request will disable all loaders specified in the configuration

  • 引用中添加!!会使配置的所有 loader 无效

    • require("!!raw!./script.coffee")
  • adding -! to a request will disable configured preLoaders and loaders but not the postLoaders

  • 引用中添加-!会使配置的preLoadersloaders无效,但不包括postLoaders

    • require("-!raw!./script.coffee")

recommendations

推荐做法

It is recommended that the result is JavaScript after step 2. 建议在第2步后输出结果是 JavaScript

It is recommended to apply non-JavaScript to JavaScript transformations in step 1 (or step 2 when they don't apply globally). 建议在第1步进行 non-JavaScript 到 JavaScript 的转换(或者没有全局使用的话可以在第2步)

It is recommended to stay in the same language in pre and post loaders. 建议前置(pre)和后置(post)的 loader 处理时保持语言不变。

Source code that want to override the non-js to js transformation should use the ! prefix. (i. e. to transform it in another way) 源代码如果需要覆盖 non-js 到 js 的转换,应该使用!前缀。(如用另一种方式转换)

Using the !! and -! prefix to disable loaders is not recommended except from another loader. 不建议使用!!-!前缀来关闭 loader,除非用来覆盖另一个 loader

  • Example for a preLoader: Image compression

  • Example for a loader (in config): coffee-script transformation

  • Example for a loader (in request): bundle loader

  • Example for a postLoader: Code coverage instrumenting

  • preLoader 的例子:图片压缩

  • config 中 loader 的例子:转换 coffee-script

  • request 中 loader 的例子:bundle loader

  • postLoader 的例子:代码覆盖率测试

Writing a loader

编写一个 loader

Writing a loader is pretty simple. A loader is just a file that exports a function. The compiler calls this function and passes the result of the previous loader or the resource file into it. The this context of the function is filled-in by the compiler with some useful methods that allow the loader to, among other things, change its invocation style to async or get query parameters. The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a String or a Buffer (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed.

写一个 loader 相当简单。一个 loader 只是一个输出一个函数的文件。编译器调用这个函数并将上一个 loader 的结果或者资源文件作为参数传入。函数的this上下文被编译器注以一些有用的函数,允许 loader 改变成异步运行的模式或者获取查询参数。第一个 loader 被传入一个参数:资源文件的内容。编译器期望上一个 loader 返回一个结果。该结果应该是一个字符串或者一个 Buffer 对象(会被转换成字符串),代表着该模块的 JavaScript 源码,(可选)也可以传递模块的 SourceMap 结果(作为 JSON 对象)

A single result can be returned in sync mode. For multiple results the this.callback must be called. In async mode this.async() must be called. It returns this.callback if async mode is allowed. Then the loader must return undefined and call the callback.

一个单一的结果可以同步返回。对于多个结果,必须调用this.callback。异步模式下,this.async()必须被调用。如果允许异步模式的话,它会返回this.callback。然后 loader 必须返回undefined并调用该回调函数。

Errors can be thrown in sync mode or the this.callback can be called with the error. 错误可以同步抛出或者以错误信息调用this.callback

webpack allows async mode in every case. webpack每种情况下都允许异步模式。

enhanced-require allows async mode only with require.ensure or AMD require. enhanced-require在存在require.ensure或者AMDrequire的情况下允许异步模式。

For more detailed instructions and guidelines, check out How to write a loader. 查阅How to write a loader以获取更多规范与指导。

examples

样例

sync loader

同步 loader

module.exports = function(content) {
	return someSyncOperation(content);
};

async loader

异步 loader

module.exports = function(content) {
	var callback = this.async();
	if(!callback) return someSyncOperation(content);
	someAsyncOperation(content, function(err, result) {
		if(err) return callback(err);
		callback(null, result);
	});
};

Note: It's recommended to give an asynchronous loader a fall back to synchronous mode. This isn't required for webpack, but allows to run the loader sync using enhanced-require. 注意:建议为异步执行的 loader 提供一个同步版本的回退方案。webpack 本身不需要这些,但这允许使用enhanced-require同步允许 loader。

raw loader

raw loader

By default the resource file is treated as utf-8 string and passed as String to the loader. By setting raw to true the loader is passed the raw Buffer. 资源文件默认以utf-8字符串识别,并以字符串的形式传递给 loader。通过设置 loader 的raw字段设置为true,loader 会被传入未经处理的 Buffer 对象。

Every loader is allowed to deliver its result as String or as Buffer. The compiler converts them between loaders. 允许每个 loader 以字符串或者 Buffer 传递其结果。编译器会在 loader 间进行转换。

module.exports = function(content) {
	assert(content instanceof Buffer);
	return someSyncOperation(content);
	// return value can be a Buffer too
	// This is also allowed if loader is not "raw"
};
module.exports.raw = true;

pitching loader

The loaders are called from right to left. But in some cases loaders do not care about the results of the previous loader or the resource. They only care for metadata. The pitch method on the loaders is called from left to right before the loaders are called. If a loader delivers a result in the pitch method the process turns around and skips the remaining loaders, continuing with the calls to the more left loaders. data can be passed between pitch and normal call.

loader 是从右到左调用的。但在某种情况下,loader 并不关心上一个 loader 返回的结果或者资源。其只关心元数据。loader 的pitch方法在 loader 调用前从左到右被唤起。如果一个 loader 在其 pitch 方法中返回一个结果,处理流程会反转并跳过剩余的 loader,继续调用其左边的 loader。data可在普通调用与pitch调用间传递。

module.exports = function(content) {
	return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function(remainingRequest, precedingRequest, data) {
	if(someCondition()) {
		// fast exit
		return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");";
	}
	data.value = 42;
};

loader context

loader 的上下文

This stuff is available on this in a loader. 一个 loader 的上下文可在其 this 对象获取。

For the example this require call is used: 见下例 require 的调用。

In /abc/file.js:

require("./loader1?xyz!loader2!./resource?rrr");

version

Loader API version. Currently 1. loader 的 API 版本号,当前是1

context

A string. The directory of the module. Can be used as context for resolving other stuff. 是一个字符串。模块的目录名。可以作为解析其他东西的上下文。

In the example: /abc because resource.js is in this directory 上例中:值为/abc, 因为 resource.js 在同一目录下。

request

The resolved request string. 解析了的请求字符串。

In the example: "/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"

query

A string. The query of the request for the current loader. 请求资源的当前 loader 的查询字符串。

In the example: in loader1: "?xyz", in loader2: "" 上例中:在 loader1:"?xyz", 在 loader2: ""

data

A data object shared between the pitch and the normal phase. 在 pitch 与普通阶段共享的一个数据对象。

cacheable

cacheable(flag = true: boolean)

Make this loader result cacheable. By default it's not cacheable. 让此 loader 的结果成为可缓存的。默认不可缓存。

A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with this.addDependency. Most loaders are deterministic and cacheable. 当输入与依赖不变的情况下,一个可缓存的 loader 必须拥有确定一致的结果。这意味着 loader 不应该存在其他依赖,除已经在this.addDependeny指定的。大部分的 loader 都是确定且可缓存的。

loaders

loaders = [{request: string, path: string, query: string, module: function}]

An array of all the loaders. It is writeable in the pitch phase. 包含所有 loader 的数组。在 pitch 阶段是可写的。

In the example: 例如:

[
  { request: "/abc/loader1.js?xyz",
	path: "/abc/loader1.js",
	query: "?xyz",
	module: [Function]
  },
  { request: "/abc/node_modules/loader2/index.js",
	path: "/abc/node_modules/loader2/index.js",
	query: "",
	module: [Function]
  }
]

loaderIndex

The index in the loaders array of the current loader. 当前 loader 在 loader 数组里的索引。

In the example: in loader1: 0, in loader2: 1 即上例的:loader1 是0, loader2 是1

resource

The resource part of the request, including query. 请求的资源部分,包括查询部分。

In the example: "/abc/resource.js?rrr" 即上例的:"/abc/resource.js?rrr"

resourcePath

The resource file. 资源文件的路径。

In the example: "/abc/resource.js" 即上例的:"/abc/resource.js"

resourceQuery

The query of the resource. 资源的查询字符串。

In the example: "?rrr" 即上例的:"?rrr"

emitWarning

emitWarning(message: string)

Emit a warning. 发送一个警告信号。

emitError

emitError(message: string)

Emit an error. 发送一个错误信号。

exec

exec(code: string, filename: string)

Execute some code fragment like a module. 像模块一样执行某些代码片段。

Hint: Don't use require(this.resourcePath), use this function to make loaders chainable! 提示: 不要使用 require(this.resourcePath), 而是用这个函数时使 loader 可以串联使用。

resolve

resolve(context: string, request: string, callback: function(err, result: string))

Resolve a request like a require expression. 解析一个请求,如同一个 require 表达式

resolveSync

resolveSync(context: string, request: string) -> string

Resolve a request like a require expression. 同步解析一个请求,如同一个 require 表达式

addDependency

addDependency(file: string)
dependency(file: string) // shortcut

Add a file as dependency of the loader result in order to make them watchable. 为 loader 的结果添加一个文件作为依赖,以便让其可监控。

addContextDependency

addContextDependency(directory: string)

Add a directory as dependency of the loader result. 给 loader 的结果添加一个目录作为依赖。

clearDependencies

clearDependencies()

Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using pitch. 移除 loader 结果的所有依赖。即使初始的依赖以及其他 loader 添加的。考虑使用pitch

value

Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array).

向后续 loader 传递值。如果你了解资源作为模块执行时输出的结果,在这里设置该值(只是一个数组)

inputValue

Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). 传自上一个 loader。如果你想将输入参数作为一个模块执行,为了快捷,可以考虑读取这个变量(性能更佳)

options

The options passed to the Compiler. 编译器的 options

debug

A boolean flag. It is set when in debug mode. 一个布尔标志。在调试模式时被设置。

minimize

Should the result be minimized. 要求结果是最小化的。

sourceMap

Should a SourceMap be generated. 要求生成一个 sourceMap

target

Target of compilation. Passed from configuration options. 编译目标。从配置选项传进。

Example values: "web", "node" 样例值:"web", "node"

webpack

Set to true when this is compiled by webpack. 当使用 webpack 编译时会被设为 true

emitFile

emitFile(name: string, content: Buffer|String, sourceMap: {...})

Emit a file. This is webpack-specific 发送一个文件。这是 webpack 特有的。

_compilation

Hacky access to the Compilation object of webpack. webpack 的编译对象的 不正当访问。

_compiler

Hacky access to the Compiler object of webpack. webpack 的编译器对象的 不正当访问。

Clone this wiki locally