|
1 | 1 | ---
|
2 | 2 | title: Loader API
|
3 | 3 | sort: 4
|
| 4 | +contributors: |
| 5 | + - TheLarkInn |
4 | 6 | ---
|
5 | 7 |
|
6 |
| -> TODO |
| 8 | +Loaders allow you to preprocess files as you `require()` or “load” them. Loaders are kind of like “tasks” in other build tools, |
| 9 | +and provide a powerful way to handle front-end 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! |
| 10 | + |
| 11 | +To tell webpack to transform a module with a loader, you can specify the loader in the webpack [configuration](/configuration) file (preferred) or in the module request, such as in a `require()` call. |
| 12 | + |
| 13 | +?> When /concepts/loaders merges, we should link to the many usages of loaders found there (require vs configuration) from this page. |
| 14 | + |
| 15 | +## How to write a loader |
| 16 | + |
| 17 | +A loader is just a JavaScript module 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 (among other things) to 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. |
| 18 | + |
| 19 | +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. |
| 20 | + |
| 21 | +## Examples |
| 22 | + |
| 23 | +### Sync Loader |
| 24 | + |
| 25 | +**sync-loader.js** |
| 26 | + |
| 27 | +```javascript |
| 28 | +module.exports = function(content) { |
| 29 | + return someSyncOperation(content); |
| 30 | +}; |
| 31 | +``` |
| 32 | + |
| 33 | +### Async Loader |
| 34 | + |
| 35 | +**async-loader.js** |
| 36 | + |
| 37 | +```javascript |
| 38 | +module.exports = function(content) { |
| 39 | + var callback = this.async(); |
| 40 | + if(!callback) return someSyncOperation(content); |
| 41 | + someAsyncOperation(content, function(err, result) { |
| 42 | + if(err) return callback(err); |
| 43 | + callback(null, result); |
| 44 | + }); |
| 45 | +}; |
| 46 | +``` |
| 47 | + |
| 48 | +T> It’s recommended to give an asynchronous loader a fall-back to synchronous mode. This isn’t required for webpack, but allows the loader to run synchronously using [enhanced-require](https://github.com/webpack/enhanced-resolve). |
| 49 | + |
| 50 | +### "Raw" Loader |
| 51 | + |
| 52 | +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`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. |
| 53 | + |
| 54 | +**raw-loader.js** |
| 55 | + |
| 56 | +```javascript |
| 57 | +module.exports = function(content) { |
| 58 | + assert(content instanceof Buffer); |
| 59 | + return someSyncOperation(content); |
| 60 | + // return value can be a `Buffer` too |
| 61 | + // This is also allowed if loader is not "raw" |
| 62 | +}; |
| 63 | +module.exports.raw = true; |
| 64 | +``` |
| 65 | + |
| 66 | +### Pitching Loader |
| 67 | + |
| 68 | +The order of chained loaders are **always** 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 (from right to left). |
| 69 | + |
| 70 | +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. |
| 71 | + |
| 72 | +```javascript |
| 73 | +module.exports = function(content) { |
| 74 | + return someSyncOperation(content, this.data.value); |
| 75 | +}; |
| 76 | +module.exports.pitch = function(remainingRequest, precedingRequest, data) { |
| 77 | + if(someCondition()) { |
| 78 | + // fast exit |
| 79 | + return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");"; |
| 80 | + } |
| 81 | + data.value = 42; |
| 82 | +}; |
| 83 | +``` |
| 84 | + |
| 85 | +## The loader context |
| 86 | + |
| 87 | +The loader context represents the properties that are available inside of a loader assigned to the `this` property. |
| 88 | + |
| 89 | +Given the following example this require call is used: |
| 90 | +In `/abc/file.js`: |
| 91 | + |
| 92 | +```javascript |
| 93 | +require("./loader1?xyz!loader2!./resource?rrr"); |
| 94 | +``` |
| 95 | + |
| 96 | +### `version` |
| 97 | + |
| 98 | +**Loader API version.** Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. |
| 99 | + |
| 100 | +### `context` |
| 101 | + |
| 102 | +**The directory of the module.** Can be used as context for resolving other stuff. |
| 103 | + |
| 104 | +In the example: `/abc` because `resource.js` is in this directory |
| 105 | + |
| 106 | +### `request` |
| 107 | + |
| 108 | +The resolved request string. |
| 109 | + |
| 110 | +In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` |
| 111 | + |
| 112 | +### `query` |
| 113 | + |
| 114 | +A string. The query of the request for the current loader. |
| 115 | + |
| 116 | +In the example: in loader1: `"?xyz"`, in loader2: `""` |
| 117 | + |
| 118 | +### `data` |
| 119 | + |
| 120 | +A data object shared between the pitch and the normal phase. |
| 121 | + |
| 122 | +### `cacheable` |
| 123 | + |
| 124 | +```typescript |
| 125 | +cacheable(flag = true: boolean) |
| 126 | +``` |
| 127 | + |
| 128 | +Make this loader result cacheable. By default it's not cacheable. |
| 129 | + |
| 130 | +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. |
| 131 | + |
| 132 | +### `loaders` |
| 133 | + |
| 134 | +```typescript |
| 135 | +loaders = [{request: string, path: string, query: string, module: function}] |
| 136 | +``` |
| 137 | +
|
| 138 | +An array of all the loaders. It is writeable in the pitch phase. |
| 139 | +
|
| 140 | +In the example: |
| 141 | +
|
| 142 | +```javascript |
| 143 | +[ |
| 144 | + { request: "/abc/loader1.js?xyz", |
| 145 | + path: "/abc/loader1.js", |
| 146 | + query: "?xyz", |
| 147 | + module: [Function] |
| 148 | + }, |
| 149 | + { request: "/abc/node_modules/loader2/index.js", |
| 150 | + path: "/abc/node_modules/loader2/index.js", |
| 151 | + query: "", |
| 152 | + module: [Function] |
| 153 | + } |
| 154 | +] |
| 155 | +``` |
| 156 | +
|
| 157 | +### `loaderIndex` |
| 158 | +
|
| 159 | +The index in the loaders array of the current loader. |
| 160 | +
|
| 161 | +In the example: in loader1: `0`, in loader2: `1` |
| 162 | +
|
| 163 | +### `resource` |
| 164 | +
|
| 165 | +The resource part of the request, including query. |
| 166 | +
|
| 167 | +In the example: `"/abc/resource.js?rrr"` |
| 168 | +
|
| 169 | +### `resourcePath` |
| 170 | +
|
| 171 | +The resource file. |
| 172 | +
|
| 173 | +In the example: `"/abc/resource.js"` |
| 174 | +
|
| 175 | +### `resourceQuery` |
| 176 | +
|
| 177 | +The query of the resource. |
| 178 | +
|
| 179 | +In the example: `"?rrr"` |
| 180 | +
|
| 181 | +### `emitWarning` |
| 182 | +
|
| 183 | +```typescript |
| 184 | +emitWarning(message: string) |
| 185 | +``` |
| 186 | +
|
| 187 | +Emit a warning. |
| 188 | +
|
| 189 | +### `emitError` |
| 190 | +
|
| 191 | +```typescript |
| 192 | +emitError(message: string) |
| 193 | +``` |
| 194 | +
|
| 195 | +Emit an error. |
| 196 | +
|
| 197 | +### `exec` |
| 198 | +
|
| 199 | +```typescript |
| 200 | +exec(code: string, filename: string) |
| 201 | +``` |
| 202 | +
|
| 203 | +Execute some code fragment like a module. |
| 204 | +
|
| 205 | +T> Don't use `require(this.resourcePath)`, use this function to make loaders chainable! |
| 206 | +
|
| 207 | +### `resolve` |
| 208 | +
|
| 209 | +```typescript |
| 210 | +resolve(context: string, request: string, callback: function(err, result: string)) |
| 211 | +``` |
| 212 | + |
| 213 | +Resolve a request like a require expression. |
| 214 | + |
| 215 | +### `resolveSync` |
| 216 | + |
| 217 | +```typescript |
| 218 | +resolveSync(context: string, request: string) -> string |
| 219 | +``` |
| 220 | + |
| 221 | +Resolve a request like a require expression. |
| 222 | + |
| 223 | +### `addDependency` |
| 224 | + |
| 225 | +```typescript |
| 226 | +addDependency(file: string) |
| 227 | +dependency(file: string) // shortcut |
| 228 | +``` |
| 229 | + |
| 230 | +Adds a file as dependency of the loader result in order to make them watchable. For example, [html-loader](https://github.com/webpack/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. |
| 231 | + |
| 232 | +### `addContextDependency` |
| 233 | + |
| 234 | +```typescript |
| 235 | +addContextDependency(directory: string) |
| 236 | +``` |
| 237 | + |
| 238 | +Add a directory as dependency of the loader result. |
| 239 | + |
| 240 | +### `clearDependencies` |
| 241 | + |
| 242 | +```typescript |
| 243 | +clearDependencies() |
| 244 | +``` |
| 245 | + |
| 246 | +Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. |
| 247 | + |
| 248 | +### `value` |
| 249 | + |
| 250 | +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). |
| 251 | + |
| 252 | +### `inputValue` |
| 253 | + |
| 254 | +Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). |
| 255 | + |
| 256 | +### `options` |
| 257 | + |
| 258 | +The options passed to the Compiler. |
| 259 | + |
| 260 | +### `debug` |
| 261 | + |
| 262 | +A boolean flag. It is set when in debug mode. |
| 263 | + |
| 264 | +### `minimize` |
| 265 | + |
| 266 | +Should the result be minimized. |
| 267 | + |
| 268 | +### `sourceMap` |
| 269 | + |
| 270 | +Should a SourceMap be generated. |
| 271 | + |
| 272 | +### `target` |
| 273 | + |
| 274 | +Target of compilation. Passed from configuration options. |
| 275 | + |
| 276 | +Example values: `"web"`, `"node"` |
| 277 | + |
| 278 | +### `webpack` |
| 279 | + |
| 280 | +This boolean is set to true when this is compiled by webpack. |
| 281 | + |
| 282 | +T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. |
| 283 | + |
| 284 | +### `emitFile` |
| 285 | + |
| 286 | +```typescript |
| 287 | +emitFile(name: string, content: Buffer|String, sourceMap: {...}) |
| 288 | +``` |
| 289 | + |
| 290 | +Emit a file. This is webpack-specific. |
| 291 | + |
| 292 | +### `fs` |
| 293 | + |
| 294 | +Access to the `compilation`'s `inputFileSystem` property. |
| 295 | + |
| 296 | +### `_compilation` |
| 297 | + |
| 298 | +Hacky access to the Compilation object of webpack. |
| 299 | + |
| 300 | +### `_compiler` |
| 301 | + |
| 302 | +Hacky access to the Compiler object of webpack. |
| 303 | + |
| 304 | +### `_module` |
| 305 | + |
| 306 | +Hacky access to the Module object being loaded. |
| 307 | + |
| 308 | +### Custom `loaderContext` Properties |
| 309 | + |
| 310 | +Custom properties can be added to the `loaderContext` by either specifying values on the `loader` proprty on your webpack [configuration](/configuration), or by creating a [custom plugin](/api/plugins) that hooks into the `normal-module-loader` event which gives you access to the `loaderContext` to modify or extend. |
0 commit comments