【手机病毒链接源码】【okio 1.13.0 源码】【mybatis源码流程】loader源码分析

来源:ckeditor 源码

1.webpack5loader和plugin原理解析
2.vue3源码学习--编译阶段汇总
3.Webpack进阶less-loader、源码css-loader、分析style-loader源码解析
4.Loader学习,源码简析babel-loader
5.vue-loader源码分析学习

loader源码分析

webpack5loader和plugin原理解析

       大家好,分析今天为大家解析下loader和plugin

一、源码区别

       loader是分析手机病毒链接源码文件加载器,能够加载资源文件,源码并对这些文件进行一些处理,分析诸如编译、源码压缩等,分析最终一起打包到指定的源码文件中

       plugin赋予了Webpack各种灵活的功能,例如打包优化、分析资源管理、源码环境变量注入等,分析目的源码是解决loader无法实现的其他事从整个运行时机上来看,如下图所示:

       可以看到,两者在运行时机上的区别:

       loader运行在打包文件之前plugins在整个编译周期都起作用在Webpack运行的生命周期中会广播出许多事件,Plugin可以监听这些事件,在合适的时机通过Webpack提供的API改变输出结果

       对于loader,实质是一个转换器,将A文件进行编译形成B文件,操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程

       下面我们来看看loader和plugin实现的原理

Loader原理loader概念

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

loader执行顺序

       分类

       pre:前置loader

       normal:普通loader

       inline:内联loader

       post:后置loader

       执行顺序

       4类loader的执行优级为:pre>normal>inline>post。

       相同优先级的loader执行顺序为:从右到左,从下到上。

       例如:

//此时loader执行顺序:loader3-loader2-loader1module:{ rules:[{ test:/\.js$/,loader:"loader1",},{ test:/\.js$/,loader:"loader2",},{ test:/\.js$/,loader:"loader3",},],},//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},

       使用loader的方式

       配置方式:在webpack.config.js文件中指定loader。(pre、normal、okio 1.13.0 源码postloader)

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

开发一个loader1.最简单的loader//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};

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

2.loader接受的参数

       content源文件的内容

       mapSourceMap数据

       meta数据,可以是任何内容

loader分类1.同步loadermodule.exports=function(content,map,meta){ returncontent;};

       this.callback方法则更灵活,因为它允许传递多个参数,而不仅仅是content。

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

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

3.RawLoader

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

module.exports=function(content){ //content是一个Buffer数据returncontent;};module.exports.raw=true;//开启RawLoader4.PitchingLoadermodule.exports=function(content){ returncontent;};module.exports.pitch=function(remainingRequest,precedingRequest,data){ console.log("dosomethings");};

       webpack会先从左到右执行loader链中的每个loader上的pitch方法(如果有),然后再从右到左执行loader链中的每个loader上的普通loader方法。

       在这个过程中如果任何pitch有返回值,则loader链被阻断。webpack会跳过后面所有的的pitch和loader,直接进入上一个loader。

loaderAPI方法名含义用法this.async异步回调loader。返回this.callbackconstcallback=this.async()this.callback可以同步或者异步调用的并返回多个结果的函数this.callback(err,content,sourceMap?,meta?)this.getOptions(schema)获取loader的optionsthis.getOptions(schema)this.emitFile产生一个文件this.emitFile(name,content,sourceMap)this.utils.contextify返回一个相对路径this.utils.contextify(context,request)this.utils.absolutify返回一个绝对路径this.utils.absolutify(context,request)

       更多文档,请查阅webpack官方loaderapi文档

手写clean-log-loader

       作用:用来清理js代码中的mybatis源码流程console.log

//loaders/clean-log-loader.jsmodule.exports=functioncleanLogLoader(content){ //将console.log替换为空returncontent.replace(/console\.log\(.*\);?/g,"");};手写banner-loader

       作用:给js代码添加文本注释

       loaders/banner-loader/index.js

constschema=require("./schema.json");module.exports=function(content){ //获取loader的options,同时对options内容进行校验//schema是options的校验规则(符合JSONschema规则)constoptions=this.getOptions(schema);constprefix=`/**Author:${ options.author}*/`;return`${ prefix}\n${ content}`;};

       loaders/banner-loader/schema.json

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},0手写babel-loader

       作用:编译js代码,将ES6+语法编译成ES5-语法。

       下载依赖

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},1

       loaders/babel-loader/index.js

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},2

       loaders/banner-loader/schema.json

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},3手写file-loader

       作用:将文件原封不动输出出去

       下载包

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},4

       loaders/file-loader.js

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},5

       loader配置

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},6手写style-loader

       作用:动态创建style标签,插入js中的样式代码,使样式生效。

       loaders/style-loader.js

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},7Plugin原理Plugin的作用

       通过插件我们可以扩展webpack,加入自定义的构建行为,使webpack可以执行更广泛的任务,拥有更强的构建能力。

