这是我参与11月更文挑战的第5天
webpack运行过程(1)中讲到 宏任务执行AsyncQueue的_ensureProcessing()方法,该方法内会遍历前面加入到AsyncAueue中的所有entry
遍历AsyncQueue中存储的所有entry,执行_startProcessing(entry)
function _startProcessing(entry){
this.hooks.beforestart.callAsync(entry.item, err => {
if(err) {}
this._processor(entry.item)
})
}
执行AsyncQueue的_processor()方法
_processor方法时前面实例化new AsyncQueue时传入的函数
这个函数是:
this.factorizeQueue = new AsyncQueue({
name: 'factorize',
parent: this.addModuleQueue,
processor: this._factorizeModule.bind(this)
})
function _factorizeModule(){
factory.create()
}
//webpack/lib/NormalModuleFactory.js
function create(data, callback){
const dependencies = data.dependencies
const request = dependencies.request // './src/app.js'
this.hooks.beforeResolved.callAsync(resolveData, (err, result) => {
this.hooks.factorize.callAsync(resolveDate, (err, module) => {
})
})
}
//插件ExternalModuleFactoryPlugin注册了normalModuleFactory.hooks.factorize.tapAsync
normalModuleFactory.hooks.factorize.tapAsync(
"ExternalModuleFactoryPlugin",
(data, callback) => {
handleExternals()
}
)
// NormalModuleFactory自己也注册了 this.hooks.factorize.tapAsync
this.hooks.factorize.tapAsync({
name : 'NormalModuleFactory',
stage: 400
}, (resolveData, callback) => {
// 运行NormalModuleFactory的resolve钩子
this.hooks.resolve.callAsync()
})
this.hooks.resolve.tapAsync({}, ()=>{
defaultResolve(context) // context = 'D:\\code\\web_learn\\webpack\\demo'
})
function defaultResolve(){
this.resolveResource()
}
function resolveResource(){
resolver.resolve()
}
//enhanced-resolve/lib/Resolver.js
function resolve(){
this.doResolve()
}
function doResolve(){
request = {
context: {}
path : 'D:\\code\\web_learn\\webpack\\demo'
request: './src/app.js'
}
hook.callAsync(request)
}
// webpack/li/cache/ResolverCachePlugin.js
// ResolverCachePlugin注册了hook.tapAsync
resolver.hooks.resolve.tapAsync({},()=>{
itemCache.get(processCacheResult)
})
// webpack/lib/CacheFacade.js
get(){
// this._name = 'ResolverCachePlugin|normal|dependencyType=|esm|path=|D:\\code\\web_learn\\webpack\\demo|request=|./src/app.js'
this._cache.get(this._name)
}
// Cache.js
get(identifier){
const gotHandler = []
this.hooks.get.callAsync(identifier, gotHandler, (err, result)=>{
if(gotHandlers.length === 1){
// 先执行回调函数callback
gotHandler[0](result, ()=> callback(null, result))
}
})
}
// 上面的回调函数是processCacheResult
// webpack/li/cache/ResolverCachePlugin.js
function processCacheResult(err, cacheEntry){
if(cacheEntry){
}else{
doRealResolve(itemCache)
}
}
function doRealResolve(){
resolver.doResolve()
}
//enhanced-resolve/lib/Resolver.js
function doResolve(){
}
处理入口文件之前,先下载描述文件package.json
DescriptionFilePlugin插件注册了resolver.getHook(this.source).tapAsync
class DescriptionFilePlugin {
apply(resolver){
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync(
"DescriptionFilePlugin",
(request, resolveContext, callback) => {
//'D:\\code\\web_learn\\webpack\\demo'
const path = request.path;
DescriptionFileUtils.loadDescriptionFile()
}
}
}
loadDescriptionFile(){
(findDescripttionFile(){
forEachBail(filenames, (filename, callback) => {
// directory = 'D:\\code\\web_learn\\webpack\\demo'
// filename = 'package.json'
const descriptionFilePath = resolver.join(directory, filename);
resolver.fileSystem.readJson(descriptionFilePath, (err, context) => {
})
})
})()
}
使用node的fs.readFile(path)读取package.json文件,并将文件内容缓存
_readFileTimestamp(path) //webpack/lib/FileSystemInfo.js
provide(path) //enhanced-resolve/lib/CachedInputFileSystem.js
function provide(path){
// 首先检查缓存中是否有该路径文件
let cacheEntry = this._data.get(path)
let result = this.readFile(path)
this.storeResult(path, result)
// 获取到文件以后再执行回调函数
}
//graceful-fs/graceful-fs.js
function readFile(path){
go$readFile(path)
fs$readFile(path)
fs$readFile = fs.readfile(path)
// 通过node的fs.readFile(path)读取文件
}
//读取文件内容后,缓存起来
function _storeResult(path,result){
if(this._data.has(path)) return;
const level = this._levels[this._currentLevel]
this._data.set(path, {err, result, level})
level.add(path)
}
将读取到的package.json文件内容Buffer转换为utf-8
let cacheEntry = this._data.get(path)
if(!cacheEntry){
fs.readFile(path, (err, result){
this.date.set(path, result)
// buffer转化为utf-8
let data = JSON.parse(result.toString('utf-8'))
})
}
resolveContext.fileDependencies中添加path
//descriptionFilePath = 'D:\\code\\web_learn\\webpack\\demo\\package.json'
resolveContext.fileDependencies.add(descriptionFilePath);
//enhanced-resolve/lib/DescriptionFileUtil.js
function onJson(){
callback()
}
// 执行前面传入的回调函数
// result.directory = 'D:\\code\\web_learn\\webpack\\demo'
// path = 'D:\\code\\web_learn\\webpack\\demo'
const relativePath = "." + path.substr(result.directory.length).replace(/\\/g, "/")
// relativePath = "."
resolver.doResolve()
//enhanced-resolve/lib/Resolver.js
function doResolve(){
const stackEntry = "describedResolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js"
let newStack;
newStack.add(stackEntry)
newStack = {
0 : "resolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
1 : "parseResolve (D:\\code\\web_learn\\webpack\\demo) ./src/app.js",
2 : "describedResolve: (D:\\code\\web_learn\\webpack\\demo) ./src/app.js"
}
}
ConditionalPlugin插件
FileExistsPlugin插件判断文件是否存在
//enhanced-relove/lib/FileExistsPlugin.js
apply(resolver) {
const target = resolver.ensureHook(this.target);
const fs = resolver.fileSystem;
resolver.getHook(this.source).tapAsync("FileExistsPlugin", (request, resolveContext, callback) => {
const file = request.path;
if (!file) return callback();
// 使用node的fs.stat(file)判断文件是否存在
fs.stat(file, (err, stat) => {
if(!stat.isFile()){
}
resolveContext.fileDependencies.add(file);
resolver.doResolve()
}
}
SymlinkPlugin插件
// path = 'D:\\code\\web_learn\\webpack\\demo\\src\\app.js'
fs.readlink(path)