手写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?");

/***/ })

/******/ 	});
/************************************************************************/
相关推荐
FungLeo4 分钟前
成为全栈·Node 后端篇·全文搜索:从 LIKE 到全文索引
node.js·全文索引·模糊搜索·全文搜索·成为全栈·like 搜索
mldong2 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排3 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60614 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角5 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!5 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰5 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi7 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen7 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马8 小时前
AI源码分析:拆解模型底层实现逻辑
前端