webpack
来说每个文件都是一个module
entry
定义开始,找到全部的文件,并转化为 module
entry: './index.js',
entry: ['./index1.js', './index2.js']
entry: {
main: './main.js'
}
entry: () => './index.js'
entry: () => new Promise((resolve) => resolve('./index.js'))
compiler.hooks.compilation.tap("SingleEntryPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(SingleEntryDependency,normalModuleFactory);
}
);
make
事件回调,在make
阶段的时候调用addEntry
方法,然后进入_addModuleChain
进入正式的编译阶段chunk
时会依靠dependency
来得到依赖关系图dependency
中方法和保存的信息将源文件中的import
等语句替换成最终输出的可执行的JS语句module: {
dependencies: [
dependency: {
module
}
]
}
add 阶段是将 module 的所有信息保存到 Compilation 中,以便于在最后打包成 chunk 的时候使用
Compilation.modules
数组中Compilation._modules
对象reason
Compilation.entries
addModule(module) {
const identifier = module.identifier();
this._modules.set(identifier, module);
this.modules.push(module);
this.entries.push(module);
module.reasons.push(new ModuleReason(module, dependency, explanation));
}
build(options, compilation, resolver, fs, callback) {
return this.doBuild(options, compilation, resolver, fs, err => {
// 处理 source 这里会将 source 转为 AST,分析出所有的依赖
const result = this.parser.parse(this._ast || this._source.source());
handleParseResult(result);
})
}
//获取 source
doBuild(options, compilation, resolver, fs, callback) {
runLoaders(
{
resource: this.resource,
loaders: this.loaders,
context: loaderContext,
readResource: fs.readFile.bind(fs)
},
(err, result) => {
// createSource 会将 runLoader 得到的结果转为字符串以便后续处理
this._source = this.createSource(
this.binary ? asBuffer(source) : asString(source),
resourceBuffer,
sourceMap
);
return callback();
}
);
}
遍历 AST,遇到 import 语句就增加相关依赖
module
增加dependency
实例,每个 dependency
类都会有一个 template
方法,并且保存了原来代码中的字符位置 range
,在最后生成打包后的文件时,会用 template
的结果替换 range
部分的内容dependency
不仅包含了文件中所有的依赖信息,还被用于最终生成打包代码时对原始内容的修改和替换得到的依赖
__webpack_require__.r(__webpack_exports__)
RuntimeTemplatevar _title_js__WEBPACK_IMPORTED_MODULE_0__
use strict
var _title_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./title.js */ "./src/title.js");
console.log(_title_js__WEBPACK_IMPORTED_MODULE_0__["message"]);
title.js
export const message = 'zhufeng';
lazy.js
export const message = 'zhufeng';
index.js
import { message } from './title.js';
console.log(message);
import('./lazy.js').then(result => {
console.log(result);
})
console.log(__resourceQuery);
prewalkStatements(statements) {
for (let index = 0, len = statements.length; index < len; index++) {
const statement = statements[index];
this.prewalkStatement(statement);
}
}
prewalkImportDeclaration(statement) {
const source = statement.source.value;//./title.js
this.hooks.import.call(statement, source);
for (const specifier of statement.specifiers) {
const name = specifier.local.name;//name
this.scope.renames.set(name, null);
this.scope.definitions.add(name);
switch (specifier.type) {
case "ImportDefaultSpecifier":
this.hooks.importSpecifier.call(statement, source, "default", name);
break;
case "ImportSpecifier":
this.hooks.importSpecifier.call(
statement,
source,
specifier.imported.name,
name
);
break;
}
}
}
HarmonyImportDependencyParserPlugin
const sideEffectDep = new HarmonyImportSideEffectDependency(
source,
parser.state.module,
parser.state.lastHarmonyImportOrder,
parser.state.harmonyParserScope
);
sideEffectDep.loc = statement.loc;
parser.state.module.addDependency(sideEffectDep);
dependencies
按照代码在文件中出现的先后顺序排序const afterBuild = () => {
if (addModuleResult.dependencies) {
this.processModuleDependencies(module, err => {
if (err) return callback(err);
callback(null, module);
});
} else {
return callback(null, module);
}
};
dependencies={
NormalModuleFactory: {
"module./title.js": [
HarmonyImportSideEffectDependency,
HarmonyImportSpecifierDependency
],
"module./lazy.js": [
HarmonyImportSideEffectDependency,
HarmonyImportSpecifierDependency
]
}
}
sortedDependencies = [
{
factory: NormalModuleFactory,
dependencies: [
HarmonyImportSideEffectDependency,
HarmonyImportSpecifierDependency
]
},
{
factory: NormalModuleFactory,
dependencies: [
HarmonyImportSideEffectDependency,
HarmonyImportSpecifierDependency
]
}
]
addModuleDependencies(
module,
dependencies,
bail,
cacheGroup,
recursive,
callback
) {
asyncLib.forEach(
dependencies,
(item, callback) => {
//获取依赖
const dependencies = item.dependencies;
//获取工厂
const factory = item.factory;
//创建模块
factory.create(
(err, dependentModule) => {
const addModuleResult = this.addModule(dependentModule);
dependentModule = addModuleResult.module;
// 将 module 信息写入依赖中
iterationDependencies(dependencies);
// build 阶段
const afterBuild = () => {
// build 阶段结束后有依赖的话继续处理依赖
this.processModuleDependencies(dependentModule, callback);
};
this.buildModule(afterBuild);
}
);
}
);
}
dependencies{
HarmonyImportSideEffectDependency(request:"./title.js")
}
blocks{
ImportDependenciesBlock(request:"./lazy.js")
}