美文网首页
编写一个 loader

编写一个 loader

作者: jluemmmm | 来源:发表于2020-12-30 21:10 被阅读0次

loader 是一个导出为一个函数的 node 模块,该函数在 loader 转换资源的时候调用。给定的函数将调用 loader模块,并通过 this 上下文访问。

单个 loader 调用

当一个loader 在资源中使用,这个loader只能传入一个参数,这个参数是一个包含资源文件内容的字符串。同步 loader可以返回一个代表模块转化后的值,loader也可以通过使用this.callback(err, value)函数,返回任意数量的值。错误传递给 this.callback函数,或者放入同步 loader中。

多个loader

链式调用多个 loader 时,会以相反顺序执行。

  • 最后的 loader 最早调用,将会传入原始资源内容。
  • 第一个 loader 最后调用,期望值传出 js 和 sourcemap(可选)
  • 中间的 loader 执行时,会传入前一个 loader 传出的结果

编写 loader 注意事项

1. 简单易用

loader 应该只做单一任务,使得loader易于维护,可以在更多场景链式调用

2. 链式调用

使用loader可以链式调用的优势,写五个简单的loader实现五项任务,而不是一个loader实现五项任务。

3. 模块化

保证输出模块化,loader生成的模块于普通模块遵循相同的设计原则

4. 无状态

确保loader 在不同模块转换之间不保存状态,每次运行都独立于其他编译模块以及相同模块之前的编译结果

5. loader utilities

利用 loader-utils 包,提供非常多的有用工具,常用的工具是获取传递给 loader 的选项。schema-utils 包配合 loader-utils,用于保证 loader 选项,进行与 JSON schema结构一致性的校验。

import { getOptions } from 'loader-utils'
import validateOptions from 'schema-utils'

const schema = {
  type: 'object',
  properties: {
    test: {
      type: 'sting'
    }
  }
}

export default function(source) {
  const options = getOptions(this)
  validateOptions(schema, options, 'Example loader')
  /* 对资源应用进行一些转换 */
  return `export default ${ JSON.stringify(source) }`
}

6. loader 依赖

如果一个loader使用外部资源(例如,从文件系统读取),必须声明它。这些信息用于使缓存 loaders 无效,以及在观察者模式下重新编译。

import path from 'path'
export default function(source) {
  var callback = this.async()
  var headPath = path.resolve('header.js')

  this.addDependency(headPath)

  fs.readFile(headPath, 'utf-8', function(err, header) {
    if (err) return callback(err)
    callback(null, header + "\n" + source)
  })
}

7. 模块依赖

根据模块类型,可能会有不同的模块指定依赖关系。如在 css 中,使用 @importurl(...) 语句来声明依赖。这些模块应由模块系统解析。可以通过以下两种方式的一种来实现:

  • 通过将其转化成 require 语句
  • 使用this.resolve函数解析路径

css-loader中,将 @import 语句转化为 require 其他样式文件,将 url(...) 替换为 require 引用文件,实现将依赖关系转化为 require 声明

less-loader,无法将每个 @import 转化为 require,因为所有 .less文件中的变量和混合跟踪必须经历一次编译。因此,less-loader 将 less 编译器进行扩展,自定义路径解析逻辑,然后通过 webpack 的 this.resolve解析依赖。

如果语言只支持相对 url,如 url(file)总是指向 ./file,通过 ~来指定已安装的模块(如 node_modules中的模块)。所以对于url,相当于 url('~some-library/img.jpg')

8. 通用代码

避免在 loader 处理的每个模块中生成通用代码。应该在 loader 中创建一个运行时文件,并生成 require 语句以引用该共享模块。

9. 绝对路径

不要在模块代码中插入绝对路径,当项目根路径变化时,文件绝对路径也会变化。loader-utils 中的stringifyRequest方法,可以将绝对路径转化为相对路径。

10. 同等依赖

如果你的 loader 简单包裹另外一个包,应该把这个包作为 peerDependency 引入。这种方式允许应用程序开发者在必要的情况下,在package.json中指定所需的确定版本。

编写一个最最简单的 loader

const _loaderUtils = require('loader-utils')

module.exports = (source) => {
  const options = _loaderUtils.getOptions(this);
  console.log(this)
  source = source.replace(/\[name\]/g, ''); 
  return `export default ${ JSON.stringify(source) }`;
};


rules 中通过指向具体的路径使用

{
  test: /\.txt$/,
  use: {
    loader: path.resolve(__dirname, './test/loader.js'),
    options: {
      name: 'Alice'
    }
  }
}

相关文章

  • 编写一个webpack的loader(2)

    目录 介绍一下raw-loader 编写一个raw-loader的demo,watermark-loader 个人...

  • 编写一个 loader

    loader 是一个导出为一个函数的 node 模块,该函数在 loader 转换资源的时候调用。给定的函数将调用...

  • 编写 webpack loader

    loader loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加...

  • 编写 webpack Loader

    loader 类型 pre post normal inline 行内 loader 1、2、3 通过修改 loa...

  • 怎么编写一个 webpack loader

    编写 loader 前需要知道 webpack loader 的执行循序?从右到左执行。 为什么 webpack ...

  • 如何编写一个Loader

    创建一个demo(make_loader) 新建一个文件,名字为make_loader 在make_loader目...

  • Webpack4.0原理

    1. 编写一个Loader 1.1 初始化项目 创建文件夹make-loader 初始化npm包➜ make-lo...

  • Webpack原理—编写Loader和Plugin

    编写 Loader Loader就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多...

  • webpack配置之自定义loader

    自己编写一个Loader的过程是比较简单的 Loader就是一个函数,声明式函数,不能用箭头函数拿到源代码,作进一...

  • 编写 webpack loader(一)

    用过webpack的人都知道处理各种资源的时候要用到loader,比如babel-loader可以将ES6转化为E...

网友评论

      本文标题:编写一个 loader

      本文链接:https://www.haomeiwen.com/subject/tcxkoktx.html