const webpack = (options, callback) => { //... if (callback) { if (typeof callback !== "function") { throw new Error("Invalid argument: callback"); } if ( options.watch === true || (Array.isArray(options) && options.some(o => o.watch)) ) { const watchOptions = Array.isArray(options) ? options.map(o => o.watchOptions || {}) : options.watchOptions || {}; return compiler.watch(watchOptions, callback); } compiler.run(callback); } return compiler; }
最终返回了compilerreact
exports.version = version; // ...属性挂载,把引入的函数模块所有暴露出来 webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; webpack.WebpackOptionsApply = WebpackOptionsApply; webpack.Compiler = Compiler; webpack.MultiCompiler = MultiCompiler; webpack.NodeEnvironmentPlugin = NodeEnvironmentPlugin; // @ts-ignore Global @this directive is not supported webpack.validate = validateSchema.bind(this, webpackOptionsSchema); webpack.validateSchema = validateSchema; webpack.WebpackOptionsValidationError = WebpackOptionsValidationError;
下面暴露了一些插件webpack
const exportPlugins = (obj, mappings) => { for (const name of Object.keys(mappings)) { Object.defineProperty(obj, name, { configurable: false, enumerable: true, get: mappings[name] }); } }; exportPlugins(exports, { AutomaticPrefetchPlugin: () => require("./AutomaticPrefetchPlugin"), BannerPlugin: () => require("./BannerPlugin"), CachePlugin: () => require("./CachePlugin")} )
再通俗一点的解释:
好比当你api.AutomaticPrefetchPlugin你能
调用AutomaticPrefetchPlugin文件下的方法
这个和上面的不一样在于上面的是挂在webpack函数对象上的git
要想理解Compiler.js
必需要理解tapable
再写一遍 git地址 github
咱们先简单的理解它为一个经过tap 注册插件
call是run插件的事件流,里面还有一些异步的操做web
Compiler整理以下api
class Compiler extends Tapable { constructor(context) { super(); this.hooks = { //罗列一些出现频率比较高的 shouldEmit: new SyncBailHook(["compilation"]), done: new AsyncSeriesHook(["stats"]), beforeRun: new AsyncSeriesHook(["compiler"]), run: new AsyncSeriesHook(["compiler"]), emit: new AsyncSeriesHook(["compilation"]), afterEmit: new AsyncSeriesHook(["compilation"]), thisCompilation: new SyncHook(["compilation", "params"]), compilation: new SyncHook(["compilation", "params"]), beforeCompile: new AsyncSeriesHook(["params"]), compile: new SyncHook(["params"]), make: new AsyncParallelHook(["compilation"]), afterCompile: new AsyncSeriesHook(["compilation"]), watchRun: new AsyncSeriesHook(["compiler"]), //... } // 添加事件流 this._pluginCompat.tap("Compiler", options => { switch (options.name) { case "additional-pass": case "before-run": case "run": case "emit": case "after-emit": case "before-compile": case "make": case "after-compile": case "watch-run": options.async = true; break; } }); } watch(){ //... } run(callback) { //... } // 清除输入文件系统 purgeInputFileSystem() { if (this.inputFileSystem && this.inputFileSystem.purge) { this.inputFileSystem.purge(); } } emitAssets(compilation, callback) { //... } createChildCompiler( compilation, compilerName, compilerIndex, outputOptions, plugins ) { //... } //... compile(callback){ //... } }
和tapable用法一个模子里刻出来的,咱们仔细的研究run函数promise
compiler.js是webpack 的核心app
run(callback) { //若是正在running,返回报错处理 if (this.running) return callback(new ConcurrentCompilationError()); //running调用finalCallback const finalCallback = (err, stats) => { this.running = false; if (callback !== undefined) return callback(err, stats); }; //记录初始化running时间 const startTime = Date.now(); //设置running标志,防止屡次running this.running = true; //正在编译 const onCompiled = (err, compilation) => { //若是报错,编译结束 if (err) return finalCallback(err); //若是没有编译完成 if (this.hooks.shouldEmit.call(compilation) === false) { // Stats模块有1400行, // compiler.js是webpack 的核心,new Stats(compilation)是compiler.js的核心 const stats = new Stats(compilation); // stats对象挂载startTime,endTime stats.startTime = startTime; stats.endTime = Date.now(); // 异步调用完成事件流,running结束 this.hooks.done.callAsync(stats, err => { if (err) return finalCallback(err); return finalCallback(null, stats); }); return; } // 调用emitAsset方法,emitAsset主要负责写入文件输出文件,不影响咱们先看编译 this.emitAssets(compilation, err => { // 相似同上, 若是报错,编译结束 if (err) return finalCallback(err); // 若是须要额外的编译,上次的没编译完成吗😰 if (compilation.hooks.needAdditionalPass.call()) { compilation.needAdditionalPass = true; //再来一遍new Stats const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); //继续异步调用时间流 this.hooks.done.callAsync(stats, err => { if (err) return finalCallback(err); // 此次多了一个时间流,调用额外编译,告知编译终于编完了 this.hooks.additionalPass.callAsync(err => { if (err) return finalCallback(err); //调用compile,把onCompiled的返回值传入compile函数,onCompiled的返回值也就是new Stats的对象 this.compile(onCompiled); }); }); return; } // 若是都不走上面的分支,即编译完成,不须要额外的编译 // 调用emitRecords方法,主要用来记录输出的 this.emitRecords(err => { if (err) return finalCallback(err); // 一样new Stats const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); // 异步调用完成事件 this.hooks.done.callAsync(stats, err => { if (err) return finalCallback(err); return finalCallback(null, stats); }); }); //最终总结,不管走那个分支都是 new Stats(compilation) 返回stats的回调函数,按照目前的流程走的是最后一个分支,调用 this.emitRecords }); }; // 调用beforeRun钩子 this.hooks.beforeRun.callAsync(this, err => { if (err) return finalCallback(err); // 调用run钩子 this.hooks.run.callAsync(this, err => { if (err) return finalCallback(err); //读文件记录 this.readRecords(err => { if (err) return finalCallback(err); //把onCompiled函数传入,调用compile this.compile(onCompiled); }); }); }); }
compilation和Stats分别对应两个模块
compilation.js 2500行,Stats.js 1400行异步
接下来咱们看一下compile函数async
newCompilationParams() { const params = { // 普通模块工厂 normalModuleFactory: this.createNormalModuleFactory(), // 上下文模块工厂 contextModuleFactory: this.createContextModuleFactory(), // 编译依赖 compilationDependencies: new Set() }; return params; } compile(callback) { // params值以下 const params = this.newCompilationParams(); // 异步调用beforeCompile钩子 this.hooks.beforeCompile.callAsync(params, err => { if (err) return callback(err); // 调用compile钩子 this.hooks.compile.call(params); // 终于出现了compilation,以前一直没有讲了compilation是什么,newCompilation咱们看以下函数 const compilation = this.newCompilation(params); this.hooks.make.callAsync(compilation, err => { if (err) return callback(err); compilation.finish(); compilation.seal(err => { if (err) return callback(err); // 异步调用afterCompile,返回回调函数 this.hooks.afterCompile.callAsync(compilation, err => { if (err) return callback(err); return callback(null, compilation); }); }); }); }); } newCompilation(params) { // compilation 是 this.createCompilation(),继续往下 const compilation = this.createCompilation(); //给compilation对象挂载属性 compilation.fileTimestamps = this.fileTimestamps; compilation.contextTimestamps = this.contextTimestamps; compilation.name = this.name; compilation.records = this.records; compilation.compilationDependencies = params.compilationDependencies; //告知钩子调用完毕 this.hooks.thisCompilation.call(compilation, params); this.hooks.compilation.call(compilation, params); return compilation; } createCompilation() { // 原来compilation 是 newCompilation而来,Compilation一共2500行,堪称整个compiler.js的核心 return new Compilation(this); }
params以下
{ normalModuleFactory: NormalModuleFactory { _pluginCompat: SyncBailHook { // key是tapable 方法名 _args: [Array], taps: [Array], interceptors: [], call: [Function: lazyCompileHook], promise: [Function: lazyCompileHook], callAsync: [Function: lazyCompileHook], _x: undefined }, hooks: { resolver: [SyncWaterfallHook], factory: [SyncWaterfallHook], beforeResolve: [AsyncSeriesWaterfallHook], afterResolve: [AsyncSeriesWaterfallHook], createModule: [SyncBailHook], module: [SyncWaterfallHook], createParser: [HookMap], parser: [HookMap], createGenerator: [HookMap], generator: [HookMap] }, resolverFactory: ResolverFactory { _pluginCompat: [SyncBailHook], hooks: [Object], cache1: [WeakMap], cache2: Map {} }, ruleSet: RuleSet { references: {}, rules: [Array] }, cachePredicate: [Function: bound Boolean], //文件路径 context: '/Users/orion/Desktop/react-beauty-highcharts', parserCache: {}, generatorCache: {} }, contextModuleFactory: ContextModuleFactory { _pluginCompat: SyncBailHook { _args: [Array], taps: [Array], interceptors: [], call: [Function: lazyCompileHook], promise: [Function: lazyCompileHook], callAsync: [Function: lazyCompileHook], _x: undefined }, hooks: { beforeResolve: [AsyncSeriesWaterfallHook], afterResolve: [AsyncSeriesWaterfallHook], contextModuleFiles: [SyncWaterfallHook], alternatives: [AsyncSeriesWaterfallHook] }, resolverFactory: ResolverFactory { _pluginCompat: [SyncBailHook], hooks: [Object], cache1: [WeakMap], cache2: Map {} } }, compilationDependencies: Set {} }
this.compile(onCompiled) 是个高阶函数,能够简单的理解为参数是函数,而且返回一个函数
撒花🌹 🎉🍀我要买瓶skii犒赏本身