webpack loader原理以及自定义loader

news/2024/11/17 14:48:13/

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= styledocument.head.appendChild(styleEl)`// 终止后面的loader执行return script
}
{test:/\.css$/,use:["./loaders/style-loader.js","css-loader"]},


http://www.ppmy.cn/news/60015.html

相关文章

pytorch——损失函数之nn.L1Loss()和nn.SmoothL1Loss()

文章目录 【回归损失函数】L1&#xff08;MAE&#xff09;、L2&#xff08;MSE&#xff09;、Smooth L1 Loss详解1. L1 Loss&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;1.1 数学定义1.2 、使用场景与问题1.3 、如何使用 2. L2 Loss&#xff08;Mean Squared E…

SPSS如何制作基本统计分析报表之案例实训?

文章目录 0.引言1.制作在线分析处理报告2.制作个案摘要报告3.制作行形式摘要报告4.制作列形式摘要报告 0.引言 因科研等多场景需要进行数据统计分析&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记…

GO实现RSA 、AES加解密

GO实现RSA 、AES加解密 实现思路RSAAES测试用例 实现思路 只有加解密两个函数&#xff0c;抽象出一个接口&#xff0c;使用门面和策略模式&#xff0c;对外开放加解密接口&#xff0c;由于密码比较场景使用率较高&#xff0c;再对外开放一个比较的接口&#xff0c;接口最少有两…

Python并发编程之进程操作

前言 本文介绍一下如何在python中开启进程。 查看进程 一台计算机上面运行着很多进程&#xff0c;计算是如何区分并管理这些进程服务端的呢&#xff1a;计算机会给每一个运行的程序即进程分配一个PID号。 windows系统电脑进入cmd后输入tasklist即可查看所有进程的进程号&am…

上班摸鱼在群里吹牛B,逮到一个阿里10年老测试开发,聊过之后收益良多...

老话说的好&#xff0c;这人呐&#xff0c;一单在某个领域鲜有敌手了&#xff0c;就会闲得蛋疼。前几天我在上班摸鱼刷群的时候认识了一位阿里测试开发大佬&#xff0c;在华为工作了10年&#xff0c;因为本人天赋比较高&#xff0c;平时工作也兢兢业业&#xff0c;现在企业内有…

Golang 包使用注意事项

1&#xff09;在给一个文件打包时&#xff0c;该包对应一个文件夹&#xff0c;比如这里的utils文件夹对应的包名就是utils&#xff0c;文件的包名通常和文件所在的文件夹名一致&#xff0c;一般为小写字母。 2&#xff09;当一个文件要使用其它包函数或变量时&#xff0c;需要…

分享kubernetes部署:cachecloud部署说明

cachecloud部署 cachecloud是搜狐视频(sohutv)Redis私有云平台 已省略~ 挑选一台服务器部署cachecloud-web 将cachecloud-web打成war包&#xff0c;可以在服务器上打包&#xff0c;也可以在本地打包&#xff0c;这里举一个在服务器上打包的例子。 将源代码下载到/opt下 已省略~…

十一、MyBatis的逆向工程

文章目录 十一、MyBatis的逆向工程11.1 (清新简洁版)创建逆向工程的步骤11.2 (奢华尊享版)创建逆向工程的步骤11.3 说明尊享版和简洁版的区别 本人其他相关文章链接 十一、MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库…