webpack loader原理以及自定义loader

news2024/12/22 21:20:37

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

分类:enforce属性

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

如果不写默认是 normal类型

执行顺序:pre > normal > inline > post

相同等级的,从后往前执行。

//普通loader,执行顺序:loader3,loader2,loader1
module:{
    {
        test:/\.js$/,
        loader:"loader1"
    },
    {
        test:/\.js$/,
        loader:"loader2"
    },
    {
        test:/\.js$/,
        loader:"loader3"
    },

}

//不同级别loader,执行顺序:loader1,loader2,loader3
module:{
    {
        enforce:"pre",
        test:/\.js$/,
        loader:"loader1"
    },
    {
        test:/\.js$/,
        loader:"loader2"
    },
    {
        enforce:"post",
        test:/\.js$/,
        loader:"loader3"
    },

}

使用loader的方式:

配置方式:如上述直接在webpack.config.js文件配置,加上enforce配置。(pre normal post)

内联方式:在每个import语句中显示指定loader(inline)

inline loader用法:

这里使用css-loader,style-loader来处理这个css资源,!是为了隔开各个loader

import Styles from 'style-loader!css-loader?modules!./styles.css'

inline loader可以通过添加不同的前缀,跳过其他类型的loader:

! :表示跳过normal loader,即使在module里配置了style-loader,css-loader,如是normal类型的,也不会执行的。

import Styles from '!style-loader!css-loader?modules!./styles.css'

- ! :表示跳过pre和normal loader,即使在module里配置了style-loader,css-loader,如是pre或normal类型的,也不会执行的。

import Styles from '-!style-loader!css-loader?modules!./styles.css'

 ! ! :表示跳过pre和normal和post loader,即使在module里配置了style-loader,css-loader,如是pre或normal或post类型的,也不会执行的。

import Styles from '!!style-loader!css-loader?modules!./styles.css'

但是一般不会选择使用inline,因为不好复用。


实际使用:

新创建一个项目:

npm init -y
//webpack.config.js
const path = require("path")
const HtmlWebpackPlugin=reuqire("html-webpack-plugin")
module.exports={
    entry:"./src/main.js",
    output:{
        path:path.resolve(__dirname,"./dist"),
        filename:"js/[name].js",
        clean:true
    },
    module:{
        rules:[]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"public/index.html")
        })
    ],
    mode:"development"
}
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>myLoader</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>
//main.js
console.log("hello main");

下载依赖:

npm i webpack webpack-cli html-webpack-plugin -D

尝试打包:npx webpack成功

新建loaders文件夹,建立test-loader.js

loader是一个函数,当webpack解析资源时,会调用响应的loader,传入内容loader会作为参数收到数据并且返回出去,

content 文件内容

map SourceMap相关

meta 别的loader传来的数据

module.exports=function(content,map,meta){
    console.log(content);
    return content
}

webpack.config.js配置:

rules:[
            {
                test:/\.js$/,
                loader:"./loaders/test-loader.js"
            }
        ]

loader的分类

同步loader

// 同步loader 
// 简单写法,只有一个loader
// module.exports=function(content){
//     return content
// }
//多个loader传递,倾向于这个
module.exports=function(context,map,meta){
    //第一个参数:表示是否有错误,有错就是具体内容,无错就是null
    //第二个参数:传递的内容
    //第三个参数:source-map,继续传递
    //第四个参数:meta给其他loader的参数,可以自己写,也可以传上一个下来的

    this.callback(null,context,map,meta)
}

异步loader:异步代码一定要放在异步loader中放在同步中会有问题。

// 异步loader,会等待异步做完后再做其他的事
module.exports=function(context,map,meta){
    const callback = this.async();
    setTimeout(()=>{
        console.log("test2");
        callback(null,context,map,meta)
    },1000)
}

在webpack配置:

rules:[
            // {
            //     test:/\.js$/,
            //     loader:"./loaders/test-loader.js"
            // },
            {
                test:/\.js$/,
                use:[
                    "./loaders/test/test1.js","./loaders/test/test2.js"
                ]
            },
        ]

raw loader:可以写异步或者同步,但是要在最后加一句:module.exports.raw = true

//接收的content数据是buffer类型的
module.exports=function(context,map,meta){
    const callback = this.async();
    setTimeout(()=>{
        console.log("test2");
        callback(null,context,map,meta)
    },1000)
}
module.exports.raw = true

pitch loader:在输出的对象里加上pitch方法,这个方法会在loader执行之前先执行,优先级大于loader,会先把每个loader的pitch方法执行后,在按照顺序执行loader