Plugin工作原理

       webpack就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。webpack通过Tapable来组织这条复杂的生产线。webpack在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。webpack的事件流机制保证了插件的有序性,使得整个系统扩展性很好。——「深入浅出Webpack」

       站在代码逻辑的角度就是:webpack在编译代码过程中,会触发一系列Tapable钩子事件,插件所做的,就是找到相应的钩子,往上面挂上自己的任务,也就是微红包源码注册事件,这样,当webpack构建的时候,插件注册的事件就会随着钩子的触发而执行了。

Webpack内部的钩子什么是钩子

       钩子的本质就是:事件。为了方便我们直接介入和控制编译过程,webpack把编译过程中触发的各类关键事件封装成事件接口暴露了出来。这些接口被很形象地称做:hooks(钩子)。开发插件,离不开这些钩子。

Tapable

       Tapable为webpack提供了统一的插件接口(钩子)类型定义,它是webpack的核心功能库。webpack中目前有十种hooks,在Tapable源码中可以看到,他们是:

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},8

       Tapable还统一暴露了三个方法给插件,用于注入不同类型的自定义构建行为:

       tap:可以注册同步钩子和异步钩子。

       tapAsync:回调方式注册异步钩子。

       tapPromise:Promise方式注册异步钩子。

Plugin构建对象Compiler

       compiler对象中保存着完整的Webpack环境配置,每次启动webpack构建时它都是一个独一无二,仅仅会创建一次的对象。

       这个对象会在首次启动Webpack时创建,我们可以通过compiler对象上访问到Webapck的主环境配置,比如loader、plugin等等配置信息。

       它有以下主要属性:

       compiler.options可以访问本次启动webpack时候所有的配置文件,包括但不限于loaders、entry、output、plugin等等完整配置信息。蓝牙bleapp源码

       compiler.inputFileSystem和compiler.outputFileSystem可以进行文件操作,相当于Nodejs中fs。

       compiler.hooks可以注册tapable的不同种类Hook,从而可以在compiler生命周期中植入不同的逻辑。

       compilerhooks文档

Compilation

       compilation对象代表一次资源的构建,compilation实例能够访问所有的模块和它们的依赖。

       一个compilation对象会对构建依赖图中所有模块,进行编译。在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、分块(chunk)、哈希(hash)和重新创建(restore)。

       它有以下主要属性:

       compilation.modules可以访问所有模块,打包的每一个文件都是一个模块。

       compilation.chunkschunk即是多个modules组成而来的一个代码块。入口文件引入的资源组成一个chunk,通过代码分割的模块又是另外的chunk。

       compilation.assets可以访问本次打包生成所有文件的结果。

       compilation.hooks可以注册tapable的不同种类Hook,用于在compilation编译模块阶段进行逻辑添加以及修改。

       compilationhooks文档

生命周期简图开发一个插件最简单的插件

       plugins/test-plugin.js

//此时loader执行顺序:loader1-loader2-loader3module:{ rules:[{ enforce:"pre",test:/\.js$/,loader:"loader1",},{ //没有enforce就是normaltest:/\.js$/,loader:"loader2",},{ enforce:"post",test:/\.js$/,loader:"loader3",},],},9注册hook//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};0启动调试

       通过调试查看compiler和compilation对象数据情况。

       package.json配置指令

//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};1

       运行指令

//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};2

       此时控制台输出以下内容:

PSC:\Users\\Desktop\source>//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};2>source@1.0.0debug>node--inspect-brk./node_modules/webpack-cli/bin/cli.jsDebuggerlisteningonws://.0.0.1:/ea-7b--a7-fccForhelp,see:/post/

       开发思路:

       我们需要借助html-webpack-plugin来实现

       在html-webpack-plugin输出index.html前将内联runtime注入进去

       删除多余的runtime文件

       如何操作html-webpack-plugin?官方文档

       实现:

//loaders/loader1.jsmodule.exports=functionloader1(content){ console.log("hellofirstloader");returncontent;};7

vue3源码学习--编译阶段汇总

       从vue-loader开始,我们逐步探索vue/compiler-core包的源码,完成了编译阶段的解析(忽略了compiler-ssr部分)。

       涉及的包包括:

       vue-loader:基于webpack的入口

       vueLoaderPlugin:处理核心操作

       @vue/compiler-sfc:处理script、template和style

       compiler-dom:处理template,与compiler-core协同工作

       compiler-core:处理template的核心部分

       vue-loader首先安装vueLoaderPlugin,主要负责匹配资源并调用相应方法。script部分通过@vue/compiler-sfc的compileScript处理,其他如template和style则根据其类型调用相应处理函数。

       编译流程中,script通过babel将JavaScript转换为AST节点,然后进行处理。template则通过compiler-dom和compiler-core转换为浏览器可识别的JavaScript代码。CSS变量和scopeId也是在这个阶段进行处理的。

       在dev模式下,render function会被分离出来以支持热模块替换(HMR),而prod模式下,这些代码会被整合到setup函数中,以提高代码效率。

       最后,总结整个编译阶段,对Vue源码有了深入理解,不再是神秘的魔法,而是清晰的流程。希望这些内容对您有所帮助,祝大家新春快乐!

