手写webpack的loader

一、概念

帮助webpack将不同类型的文件转换为webpack可识别的模块。

二、Loader执行顺序

分类

  • pre:前置loader
  • normal:普通loader
  • inline:内联loader
  • post:后置loader

执行顺序

  • 4类loader的执行顺序为per>normal>inline>post
  • 相同优先级的loader执行顺序为:从右到左,从下到上。
    例如:
js 复制代码
// 此时loader执行顺序:loader3 - loader2 - loader1
module: {
  rules: [
    {
      test: /\.js$/,
      loader: "loader1",
    },
    {
      test: /\.js$/,
      loader: "loader2",
    },
    {
      test: /\.js$/,
      loader: "loader3",
    },
  ],
},
js 复制代码
// 此时loader执行顺序:loader1 - loader2 - loader3
module: {
  rules: [
    {
      enforce: "pre",
      test: /\.js$/,
      loader: "loader1",
    },
    {
      // 没有enforce就是normal
      test: /\.js$/,
      loader: "loader2",
    },
    {
      enforce: "post",
      test: /\.js$/,
      loader: "loader3",
    },
  ],
},

使用Loader 的方式

  • 配置方式:在 webpack.config.js 文件中指定 loader。(pre、normal、post loader)
  • 内联方式:在每个 import 语句中显式指定 loader。(inline loader)

inline Loader

用法:import Styles from 'style-loader!css-loader?modules!./styles.css';

含义:使用 css-loader 和 style-loader 处理 styles.css 文件通过 ! 将资源中的 loader 分开

inline loader 可以通过添加不同前缀,跳过其他类型 loader。! 跳过 normal loader。

复制代码
import Styles from '!style-loader!css-loader?modules!./styles.css';

-! 跳过 pre 和 normal loader。

复制代码
import Styles from '-!style-loader!css-loader?modules!./styles.css';

!! 跳过 pre、 normal 和 post loader。

复制代码
import Styles from '!!style-loader!css-loader?modules!./styles.css';

三、开发一个Loader

最简单的Loader

js 复制代码
//loader/loader1.js
module.exports = function (content){
	console.log(content)
	return content;
}

他接受要处理的源码作为参数,输出转换后的js代码

Loader接受的参数

  • content 源文件的内容
  • map sourceMap数据
  • meta 数据可以是任何内容

Loader分类

  1. 同步Loader
js 复制代码
module.exports = function (content ,map ,meta) {
    /* 
        第一个参数:err代表是否有错误
        第二个参数:content处理后的内容
        第三个参数:sorce-map继续传递sourcemap 
        第四个参数:meta给下一个loader传递参数
    */
    //相比于普通return方式这种写法可以传递更多参数,不中断loader执行。
    //return content 
    this.callback(null,content,map,meta)
}
  1. 异步Loader

由于同步计算过于耗时,在 Node.js 这样的单线程环境下进行此操作并不是好的方案,我们建议尽可能地使你的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。

js 复制代码
module.exports = function (content, map, meta) {
  const callback = this.async();
  // 进行异步操作
  setTimeout(() => {
    callback(null, result, map, meta);
  }, 1000);
};
  1. Raw Loader

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

js 复制代码
module.exports = function (content) {
  // content是一个Buffer数据
  return content;
};
module.exports.raw = true; // 开启 Raw Loader
  1. Pitching Loader

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

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

手写banner-loader

作用:给代码添加文本注释包括作者、日期

js 复制代码
//loader/banner-loader.js
const schema =  require("./schema.json");
module.exports  = function (content,map,meta){
    //获取Loader的options,同时对options做校验
    //schema 是options的校验规则。
    const options = this.getOptions(schema);
    const date = (new Date()).toLocaleString()
    
    const prefix = `
      /* 
        Author ${options.author}
        Date ${date}
      */
    `
    return `${prefix} \n ${content}`
}

下面是schema.json文件

json 复制代码
{
    "type":"object",
    "porperties":{
        "author":{
            "type":"string"
        }
    },
    "addtionalProperties":false
}

在webpack.config.js中配置

js 复制代码
//...省略
    module: {
        rules: [
            {
                test:/\.js$/,
                loader:'./loader/banner-loader',
                options:{
                    author:'老王'
                }
            }
        ]
    },

在dist压缩文件main.js中

js 复制代码
/***/ "./src/main.js":
/*!*********************!*\
  !*** ./src/main.js ***!
  \*********************/
/***/ (() => {

eval("\n      /* \n        Author 老王\n        Date 2024/1/13 14:32:11\n      */\n     \n console.log('hello main')\n\n//# sourceURL=webpack:///./src/main.js?");

/***/ })

/******/ 	});
/************************************************************************/
相关推荐
Pedantic1 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘1 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆1 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师2 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆2 小时前
VSCode自动格式化三要素
前端
爱勇宝3 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen4 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518136 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端