pitch的执行顺序取决于loader的顺序,同级的话,正向顺序执行,如果loader存在不同的优先级,那么pitch也根据优先级的反向顺序执行。

例如:

全部为normal,从左向右,从上到下执行;

存在pre,normal,post,则从优先级低的开始执行,post=>normal=>pre

pitch全部执行结束后,执行loader

如果在pitch方法中加入了返回值,那么之后的所有pitch以及loader全部都不执行,直接跳到前一个pitch方法对应的loader中继续加载loader。

module.exports=function(context,map,meta){
    console.log("loader1");
    this.callback(null,context,map,meta)
}
module.exports.pitch=function(){
    console.log("pitch1");
}

loader API

说几个常用的,具体的参考:Loader Interface | webpack 中文文档 | webpack 中文文档 | webpack 中文网

 自定义clean-log-loader

module.exports=function(content,map,meta){
    return content.replace(/console\.log\(.*\);?/g,"")
}
rules:[
            // {
            //     test:/\.js$/,
            //     loader:"./loaders/test-loader.js"
            // },
            // {
            //     test:/\.js$/,
            //     use:[
            //         // "./loaders/test/test1.js","./loaders/test/test2.js"
            //         // "./loaders/test/test3.js"
            //         "./loaders/test/test4.js","./loaders/test/test5.js","./loaders/test/test6.js"
            //     ]
            // },
            // {
            //     enforce:"pre",
            //     test:/\.js$/,
            //     loader:"./loaders/test/test4.js"
            // },
            
            // {
            //     enforce:"post",
            //     test:/\.js$/,
            //     loader:"./loaders/test/test6.js"
            // },
            // {
            //     test:/\.js$/,
            //     loader:"./loaders/test/test5.js"
            // },
            {
                test:/\.js$/,
                loader:"./loaders/clean-log-loader.js"
            },
        ]

自定义banner-loader,添加作者:

module.exports=function(context,map,meta){
    //获取传入的options选项
    //schema要符合JSONschema的验证规则
    let schema = {
        "type":"object",
        "properties":{
            "author":{ //author属性
                "type":"string"
            }
        },
        "additionalProperties":false //是否允许添加其他的属性
    }
    let options = this.getOptions(schema)
    const prefix =`
    /*
    *Author:${options.author}
    */
    `
    return prefix+context
}
rules:[
            {
                test:/\.js$/,
                loader:"./loaders/clean-log-loader.js"
            },
            {
                test:/\.js$/,
                loader:"./loaders/banner-loader.js",
                options:{
                    author:"大熊",
                    age:18
                }
            },
        ]

 自定义babel-loader:

下载依赖:

npm i @babel/core @babel/preset-env -D
//babel-loader
const babel = require("@babel/core")
module.exports=function(context,map,meta){
    let schema = {
        "type":"object",
        "properties":{
            "presets":{
                "type":"array"
            }
        },
        additionalProperties:true
    }
    const callback = this.async()
    let options = this.getOptions(schema)
    babel.transform(context,options,function(err,result){
        if(err) callback(err)
        else callback(null,result.code,)
    })
    return context
}
{
                test:/\.js$/,
                loader:"./loaders/babel-loader.js",
                options:{
                    presets:["@babel/preset-env"],
                }
            },

然后打包发现箭头函数转为普通函数。

自定义file-loader:主要针对图片,字体等文件,转为二进制的流。

下载工具:

npm i loader-utils -D
const loaderUtils = require("loader-utils")
module.exports=function(content){
    //1.根据文件内容生成带hash值的文件名
    const interpolateName = loaderUtils.interpolateName(
        this,//上下文this
        "[hash].[ext][query]",//生成文件名称格式
        content// 处理内容
    )
    //interpolateName = `images/${interpolateName}`可以设置输出的路径
    //2.将文件输出
    this.emitFile(interpolateName,content)
    // 3.返回:module.exports = "文件路径(文件名)"
    return `module.exports = "${interpolateName}"`
}
module.exports.raw=true
{
                test:/\.(png|jpe?g|gif)$/,
                loader:"./loaders/file-loader.js",
                type:"javascript/auto" //阻止webpack默认处理图片资源,只用file-loader处理
            },

自定义style loader

