webpack的使用离不开loader,搞清楚loader的基本运行原理能有效的让咱们搞清楚webpack的总体工做流程。css
Loader 是支持链式执行的,如处理 sass 文件的 loader,能够由 sass-loader、css-loader、style-loader 组成,由 compiler 对其由右向左执行,第一个 Loader 将会拿到需处理的原内容,上一个 Loader 处理后的结果回传给下一个接着处理,最后的 Loader 将处理后的结果以 String 或 Buffer 的形式返回给 compiler。 这种链式的处理方式却是和 gulp 有点儿相似,当然也是但愿每一个 loader 只作该作的事,纯粹的事,而不但愿一箩筐的功能都集成到一个 Loader 中。node
{ module: { loaders: [{ test: /\.scss$/, loader: 'style!css!sass' }] } };
若是你所写的 Loader 须要依赖其余模块的话,那么一样以 module 的写法,将依赖放在文件的顶部声明,让人清晰看到webpack
// Module dependencies. var fs = require("fs"); module.exports = function(source) { return source; };
上面使用返回 return 返回,是由于是同步类的 Loader 且返回的内容惟一,若是你但愿将处理后的结果(不止一个)返回给下一个 Loader,那么就须要调用 Webpack 所提供的 API。 通常来讲,构建系统都会提供一些特有的 API 供开发者使用。Webpack 也如此,提供了一套 Loader API,能够经过在 node module 中使用 this 来调用,如 this.callback(err, value...),这个 API 支持返回多个内容的结果给下一个 Loader 。web
// return multiple result module.exports = function(source, other) { // do whatever you want // ... this.callback(null, source, other); };
总结:gulp
而实际上,掌握上面所介绍的内容及思想,就能够开始写一个简单的 Loader 了,不是吗? 由上所说的,在你的 Loader 中,你能够拿到须要处理的文件内容,而且知道了处理后的结果应该怎么去返回,在中间部分,你能够以正常使用 node 的姿态对内容进行怎样的处理,Do Whatever You Want,Loader 没有其余特殊要求。缓存
上半部分的介绍虽然确实能搭建起一个普通的 Loader 了,但这样就够了吗?sass
从提升执行效率上,如何处理利用缓存是极其重要的。 Mac OS 会让内存充分使用、尽可能占满来提升交互效率。回到 Webpack,Hot-Replace 以及 React Hot Loader 也充分地利用缓存来提升编译效率。 Webpack Loader 一样能够利用缓存来提升效率,而且只需在一个可缓存的 Loader 上加一句 this.cacheable(); 就是这么简单异步
// 让 Loader 缓存 module.exports = function(source) { this.cacheable(); return source; };
不少 Loader 都是能够缓存的,但也有例外。能够缓存的 Loader 须要具有可预见性,不变性等等async
异步并不陌生,当一个 Loader 无依赖,可异步的时候我想都应该让它再也不阻塞地去异步。在一个异步的模块中,回传时须要调用 Loader API 提供的回调方法 this.async(),使用起来也很简单工具
// 让 Loader 缓存 module.exports = function(source) { var callback = this.async(); // 作异步的事 doSomeAsyncOperation(content, function(err, result) { if(err) return callback(err); callback(null, result); }); };
pitching Loader
前面所述的 Loader 从右到左链式执行。这种说法实际说的是 Loader 中 module.exports 出来的执行方法顺序。在一些场景下,Loader 并不依赖上一个 Loader 的结果,而只关心原输入内容。这时候,从左到右执行并无什么问题。在 Loader 的 module 中,可以使用 module.exports.pitch = function(); pitch 方法在 Loader 中即是从左到右执行的,而且能够经过 data 这个变量来进行 pitch 和 normal 之间传递。
module.exports.pitch = function(remaining, preceding, data) { if(somothingFlag()) { return "module.exports = require(" + JSON.stringify("-!" + remaining) + ");"; } data.value = 1; };
具体的实践能够查看 style-loader,里面就有使用到 pitch。
raw loader
默认的状况,原文件是以 UTF-8 String 的形式传入给 Loader,而在上面有提到的,module 可以使用 buffer 的形式进行处理,针对这种状况,只须要设置 module.exports.raw = true; 这样内容将会以 raw Buffer 的形式传入到 loader 中了
module.exports = function(content) { }; module.exports.raw = true;
Loader API 将提供给每个 Loader 的 this 中,API 可让咱们的调用方式更加地方便,更加灵活。 data pitch loader 中能够经过 data 让 pitch 和 normal module 进行数据共享。 query 则能获取到 Loader 上附有的参数。 如 require("./somg-loader?ls"); 经过 query 就能够获得 "ls" 了。 emitFile emitFile 可以让开发者更方便的输出一个 file 文件,这是 webpack 特有的方法,使用的方法也很直接
emitFile(name: string, content: Buffer|String, sourceMap: {...})
在 file-loader 中有调用到 this.emitFile(url, content); 这个方法,具体能够查看其源码了解。 更多的 API 就不在此 一 一 说明了,建议查看官网文档了解。最后推荐一个工具模块 loader-utils,大多数的 Loader 都会用上它来解析或者使用它提供的一些 util 方法,很方便。
针对 Loader 的基础介绍大体就到这了,很少,但愿这篇文章可以对 Webpack Loader 有一个大体的了解。 更多进阶的方案及实战经验容我再整理整理,迟些输出。