cloud.tencent.com/developer/a… webpack 中通过compilation对象进行模板编译时,会首先进行匹配loader处理文件得到结果(string/buffer),之后才会输出给webpack进行编译。 loader 本质上就是一个函数,通过它我们可以在webpack处理特定资源文件之前进行提前处理。
Loader配置相关api:常用基础配置参数
/**
* test 是一个正则表达式,我们会对应的资源文件根据test规则去匹配,如果匹配到,那么该文件
* 就会交给loader去处理。
* use 表示匹配到test中匹配到的文件应该使用哪个loader的规则去处理,use可以是一个字符串,
* 也可以是数组
* use 为一个数组时表示多个loader依次处理匹配的资源,按照从右到左(从上到下)的顺序去处理
* enforce参数:有俩个值: pre、post
* loader中存在一个enforce参数标志这loader的顺序,比如这样一份配置文件:
* enforce: pre 我们称之为前置loader
* enforce: post 我们称之为后置loader
*/
module.exports = {
module: {
rules: [
{ test: '/.css$/', use:'sass-loader', enfore: 'pre' },
{ test: '/.css$/', use:'css-loader' },
{ test: '/.css$/', use:'style-loader', enfore: 'post' },
]
}
}
Loader的执行顺序:
pre loader 、 普通loader、 后置loader
webpack 中配置Loader的常用的三种方式
第一种:绝对路径的方式
在项目内部存在一些未发布的自定义loader,直接使用绝对路径的形式指向loader文件所在的地址。
const path = require('path')
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: path.resolve(__dirname, '../../xxx-loader.js')
}
]
}
}
第二种方式可以使用webpack 中的resolve Loader的别名alias别名进行配置 或者
const path = require('path')
// webpack.config.js
module.exports = {
...
resolveLoader:{
alias: {
'babel-loader': path.resolve(__dirname, '../../loaders/xxx-loader.js')
}
},
module: {
rules: [
{
test: /\.ts$/,
laoder: 'babel-loader'
}
]
}
}
第三种:resolveLoader中的modules resolveLoader.modules 的默认值是【node_modules】
const path = require('path')
// webpack.config.js
module.exports = {
...
resolveLoader: {
modules: [
path.resolve(__dirname, '../../loaders/')
]
},
module: {
rules: [
{
test: /\.ts$/,
laoder: 'babel-loader'
}
]
}
}
Loader的种类:
根据配置文件的enforce参数可以分为: pre loader / normale loader / post loader / inline loader
默认loader 的执行顺序
webpack 还支持内联的方式配置loader
通过!分割使用loader的方式称之为行内loader
通过内联 import语句添加前缀,可以覆盖配置中的有pre loader / normal loader /post loader
import styles from '!style-loader!css-loader?modules!./styles.css';
使用! 前缀 将会禁用所有normal loader(普通loader)
import styles from '!style-loader!css-loader?modules!./style.css';
使用!!前缀,将禁用所有已配置的loader(preload 、post loader 、loader)
import styles from '!!style-loader!css-loader?modules!./style.css';
使用-!前缀,将禁用已配置的pre loader和loader ,但是不禁用post loader
import styles from '-!style-loader!css-loader?modules!./style.css';
loader的执行阶段其实分为俩个阶段:pitch阶段/normal阶段
loader 的 pictch 阶段
- 在处理资源文件之前,首先会经历pitch阶段 2)pitch 结束后,读取资源内容,将读取到的内容交给正常阶段的loader去处理。 Pitch 阶段: loader的pitch方法按照:post loader -->inline loader --> normal loader -->pre loader的顺序调用 Picth阶段返回全是undefined ,一旦在某一个loader的pitch 返回一个非undefined的值就会发生熔断效果。 Normal阶段:loader的正常调用顺序是:pre loader --> normal loader --> inline loader --> post loader的顺序调用
同步/异步loader
同步loader: loader 在normal 阶段返回值可以通过函数内部的return 语句进行返回,同时如果需要返回多个值,也可以通过this.callback()表示loader结束时传入多个值返回,this.callback第一个参数一定是表示错误是否存在。 异步loader的实现方案:
- 返回promise
function asyncLoader() {
return new Promise((relose) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
}
- 通过在loader内部调用this.async()函数将loader变为异步,同时this.async会返回一个callback的方式,只有当我们调用callback方法才会继续执行后续阶段处理。
function asyncloader() {
let callback = this.async()
callback()
}
Normal loader
normal loader默认接受一个参数,就是需要处理的 文件内容,存在多个loader,它的参数会受上一个loader的影响。 同时normal loader默认会有一个返回值,这个返回值会链式调用给下一个loader作为入参,当最后loader执行完成以后,会将这个返回值返回给webpack进行编译。 normal loader的最后一个阶段一定返回一个js代码(一个module的代码) Pitch loader loader pitch 阶段接受三个参数:分别是remainingRequest、previousRequest、data remainingRequest 表示剩余需要处理的loader的绝对路径以“!”分割组成的字符串。与剩余loader有没有patch属性没有关系。 previousRequest 表示已经处理过的loader按照!组成的字符串。 data 默认是一个空对象。 loader.raw raw == false normal loader的source 是一个字符串,默认行为。 raw == true, normal loader的source接受一个Buffer类型。