学习webpack loader,最后模拟style-loader、less-loader
什么是loader
- loader是一个函数,用来把文件转换成webpack识别的模块。
loader API
- this.callback,一个可以同步或者异步调用的可以返回多个结果的函数。
- this.async,异步的loader,返回this.callback
如何编写loader
设置
- webpack默认从node_modules里找loader
- 直接引入loader
{
test: /\.js$/
use: [
{
loader: path.resolve('path/to/loader.js'),
options: {/* ... */}
}
]
}
复制代码
- 如果有多个loader的目录,可以设置loader的目录,webpack会从设置的目录里找到loader
resolveLoader: {
modules: [
'node_modules',
path.resolve(__dirname, 'loaders') //自己开发的loaders
]
}
复制代码
简单用法
- 当使用一个loader时,这个loader函数只有一个参数,参数是包含文件内容的字符串。
- 同步loader可以返回一个代表模块转化后的简单的值
- loader的返回值是javascript代码字符串或者是Buffer
//css-loader 把css解析成webpack识别的模块
module.exports = function(source) {
return `module.exports=${source}`;
}
复制代码
复杂用法
- 当配置多个loader时,loader的执行顺序时从右往左,右边的执行结果作为参数传到左边。
- less-loader把less转化成css,传给css-loader,css-loader把结果给style-loader,style-loader返回javascript代码字符串。
{
test:/\.less$/,
use:[
'style-loader','css-loader','less-loader'
]
}
复制代码
编写原则
- 单一职责。每个loader只负责一件事情。
- 使用链式调用,确保loader的依赖关系的正确。
- 无状态性,确保loader在不同模块转换之间不保存状态。每次运行都应该独立于其他编译模块以及相同模块之前的编译结果。
loader工具库
- loader-utils,可以获取loader的options
- schema-utils,校验loader的options的合法性
模拟less-loader、css-loader、style-loader
- less-loader负责把less编译成css
const less = require('less');
module.exports = function (source) {
less.render(source, (e, output)=>{
this.callback(e,output.css); //把编译后的css返回给下一个loader
});
};
复制代码
- css-loader负责把css交给下一个loader
module.exports = function (source) {
return source; //source是上个loader的返回值,如果没有上一个loader,则是css的内容
};
复制代码
- style-loader把css添加到style标签里
module.exports = function (source) {
return `const e = document.createElement('style');
e.innerHTML = ${JSON.stringify(source)};
document.head.appendChild(e);`;
};
复制代码
- 虽然每个loader功能简单,但是loader之前职责单一,方便扩展。
总结
webpack loader的功能远不止这些,本文算是编写loader的"套路"入门篇。