# loader开发小记

# 开发loader的工具类

  • loader-utils 提供很多辅助loader的方法
  • schema-utils 参数校验
  • mime 获取文件类型

# 在异步处理后返回代码

  • 通过this.async()来返回代码
  • asyncReturn 第一个参数 error,第二个参数 source
function loader(source){
  let asyncReturn = this.async()
  setTimeout(()=>{
    // 第一个参数 如果有什么错误,传在第一个参数中,如果没有给 null
    // 第二个参数为 异步处理后的代码
    asyncReturn(null,source)
  },1000)
}
module.exports = loader
1
2
3
4
5
6
7
8
9

# 处理文件

  • loader匹配到的文件,保持文件的源文件格式
  • loader增加属性raw来处理
function loader(source){
  // 此时source就是匹配到的文件的源文件形式
  // 如果匹配到的图片等,那这里就是图片的二进制
}
loader.raw = true
module.exports = loader
1
2
3
4
5
6

# 通过loader生成文件

  • 通过loader的this.emitFile实现
function loader(source){
  // 第一个参数文件名,第二个参数文件内容
  this.emitFile('generatorFile.js','生成一个JS文件')
  return source
}
module.exports = loader
1
2
3
4
5
6

# css-loader简单实现

  • 下面会用到正则表达式的exec, 根据返回值就可以看出exec的功能
  • 正则表达式reg有一个lastIndex,它代表匹配的字符串的后面一个字符串的索引,根据这个索引可以继续向下遍历查找
let reg = /\"(.+?)\"/g
let str = 'this is a "husky" , "are" you scared'
let matches = reg.exec(str)
console.log(matches);
// [
//   '"husky"',
//   'husky',
//   index: 10,
//   input: 'this is a "husky" , "are" you scared',
//   groups: undefined
// ]
console.log(reg.lastIndex); // 17
1
2
3
4
5
6
7
8
9
10
11
12
  • 主要是对引入的资源进行处理例如url('资源路径')
  • 首先用正则匹配全部的url('资源路径')
  • 我们声明一个arr数组,初始值为let list = [],后面向arrpush的模板为arr.push(list.push(${source}))
  • 最后通过arr.join('\r\n')来连接,拼成一段代码
  • while中主要就是将url('路径')转成url(require('路径'),因为require可以被webpack进行处理
function loader(source){
  let reg =/url\((.+?)\)/
  let pos = 0
  let current;
  let arr = ['let list = []']
  while(current = reg.exec(source)){
    let [matchUrl, group, frontIndex] = current
    arr.push(`list.push(${JSON.stringify(source.slice(pos, frontIndex))})`)
    arr.push(`list.push('url('+require(${group})+')')`)
    pos = reg.lastIndex
  }
  arr.push(`list.push(${JSON.stringify(source.slice(pos, frontIndex))})`)
  arr.push(`module.exports = list`) 
  return arr.join('\r\n')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Last Updated: 1/23/2022, 10:16:22 AM