实现一下几个简单的loader

一 关于loader

1、理解

loader其实就是一个函数,它可以通过接受一些参数,处理特定文件后暴露出去

module.exports = function loader1(content) {
  console.log("hello loader");
  return content;
};

接收的参数
content 源文件的内容
map SourceMap 数据
meta 数据,可以是任何内容

2、分类

1、同步loader
module.exports = function (content, map, meta) {
  // 传递map,让source-map不中断
  // 传递meta,让下一个loader接收到其他参数
  this.callback(null, content, map, meta);
  return; // 当调用 callback() 函数时,总是返回 undefined
};
2、异步loader
module.exports = function (content, map, meta) {
  const callback = this.async();
  // 进行异步操作
  setTimeout(() => {
    callback(null, result, map, meta);
  }, 1000);
};
3、raw loader

默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。 通过设置 raw 为 true,loader 可以接收原始的 Buffer。

module.exports = function (content) {
  // content是一个Buffer数据
  return content;
};
module.exports.raw = true; // 开启 Raw Loader
4、pitch loader

webpack 会先从左到右执行 loader 链中的每个 loader 上的 pitch 方法(如果有),然后再从右到左执行 loader 链中的每个 loader 上的普通 loader 方法。
在这个过程中如果任何 pitch 有返回值,则 loader 链被阻断。webpack 会跳过后面所有的的 pitch 和 loader,直接进入上一个 loader 。

module.exports = function (content) {
  return content;
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  console.log("do somethings");
};

更多loaderAPI参考:webpack官方文档

二、自己实现一些loader

一、clean-log-loader

用于生产环境构建项目去除代码中的console.log()

module.exports = function(content) {
    return content.replace(/console\.log\(.*\);?/g, "")
}

二、babel-loader

需要借助babel的一些预设和工具,参考babel官网

js

const babel = require("@babel/core")
const schema = require("./schema.json")

module.exports = function(content) {
    const options = this.getOptions(schema);
    // 使用异步loader
    const callback = this.async();
    // 使用babel对js代码进行编译
    babel.transform(content, options, function(err, result) {
        callback(err, result.code);
    });
}

schema标准

{
    "type": "object",
    "properties": {
        "presets": {
            "type": "array"
        }
    },
    "additionalProperties": true
}

三、style-loader

js


const styleLoader = () => {}

/**
 * 因为直接在style-loader里面接收到的是css-loader传递过来的内容,是一段js代码
 * 而我们需要的是css-loader那一段js代码执行完成之后暴露出来的样式文件,所以这里使用pitch
 * @param {*} remainingRequest 
 * @returns 
 */
styleLoader.pitch = function(remainingRequest) {
    // 获得css-loader处理结果的路径
    /*
     * remainingRequest是一个绝对路径,需要转换为相对于当前上下文的相对路径
     */
    /**
     * remainingRequest:
     * F:\webpack-loader\webpack-loader-1\node_modules\css-loader\dist\cjs.js!F:\webpack-loader\webpack-loader-1\src\styles\index.css
     * 
     * relativeRequest:
     *  ../../node_modules/css-loader/dist/cjs.js!./index.css
     */
    const relativeRequest =
        remainingRequest
        .split('!')
        .map((part) => this.utils.contextify(this.context, part))
        .join('!');

    /**
     * 创建script语句并暴露出去,提供给构建工具,在打包时执行
     */
    const scripts = `
        import style from "!!${relativeRequest}"
        const styleEl = document.createElement('style')
        styleEl.innerHTML = style
        document.head.appendChild(styleEl)
    `;
    // style-loader是第一个loader, 由于return导致熔断,所以其他loader不执行了(不管是normal还是pitch)
    return scripts;
}

module.exports = styleLoader
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值