版本

webpack :"version": "3.12.0",

webpack配置中的loaders配置是如何传递的

webpack/lib/NormalModuleFactory.js

//从webpack的参数中获取自定义的所有loaders
this.ruleSet = new RuleSet(options.rules || options.loaders);

经过ruleSet.exec处理找到处理当前模块的loader

const result = this.ruleSet.exec({
resource: resourcePath,
resourceQuery,
issuer: contextInfo.issuer,
compiler: contextInfo.compiler
});

到此处,result中的loader字段的值仍为babel-loader:

经过compiler.resolvers.loader处理之后变成了
/Users/cc/killer/webpack-L/wb/node_modules/babel-loader/lib/index.js

处理代码如下:

asyncLib.parallel([
this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPost, this.resolvers.loader),
this.resolveRequestArray.bind(this, contextInfo, this.context, useLoaders, this.resolvers.loader),
this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPre, this.resolvers.loader)
]

....

经过多次回调传递

到达钩子factory 然后创建新的模块:new NormalModule(..,loader,..)

执行一系列回调函数

-->触发before-resolve NormalModuleFactory.js
-->触发factory NormalModuleFactory.js
-->触发resolver NormalModuleFactory.js
-->执行this.buildModule Compilation.js
-->执行module.build NormalModule.js
-->doBuild回调函数 NormalModule.js
到达runLoaders,执行LoaderRunner.js中的runLoaders方法
执行 iteratePitchingLoaders,该方法是个递归函数,先处理pitch阶段,然后再处理normal阶段

先加载loader的代码
加载:
require(loader.path)
定义currentLoaderObject的normal:
loader.normal = typeof module === "function" ? module : module.default; // normal阶段的执行方法
定义currentLoaderObject的pitch:
loader.pitch = module.pitch;
pitch阶段

loader-runner/blob/master/lib/LoaderRunner.js

获取loader提供的pitch方法:
var fn = currentLoaderObject.pitch;
调用pitch:
runSyncOrAsync(fn,loaderContext,[loaderContext.remainingRequest..],callback)
递归调用:
iteratePitchingLoaders
pitch阶段不进行读取资源文件(readResource),而是向loader传递了 remainingRequest,previousRequest等参数。比如在vue-style-loader仅接受了remainingRequest参数。
normal阶段

loader-runner/blob/master/lib/LoaderRunner.js

如果 loaderContext.loaderIndex >= loaderContext.loaders.length,进入normal阶段
根据loaderContext.resourcePath读取资源内容:
options.readResource(resourcePath)
iterateNormalLoaders递归调用

loader.raw = module.raw; //如果raw配置了,根据raw是否转为buffer
runSyncOrAsync方法是真正调用loader的api并完成转换的地方:

function runSyncOrAsync(fn, context, args, callback) {
......
try {
var result = (function LOADER_EXECUTION() {
return fn.apply(context, args);
}());
} catch(e) {......}
}

结束之后通过层层回调,回到normalModule.js的runLloader的回调函数处,紧接着把转译之后内容复制给模块的_source属性,然后调用模块源码的解析,分析资源依赖:

this.parser.parse(this._source.source(), {
current: this,
module: this,
compilation: compilation,
options: options
});

根据资源类型使用对应的loader,直至make结束

webpack源码-loader的原理的更多相关文章

  1. .34-浅析webpack源码之事件流make(3)

    新年好呀~过个年光打游戏,function都写不顺溜了. 上一节的代码到这里了: // NormalModuleFactory的resolver事件流 this.plugin("resolv ...

  2. 从Webpack源码探究打包流程,萌新也能看懂~

    简介 上一篇讲述了如何理解tapable这个钩子机制,因为这个是webpack程序的灵魂.虽然钩子机制很灵活,而然却变成了我们读懂webpack道路上的阻碍.每当webpack运行起来的时候,我的心态 ...

  3. Android 网络框架之Retrofit2使用详解及从源码中解析原理

    就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...

  4. .30-浅析webpack源码之doResolve事件流(1)

    这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...

  5. MyBatis 源码分析 - 缓存原理

    1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...

  6. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  7. .17-浅析webpack源码之compile流程-入口函数run

    本节流程如图: 现在正式进入打包流程,起步方法为run: Compiler.prototype.run = (callback) => { const startTime = Date.now( ...

  8. .30-浅析webpack源码之doResolve事件流(2)

    这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...

  9. .3-浅析webpack源码之预编译总览

    写在前面: 本来一开始想沿用之前vue源码的标题:webpack源码之***,但是这个工具比较巨大,所以为防止有人觉得我装逼跑来喷我(或者随时鸽),加上浅析二字,以示怂. 既然是浅析,那么案例就不必太 ...

随机推荐

  1. vulstack红队评估(四)

    一.环境搭建: ①根据作者公开的靶机信息整理 虚拟机密码: ubuntu: ubuntu:ubuntu   win7: douser:Dotest123   Win2008 DC: administr ...

  2. MyBatis一对多嵌套list返回结果集以及分页查询问题处理

    这两天在整理原有系统接口时,遇到后端的人员-角色-菜单的权限接口没有进行连表的关联查询操作,前端拿数据非常不方便,现在将接口相关sql进行修改并让前端可以一次性拿到想要的数据 原有的单表简单sql: ...

  3. ArrayList类的使用

    ArrayList常用类方法 (1)添加元素 public boolean add(E element) 在集合末端添加一个元素 public void add(int index,E element ...

  4. 入门大数据---Redis集群分布式学习

    Redis是什么? 官方介绍: Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列( ...

  5. P1131 [ZJOI2007]时态同步【树形dp】

    时态同步 从叶子到根节点统计修改次数.树形\(dp\)思想. 题目描述 小\(Q\)在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字\(1,2,3-\). ...

  6. 二.httpRequest-httpResponse-JsonResponse对象

     一.HttpRequest对象 HttpRequest在django.http这个模块中 它是用django创建 文档https://docs.djangoproject.com/en/1.11/r ...

  7. python编码--解码

    在py3中只有两种数据类型:str  bytes str:  存unicode(万国码)编码--全球通用的 bytes:存的是16进制的 1.str s='ehllo 丽庆'  --->它存在内 ...

  8. MysqlException: max pool size was reached.

    2019-09-09 08:22:08.620 +00:00 [ERR] Connection id "0HLPKVK52H2OU", Request id "0HLPK ...

  9. CentOS 关闭暂不需要的系统服务

    需要保留的服务:crond.iptables.irqbalance.microcode_ctl.network.random.sshd.syslog.local 一 .使用命令:ntsysv 打开选项 ...

  10. 第 11 篇:基于 drf-haystack 的文章搜索接口

    作者:HelloGitHub-追梦人物 在 django 博客教程中,我们使用了 django-haystack 和 Elasticsearch 进行文章内容的搜索.django-haystack 默 ...