webpack源码-loader的原理
版本
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的原理的更多相关文章
- .34-浅析webpack源码之事件流make(3)
新年好呀~过个年光打游戏,function都写不顺溜了. 上一节的代码到这里了: // NormalModuleFactory的resolver事件流 this.plugin("resolv ...
- 从Webpack源码探究打包流程,萌新也能看懂~
简介 上一篇讲述了如何理解tapable这个钩子机制,因为这个是webpack程序的灵魂.虽然钩子机制很灵活,而然却变成了我们读懂webpack道路上的阻碍.每当webpack运行起来的时候,我的心态 ...
- Android 网络框架之Retrofit2使用详解及从源码中解析原理
就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...
- .30-浅析webpack源码之doResolve事件流(1)
这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- .17-浅析webpack源码之compile流程-入口函数run
本节流程如图: 现在正式进入打包流程,起步方法为run: Compiler.prototype.run = (callback) => { const startTime = Date.now( ...
- .30-浅析webpack源码之doResolve事件流(2)
这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...
- .3-浅析webpack源码之预编译总览
写在前面: 本来一开始想沿用之前vue源码的标题:webpack源码之***,但是这个工具比较巨大,所以为防止有人觉得我装逼跑来喷我(或者随时鸽),加上浅析二字,以示怂. 既然是浅析,那么案例就不必太 ...
随机推荐
- ca69a.cpp_c++_函数匹配(重载确定)
/*ca69a.cpp_c++_函数匹配(重载确定)#重载确定的三个步骤1.候选函数2.选择可行函数3.寻找最佳匹配(如果有的话)#含有多个形参的重载确定 void f1();void f1(int) ...
- C# 泛型的基本知识,以及什么是泛型?
1.1 泛型概述 1.1.1 泛型广泛用于容器(collections) 1.1.2 命名空间System.Collections.Generic 1.2 泛型的优点. 以前类型的泛化(general ...
- GeckoDriver+Selenium+Python的安装和使用
如果没有安装GeckoDriver会提示: selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executab ...
- 利用salt stack pillar安装多组keepalived
利用salt stack pillar安装多组keepalived 环境描述 在生产环境中,需要搭建三套keepalived环境,3个master和3个backup,要安装的软件和配置文件,虽然不是很 ...
- Spring插件安装 - Eclipse 安装 Spring 插件详解(Spring Tool Suite)
安装完成后重启eclipse即可新建spring工程
- 使用Jmeter如何测试下载接口
性能测试过程中,有时候需要对下载类的功能做压测,有些同学没有这方面的测试经验,比较迷茫,本文简单介绍下如何测试下载类的请求1.首先使用fiddler抓包,知道是一个http类型的请求,有一个post请 ...
- SpringMVC 学习笔记(三)数据的校验
34. 尚硅谷_佟刚_SpringMVC_数据绑定流程分析.avi 例如:在jsp中输入一个String字符串类型,需要转换成Date类型的流程如下 convertservice对传入的数据进行转换 ...
- 【故障公告】阿里云 RDS 实例 CPU 100% 故障引发全站无法正常访问
非常抱歉,今天凌晨 3:20~8:30 左右,我们使用的阿里云 RDS 实例 SQL Server 2016 标准版突然出现 CPU 100% 故障,造成全站无法正常访问,由此给您带来巨大的麻烦,请您 ...
- SpringMVC中Map、Model、ModelMap、ModelAndView之间的关系及区别
首先,在了解这三者之前,需要知道一点:SpringMVC在调用方法前会创建一个隐含的数据模型(Model),作为模型数据的存储容器, 成为”隐含模型”. 如果controller方法的参数为Moedl ...
- 【C++和C#的区别杂谈】后自增运算符的结算时机
C++和C#的前自增++n和后自增n++,都是先自增后取值和先取值后自增的含义,但在复杂一点的赋值语句中,我发现细节上有很大的差异. 发现这个问题主要是一个无聊的晚上,我想搞清楚后自增是什么时候结算, ...