Webpack进阶less-loader、css-loader、style-loader源码解析

       深入解析 Webpack 样式 loader

       本文将通过探讨 less-loader、css-loader、style-loader 的作用和实现方式,加深对 loader 的理解。

       对于一个样式文件(如 less 文件),最常用的 loader 配置为将 less 代码转译为浏览器可识别的 CSS 代码。

       less-loader 的主要功能是利用 less 库将 less 语法转译为 CSS 语法,其原理在于调用 less 库提供的方法,完成转译后输出 CSS 代码。

       接下来,css-loader 的作用是解析 CSS 文件中的 @import 和 url 语句,并处理 CSS-modules,最终以 js 模块形式输出结果。

       css-loader 会将多个 CSS 文件的样式内容以字符串形式拼接,形成 js 模块,供其他 loader 使用。

       而 style-loader 的任务是将 css-loader 处理后的结果以 style 标签的形式插入 DOM 树中。

       理解 style-loader 的实现逻辑,可以深化对 loader 调用链、执行顺序和模块化输出的掌握。

       总的来说,less-loader、css-loader、style-loader 的结合使用,构成了 Webpack 处理样式文件的关键步骤,对于理解 Webpack 的整体工作流程至关重要。

Loader学习,简析babel-loader

       Loader学习:深入解析babel-loader的功能与实现

       Webpack中的Loader作为模块转换器,其核心职责是将源文件内容转换为所需格式。通常,Loader通过链式处理,以单一功能的形式依次作用于源文件,确保输出符合预期。Loader作为Node.js模块,其核心是导出一个函数,利用webpack提供的API进行操作,如处理返回内容、sourceMap、AST等。

       除了基本的代码转换,Loader还可以返回额外信息。通过webpack的callback API,开发者可以控制返回结果的处理方式。Loader的同步与异步特性,异步Loader如file-loader,需要明确告诉webpack处理的是二进制数据。此外,为了优化性能,Loader可以利用cacheable API缓存转换结果,当依赖不变时,可以显著提升加载速度。

       学习Loader的深入理解,需要掌握各种API,如获取options、处理二进制数据、缓存策略等。以babel-loader为例,其源码中体现了这些概念。首先,它依赖@babel/core,并根据用户配置进行定制化处理。loader函数的核心部分,涉及options解析、配置加载、source处理、缓存判断以及元数据订阅等步骤,最后返回转换后的结果。

       总结来说,Loader的核心是处理输入和输出,通过调用webpack提供的API实现各种功能。了解并掌握这些API,我们就可以开始编写自己的定制Loader,如babel-loader那样,为项目提供强大的代码转换能力。现在,对Loader有了更直观的认识,对编写Loader的步骤和技巧也更加清晰了。

vue-loader源码分析学习

       Vue-loader源码深入解析

       Webpack配置中的loader调用和执行位置是在NormalModule的_doBuild方法中,当module需要转换为source时,会用到loader-runner包。本文将逐步分析loader的核心代码。

       首先,loader的入口点涉及到source的处理,它包含了整个.vue文件的代码。VueLoaderPlugin的作用在于检查版本差异并加载相应的文件,以适应Webpack 5的更新。

       接着,代码中的一大块内容是关于module.rules的处理,这些规则与配置文件中定义的类似,如test、include、exclude和resolve。RuleSetCompiler是一个处理rule集合的处理器,它负责收集和转换规则字段,生成带有condition和effects的集合。

       loader会监听compiler的compilation和loader hooks,确保插件在vue-loader之前执行。之后,会遍历配置的规则,对不符合特定条件的规则进行报错处理,并处理vue-loader相关的规则,添加自定义字段。

       在cloneRule方法中,关键步骤是调用ruleSetCompiler.compileRule,这个方法会执行hook并处理每个rule,将规则的特定字段转换成最终的条件和效果。整个过程确保了规则的正确匹配和处理。

       总结来说,rulePlugin扩展配置文件中的rule,而ruleSetCompiler负责管理和执行这些规则,生成最终的处理逻辑。在处理过程中,巧妙地利用闭包缓存和query判断,确保了对vue资源的精确匹配和处理。

       最后,VueLoaderPlugin还针对template、js和ts文件的处理进行了特殊规则设置,确保render function与其他用户代码得到相同的处理,同时通过pitcher处理vue块请求和资源顺序调整。

文章所属分类:时尚频道,点击进入>>