webpack的loader配置应该谁都会,讲道理,我们会使用loader,会配置loader就够了。今天只是了解loader的基本概念和基本的运行原理,了解了就能自己写一个loader了,至于手写一些复杂的loader目前就算了。
先说说webpack中文网对loader的一些介绍:
loader是用于对模块的源代码进行转换,可以在你import或加载模块时预处理文件。loader可以将不同语言(typescript)转换成JavaScript、将内联图像转成data URL、在JavaScript中import css文件。loader有一些特性,loader 支持链式传递。一组链式的 loader 将按照相反的顺序执行。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回webpack所预期的JavaScript。loader可以是同步也可以是异步。loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。内容不多,其实可以去看看,还有几个特性可以看看。
需要注意的几点:
loader就是一个函数,要返回js的脚本
loader要遵循单一原则,只做一件事,所以要有style-loader、css-loader,而不是整合成一个loader
可以链式调用,从右往左,从下往上
loader要是无状态的,不同模块之间不保存状态,要能够单一运行。
配置好常规配置,然后loader指向自己写的loader(loader/loader.js):
use: path.resolve(__dirname, 'loader', 'loader')
需要绝对路径,也可以这样:
resolveLoader: {
// alias: {
// loader: path.resolve(__dirname, 'loader', 'loader')
// },
modules: ['node_modules', path.resolve(__dirname, 'loader')]
}
两个选一个,第一个是别名,第二个是loader默认从node_module里面找,找不到就到loader文件夹里面找。
loade.js里面内容:
function loader(resource){
console.log(resource)
return resource
}
module.exports = loader;
参数resource就是js的代码,如果return的内容是数字,就会报错,因为要返回预期的JavaScript:
Module build failed: Error: Final loader (./loader/loader.js) didn't return a Buffer or String
控制台打印(index.js引入a.js):
loader的运行原理挺简单的,并不复杂,复杂的是要怎么去处理传递进来的代码。
说说loader的几个模式,优先级顺序:pre、normal、inline、post
清空index.js,然后引入loader1、loader2、loader3,分别打印文件名:
use: ['loader1', 'loader2', 'loader3']
这边没有设置什么,就是默认顺序,都是normal,接着设置:
{
test: /.js$/,
use: 'loader1',
enforce: 'pre'
},
{
test: /.js$/,
use: 'loader2'
},
{
test: /.js$/,
use: 'loader3',
enforce: 'post'
}
打印出来:
inline比较特殊,如果上面都不干预,新建一个inline-loader.js,引入文件的时候使用:
let str = require('-!inline-loader!./a.js')
打印:
-!表示不再用pre和normal的loader处理,所以这边走完inline-loader之后只执行设置post的loader3,另外还有两种,!不走normal,!!什么都不走,只走inline-loader。
loader有两部分组成,pitch和normal,先执行pitch,如果pitch有返回值,则直接跳过接下去的loader直接返回,包括自己,给每个loader加pitch方法并打印:
loader.pitch = function(resource){
console.log('loader1 pitch')
}
打印:
这边先执行pitch再执行normal,我如果在loader3 pitch这边添加return ‘’,打印:
loader还有很多api,比如异步loader的this.async(),this.callback返回多个结果的函数、通过loader-utils(需要自己安装依赖)获取配置的options参数等等,可以去官网看一下:
https://www.webpackjs.com/api/loaders/#this-target
loader大概就先了解到这样,async和callback使用其实更重要,如果要编写有用的loader要好好研究,今天就不去尝试。 loader运行过程其实不难,难得应该是内部的解析过程。