module.exports=function(context,map,meta){
    // 不能直接会用style-loader,只能处理样式,不能处理引入的其他资源
    //借助css-loader解决样式中引用其他资源的问题,但是css暴露的是js代码,style-loader需要执行js代码得到返回值,再创建style标签,插入到页面上,不好操作,于是styleloader使用pitch的方式
}
module.exports.pitch = function(remainningRequest){ // remainningRequest剩余要处理的数据
    // 1.将remainningRequest改为相对路径(后面处理只能使用相对路径)
    const relativePath = remainningRequest.split("!").map(absolutePath=>{
        // 返回一个相对路径
        return this.utils.contextify(this.context,absolutePath) //this.context指当前loader所在的目录
    }).join("!")
    // 2.在这里会使用css-loader处理资源,引入css-loader处理后的资源,创建tyle并引入。
    // 添加!!:加载完pitch方法以后不再执行其他的loader,包括pre,normal,post
    // 引入 styke使用内联的用法
    const script = `
        import style from "!!${relativePath}"
        const styleEl = document.createElement('style')
        styleEl.innerHTML= style
        document.head.appendChild(styleEl)
    `
    // 终止后面的loader执行
    return script
}
{
                test:/\.css$/,
                use:["./loaders/style-loader.js","css-loader"]
            },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT会代替数据分析师吗?

大家好&#xff0c;我是朱小五。 最近一个多月以来&#xff0c;ChatGPT已经成为了“家喻户晓”的一个词。3月15日&#xff0c;OpenAI 开发布会宣布GPT-4&#xff0c;紧接着百度发布了自己AI产品文心一言。3月23日&#xff0c;OpenAI 宣布推出插件功能&#xff0c;赋予 ChatGPT …

【Linux Network】网络编程套接字(代码练习)—TCP

目录 1. 常用接口 2. 服务器和客户端的简单流程 3. C/S 回声通信 4. 创建子进程完成 C/S 回声通信 5. 创建孙子进程完成 C/S 回声通信 6. 创建线程完成 C/S 回声通信 7. 使用线程池完成 C/S 回声通信 Linux网络编程在✨ 本篇博文的代码虽然多&#xff0c;但都是修改一点点tcp_s…

动态规划--最长公共子序列

最长公共子序列 动态规划算法思想最长公共子序列题目最优解结构性质递归方程递归实现核心函数测试测试结果 非递归实现(画表)核心函数测试测试结果 求出具体的子序列 动态规划算法思想 动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题﹐即将大规模变成…

通付盾携数智反欺诈应用防护解决方案亮相2023金融展

精彩亮相 银行数字化转型需求背景 数据驱动发展 数字经济时代&#xff0c;数据成为发展的重要资产&#xff0c;以数据驱动决策智能已是未来发展的必然趋势&#xff0c;智能化的决策将是重塑核心竞争力的关键抓手。 人工转向智能 银行的监测管理在一般业务场景中&#xff0c;…

Kyligence Zen 产品体验----设备销量商业数据

介绍 Kyligence Zen 是基于 Kyligence 核心 OLAP能力打造的一站式指标平台。凭借集业务模型、指标管理、指标加工、数据服务等于一体的解决方案,Kyligence 协助过多家金融、零售、制造企业客户搭建企业级指标平台。Kyligence Zen 是 Kyligence 基于丰富的指标平台建设实践打造…

MySQL优化二索引使用

1、索引分类 类型解释全局索引(FULLTEXT)全局索引&#xff0c;目前只有 MyISAM 引擎支持全局索引&#xff0c;它的出现是为了解决针对文本的模糊查询效率较低的问题&#xff0c;并且只限于 CHAR、VARCHAR 和 TEXT 列哈希索引(HASH)哈希索引是 MySQL 中用到的唯一 key-value 键…

《通过并行蒙特卡洛方法合成桡动脉的光电容积图(PPG),及其与体重指数(BMI)的相关性》阅读笔记

目录 一、论文摘要 二、论文十问 Q1&#xff1a;论文试图解决什么问题&#xff1f; Q2&#xff1a;这是否是一个新的问题&#xff1f; Q3&#xff1a;这篇文章要验证一个什么科学假设&#xff1f; Q4&#xff1a;有哪些相关研究&#xff1f;如何归类&#xff1f;谁是这一课…

界面控件DevExpress WPF富文本编辑器,让系统拥有Word功能(二)

DevExpress WPF控件的富文本编辑器允许开发者将文字处理功能集成到下一个WPF项目中&#xff0c;凭借其全面的文本格式选项、邮件合并以及丰富的终端用户选项集合&#xff0c;可以轻松地提供Microsoft Word功能。 DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足…

图片生成功能,ChatGPT和New Bing谁更厉害?

大家好&#xff0c;我是可夫小子&#xff0c;关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加我&#xff0c;备注&#xff1a;chatgpt&#xff0c;拉你进群。 ChatGPT和New Bing虽然是大语言模型&#xff0c;但也有「生成图」的能力&#xff0c;它们该如何调教&#…

