清湖网站建设,网站备案简介怎么写,做网站学什么,企业网站必须做可信网站认证使用联邦模块后当前项目就会有两个依赖#xff0c;一个是依赖共享模块#xff0c;一个是依赖远程模块。运行时webpack/runtime/consumes用于解析共享模块#xff0c;运行时webpack/runtime/remotes 用于解析远程模块。这两个模块对应的方法分别是__webpack_require__.f.cons…使用联邦模块后当前项目就会有两个依赖一个是依赖共享模块一个是依赖远程模块。运行时webpack/runtime/consumes用于解析共享模块运行时webpack/runtime/remotes 用于解析远程模块。这两个模块对应的方法分别是__webpack_require__.f.consumes ****和__webpack_require__.f.remotes是的这两个方法都是关在__webpack_require__.f上的和上一篇文章中的__webpack_require__.f.j在一起都是用于加载chunk中的一环。
webpack/runtime/remotes
var chunkMapping {src_bootstrap_js: [webpack/container/remote/app2/App,webpack/container/remote/app2/uitls]
};var idToExternalAndNameMapping {webpack/container/remote/app2/App: [default,./App,webpack/container/reference/app2],webpack/container/remote/app2/uitls: [default,./uitls,webpack/container/reference/app2]
};__webpack_require__.f.remotes (chunkId, promises) {...
}其中数据chunkMapping使用chunkId作为keyvalue是module组成的数组。表示该chunk依赖这些模块。
数据idToExternalAndNameMapping则使用module作为keyvalue是如何加载这个远程模块。
[”default”, “./App”, “webpack/container/reference/app2”] 表示webpack/container/remote/app2/App模块可以从”webpack/container/reference/app2”模块的”./App”获取到并且该远程模块依赖共享作用域”default”。 一般下划线分割的字符串是chunkId斜线分割的是moduleId 在这里__webpack_require__.f.remotes方法做的事情就是当加载chunk src_bootstrap_js时解析该chunk依赖的远程模块webpack/container/remote/app2/App和webpack/container/remote/app2/uitls并进行前置加载。加载完成后将这两个模块安装在当前webpack环境的__webpack_require__.modules上让代码可以通过__webpack_require__(’webpack/container/remote/app2/App’)获取到对应的远程模块导出。
**webpack_require**.f.remotes
__webpack_require__.f.remotes (chunkId, promises) {if(__webpack_require__.o(chunkMapping, chunkId)) {chunkMapping[chunkId].forEach((id) {// getScope是干啥的不知道干啥的是不是防止有多个入口entry因为现在的例子是单入口的// 要把自己也分享出去才能更加复杂var getScope __webpack_require__.R;if(!getScope) getScope [];// data是 idToExternalAndNameMapping 的值var data idToExternalAndNameMapping[id];if(getScope.indexOf(data) 0) return;getScope.push(data);if(data.p) return promises.push(data.p);var onError (error) {...}// 为什么要识别出是firstvar handleFunction (fn, arg1, arg2, d, next, first) {...}var onExternal (external, _, first) {...}var onInitialized (_, external, first) ...var onFactory (factory) {...}handleFunction(__webpack_require__, data[2], 0, 0, onExternal, 1);}}
}就像上面介绍的该方法用于加载入参chunkId依赖的远程模块。其核心方法是handleFunction webpack_require.R的作用是啥拿到是防止同一个执行两边例如index.js中的bootstrap还有别的依赖。这样就会初始化两边了 handleFunction
var handleFunction (fn, arg1, arg2, d, next, first) {try {var promise fn(arg1, arg2);if(promise promise.then) {var p promise.then((result) (next(result, d)), onError);if(first) promises.push(data.p p); else return p;} else {return next(promise, d, first);}} catch(error) {onError(error);}
}代码行数不多想表达的是将arg1和arg2作为入参调用函数fn并将函数的返回值和参数d和first一起作为函数next的入参并且兼容fn返回值为promise和非promise的情况。如果first为true并且其返回值是promise将其push到promises数组中。promises数组表示chunk bootstrap_js的加载完成依赖promises数组全部完成。 为什么只有first才会将promise push到promises中 所以简单来讲handleFunction就是等fn执行完将结果作为next入参继续执行起到了拼接两个函数顺序执行的作用。
handleFunction(__webpack_require__, data[2], 0, 0, onExternal, 1);
__webpack_require__(data[2]) data[2]为webpack/container/reference/app2 执行完成后得到结果作为onExternal的入参执行该方法。
__webpack_modules__ {webpack/container/reference/app2: ((module, __unused_webpack_exports, __webpack_require__) {use strict;
var __webpack_error__ new Error();
module.exports new Promise((resolve, reject) {if(typeof app2 ! undefined) return resolve();__webpack_require__.l(app2Url /remoteEntry.js, (event) {if(typeof app2 ! undefined) return resolve();var errorType event (event.type load ? missing : event.type);var realSrc event event.target event.target.src;__webpack_error__.message Loading script failed.\n( errorType : realSrc );__webpack_error__.name ScriptExternalLoadError;__webpack_error__.type errorType;__webpack_error__.request realSrc;reject(__webpack_error__);}, app2);
}).then(() (app2));}模块webpack/container/reference/app2加载完成后会得到一个对象{get: () get, init: () init} 这个对象就是onExternal方法的第一个入参external。
onExternal
var onExternal (external, _, first) (external ? handleFunction(__webpack_require__.I, data[0], 0, external, onInitialized, first) : onError());一行代码表达的是初始化远程模块依赖的共享作用域之后执行方法onInitialized。
onInitialized
var onInitialized (_, external, first) (handleFunction(external.get, data[1]/* ./App */, getScope, 0, onFactory, first));// external.get 方法也就是三方模块的get方法
var get (module, getScope) {__webpack_require__.R getScope;getScope (__webpack_require__.o(moduleMap, module)? moduleMap[module](): Promise.resolve().then(() {throw new Error(Module module does not exist in container.);}));__webpack_require__.R undefined;return getScope;
};var moduleMap {./App: () {return Promise.all([__webpack_require__.e(webpack_sharing_consume_default_react_react-_5e40),__webpack_require__.e(src_App_js)]).then(() (/* external.get */**() ((__webpack_require__(/*! ./src/App */ ./src/App.js)))**));},}通过三方模块的get方法获取对应模块例如这里的模块 ./App 得到返回值 () ((__webpack_require__(/*! ./src/App */ ./App.js))) 也就是下面的入参factory。
最后执行方法onFactory
var onFactory (factory) {data.p 1;// 这里可以通过id拿到远程库中的模块将id对应的module设置上__webpack_modules__[id] (module) {module.exports factory();}
};到这里__webpack_modules__[’webpack/container/remote/app2/App’] (module) {module.exports factory()} 这样三方模块安装完毕可以保证chunk src_bootstrap_js 依赖的三方模块可以通过__webpack_require__正常获取。
__webpack_require__.I 用于初始化共享作用域当前环境和remote
该方法不仅仅会初始化自身的共享作用域还会初始化当前项目依赖的外部项目的共享作用域
需要注意的是__webpack_require__.I 中初始化外部作用域并不是通过入参来知道要初始化哪些外部作用域而是直接编译到源码中。
initExternal(webpack/container/reference/app2);
// 这样就可以通过id拿到extrnal调用使用__webpack_require__.S调用它的init方法完成其共享作用域的初始化__webpack_require__.S {};
var initPromises {};
var initTokens {};__webpack_require__.I (name, initScope) {if(!initScope) initScope [];var initToken initTokens[name];if(!initToken) initToken initTokens[name] {};if(initScope.indexOf(initToken) 0) return;initScope.push(initToken);// only runs onceif(initPromises[name]) return initPromises[name];// creates a new share scope if neededif(!__webpack_require__.o(__webpack_require__.S, name)) __webpack_require__.S[name] {};// runs all init snippets from all modules reachablevar scope __webpack_require__.S[name];var warn (msg) ...var uniqueName app1;var register (name, version, factory, eager) {...}var initExternal (id) {...}var promises [];switch(name) {case default: {register(react-dom, 17.0.2, () (Promise.all([]).then(() () {} /* factory */))));register(react, 17.0.2, () (Promise.all([]).then(() () /* factory */)));initExternal(webpack/container/reference/app2);}break;}
if(!promises.length) return initPromises[name] 1;
return initPromises[name] Promise.all(promises).then(() (initPromises[name] 1));这个方法用于初始化共享作用域。在初始化当前环境共享作用域后使用方法initExternal(webpack/container/reference/app2);初始化远程模块的共享作用域。
var initPromises {};
var initTokens {};__webpack_require__.I (name, initScope) {if(!initScope) initScope [];var initToken initTokens[name];if(!initToken) initToken initTokens[name] {};if(initScope.indexOf(initToken) 0) return;initScope.push(initToken);...
}var initExternal (id) {...module.init(__webpack_require__.S[name], initScope)...
}这几行代码不太好理解。
首先每个作用域都有一个唯一的token与之对应在这里表现为对象。
正在初始化的作用域列表存在initScope中如果initScope中存在这个token直接退出表示正在初始化。这种情况会出现在相互依赖的情况下a 依赖 b 初始化b的共享作用域这时候b也依赖ab也会初始化a的作用域这时候传入的initScope就有代表a作用域的token否则会一直初始化下去。
initExternal(webpack/container/reference/app2);
var initExternal (id) {var handleError (err) (warn(Initialization of sharing external failed: err));try {var module __webpack_require__(id);if(!module) return;var initFn (module) (module module.init module.init(__webpack_require__.S[name], initScope))if(module.then) return promises.push(module.then(initFn, handleError));var initResult initFn(module);if(initResult initResult.then) return promises.push(initResult[catch](handleError));} catch(err) { handleError(err); }
}这段代码表达的是等待远程模块加载完成拿到其init方法使用当前环境的共享作用域__webpack_require__.S的某个这里是default来初始化远程环境共享作用域。
register(react, 17.0.2, () (Promise...
var register (name, version, factory, eager) {var versions scope[name] scope[name] || {};var activeVersion versions[version];if(!activeVersion || (!activeVersion.loaded (!eager ! !activeVersion.eager ? eager : uniqueName activeVersion.from))) versions[version] { get: factory, from: uniqueName, eager: !!eager };
};向指定的共享作用域上设置包。
共享作用域初始化完成后当前环境的共享作用域形状如下
__webpack_require__.S.default {react: {17.0.2: {get: () ..., from: uniqueName, eager: boolean}},...
}到这里加载chunk src_bootstrap_js 依赖的远程模块准备完毕并且远程模块依赖的共享作用域同样初始化完毕。但是src_bootstrap_js还没有加载完毕因为虽然远程模块可以通过__webpack_require__方法直接获取到但是共享模块还无法通过该方法直接获取因为到目前为止共享模块只存在于__webpack_require__.S.default 上而不存在于__webpack_modules__上。要将__webpack_require__.S.default上的共享模块在__webpack_modules__上获取还要借助接下来的方法__webpack_require__.f.consumes (chunkId, promises) {...}的帮助。
总结
webpack_require.f.remotes使用chunkId和promises作为入参解析chunkId依赖的远程模块并加载和安装让被依赖的远程模块可以通过__webpack_require__方法直接获取。
安装远程依赖的过程包括下载远程依赖和初始化远程依赖依赖的共享作用域完善远程依赖的执行环境。