人员拥挤检测系统 yolov5

人员拥挤检测系统通过YOLOv5网络模型算法技术&#xff0c;人员拥挤检测系统算法模型对校园/厂区车间/街道等场景的异常的人群聚集&#xff08;出现拥挤情况&#xff09;时&#xff0c;立刻抓拍存档并通知相关人员及时处理。在介绍Yolo算法之前&#xff0c;首先先介绍一下滑动窗…

“AIGC+”将在经济社会各领域持续大放异彩

Gartner 将生成性 Al 列为 2022 年 5大影响力技术之一。MIT 科技评论也将 Al 合成数据列为 2022 年十大突破性技术之一&#xff0c;甚至将生成性 AI&#xff08;Generative Al&#xff09;称为是 AI 领域过去十年最具前景的进展。未来&#xff0c;兼具大模型和多模态模型的 AIG…

第三十六章 Unity动画编辑器

本章节我们简单介绍一下Animation动画编辑窗口&#xff0c;请大家区别之前的Animation组件哦。首先&#xff0c;我们创建一个新的场景“SampleScene4.unity”&#xff0c;然后创建一个Plane和Cube&#xff0c; 给上图中的Cube添加一个木质材质最快的办法&#xff0c;就是将一张…

易基因:2023年植物表观转录组研究的最新进展(m6A+m5C)|深度综述

大家好这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 被称为表观转录组&#xff08;epitranscriptome&#xff09;的RNA修饰正成为基因调控的广泛调控机制。由于绘制转录组范围RNA修饰测序策略的改进&#xff0c;以及分别对沉积、去除和识别RNA修饰的wri…

谈谈HMI 的自动化生成技术

人机界面&#xff08;HMI&#xff09;是自动化领域不可或缺重要组成部分。尽管人机界面系统的设计看上去并没有太大的技术门槛&#xff0c;但是设计一个HMI系统的工作量是巨大的。如果你没有足够的耐心便完成不了一个通用的HMI系统。构建UI控件库是一个似乎永远完不成的事情&am…

【SWAT水文模型】SwatWeather软件使用教程

SwatWeather软件使用教程 1 SwatWeather天气模型发生器1.1 数据输入 2 各功能介绍2.1 计算降水2.2 计算气温2.3 计算辐射2.4 计算风速2.5 计算露点 参考 1 SwatWeather天气模型发生器 SwatWeather.exe 软件只要输入一定格式要求的文件&#xff0c;就可以根据提示进行所需 数据…

深入浅出循环语句—【C语言】

分支语句博客&#xff1a;http://t.csdn.cn/U2kZF 目录 ​编辑 前言&#xff1a;我们先来了解一下break 、continue在循环中的作用 1. while循环 while循环中的break while循环中的continue 2. for循环 for循环省略出错举例&#xff1a; for循环中的break for循环中的co…

JUC多并发编程 AQS

基础解释&#xff1a; 是用来实现锁或者其他同步器组件的公共基础部分的抽象实现,是重量级基础框架及整个JUC体系的基石&#xff0c;主要用于锁分配给“谁”的问题。整体就是一个抽象的 FIFO 队列来完成资源获取线程的排队工作&#xff0c;并通过一个 int 类变量表示持有锁的状…

编译器的优化问题(构造、拷贝)、linux如何取消优化。

编译器优化问题&#xff1a; 不同编译器优化是不一样的&#xff0c;下面代码我都用的vs2019&#xff0c;并且在Debud模式下。&#xff08;Release也会进行优化&#xff09; 下面测试的时候我先采用Debug模式测试。 先写一个简单的类&#xff0c;进行打印测试&#xff1a; c…

从血缘进化论的角度,破解婆媳关系的世纪难题

从血缘进化论的角度&#xff0c;破解婆媳关系的世纪难题 有个粉丝的留言&#xff0c;很长很复杂&#xff0c;是关于他们家的婆媳关系问题。 青木老师&#xff0c;您好&#xff0c;我也有一些问题想咨询您&#xff0c;是关于婆媳关系的&#xff0c;字数有些多&#xff0c;分开…

多线程【线程概念+线程控制】

前置知识 在谈多进程之前&#xff0c;我们在谈一谈页表&#xff0c;在语言中:char* str”hello world”; *str”H”;运行时会报错&#xff0c;原因在于&#xff1a;字符串在已初始化数据区和代码区之间的&#xff0c;需要写的时候&#xff0c;我们需要对str进行虚拟地址和物理…