You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
asyncfunctionbuildEverything(){if(!argv['unsafe-partial']){awaitasyncRimRaf('build');}// Run them serially for better console output// and to avoid any potential race conditions.letbundles=[];// eslint-disable-next-line no-for-of-loops/no-for-of-loops// bundle 即为上面的那一个个配置for(constbundleofBundles.bundles){bundles.push([bundle,UMD_DEV],[bundle,UMD_PROD],[bundle,UMD_PROFILING],[bundle,NODE_DEV],[bundle,NODE_PROD],[bundle,NODE_PROFILING],[bundle,FB_WWW_DEV],[bundle,FB_WWW_PROD],[bundle,FB_WWW_PROFILING],[bundle,RN_OSS_DEV],[bundle,RN_OSS_PROD],[bundle,RN_OSS_PROFILING]);if(__EXPERIMENTAL__){// ......}}// ......// eslint-disable-next-line no-for-of-loops/no-for-of-loopsfor(const[bundle,bundleType]ofbundles){// 开始使用 rollup 进行打包awaitcreateBundle(bundle,bundleType);}// ......}
functiongetPlugins(entry,externals,updateBabelOptions,filename,packageName,bundleType,globalName,moduleType,pureExternalModules){// ......// 获取当前环境的真正代码实现constforks=Modules.getForks(bundleType,entry,moduleType);// ......return[// ......// Shim any modules that need forking in this environment.// 这里 react 自己实现了一个 rollup plugin ,作用就是将一开始的 SchedulerHostConfig.js 文件,根据打包环境来找到对应的真正实现useForks(forks),// ......].filter(Boolean);}
getForks
// Hijacks some modules for optimization and integration reasons.functiongetForks(bundleType,entry,moduleType){constforksForBundle={};Object.keys(forks).forEach(srcModule=>{constdependencies=getDependencies(bundleType,entry);consttargetModule=forks[srcModule](bundleType,entry,dependencies,moduleType);if(targetModule===null){return;}forksForBundle[srcModule]=targetModule;});returnforksForBundle;}
// 做一个缓存letresolveCache=newMap();functionuseForks(forks){letresolvedForks=newMap();Object.keys(forks).forEach(srcModule=>{// 这里就是做上述的 forks 的一个 映射便于下面取数consttargetModule=forks[srcModule];resolvedForks.set(require.resolve(srcModule),// targetModule could be a string (a file path),// or an error (which we'd throw if it gets used).// Don't try to "resolve" errors, but cache// resolved file paths.typeoftargetModule==='string'
? require.resolve(targetModule)
: targetModule);});return{name: 'scripts/rollup/plugins/use-forks-plugin',// 这里从这里开始拦截resolveId(importee,importer){if(!importer||!importee){returnnull;}if(importee.startsWith('\u0000')){// Internal Rollup reference, ignore.// Passing that to Node file functions can fatal.returnnull;}letresolvedImportee=null;letcacheKey=`${importer}:::${importee}`;if(resolveCache.has(cacheKey)){// Avoid hitting file system if possible.resolvedImportee=resolveCache.get(cacheKey);}else{try{resolvedImportee=resolveRelatively(importee,importer);}catch(err){// Not our fault, let Rollup fail later.}if(resolvedImportee){resolveCache.set(cacheKey,resolvedImportee);}}if(resolvedImportee&&resolvedForks.has(resolvedImportee)){// We found a fork!constfork=resolvedForks.get(resolvedImportee);if(forkinstanceofError){throwfork;}returnfork;}returnnull;},};}
导言
在阅读react源码的过程中,遇到了这样的一个模块:
即该文件引用必须由特定的打包来实现。我们知道,react 这个库不只是有 react,还有 react-native、react-server ,还有一些测试环境的运行等。所以由于各个环境的不一样,打包时候的一些实现就不一样。那这一步是在哪里实现的?
react 库的打包跑的是如下命令:
可以看出,其打包用的是 rollup ,而非 webpack。
打包简介
在看打包前,先看看 scripts/rollup/bundles.js 文件,该文件定义了各个react周边包的一个打包方式,看下 react-dom 的一个打包配置:
然后我们来看 build.js 里的主入口:
createBundle 里面就是获取 rollup 打包的一个配置,然后进行 打包,而我们一开始的疑问就是通过rollup 的插件来实现的:
getForks
而上面的 forks 即是一份路径映射表,如下可以看出,该映射表可以根据打包类型,入口,依赖等返回最终的路径文件:
use-forks-plugin
刚才说到,react 自己实现了一个 rollup 插件来实现如上路径的拦截,这就是 use-forks-plugin 插件了:
至此我们就知道了,react 是如何做到根据根据不同的打包环境找到对应的代码实现的了,关于如果写 rollup 插件可以参考如下文章:
• Rollup插件
• Rollup.js插件开发
最后
如有不当或者见解,欢迎交流^_^
The text was updated successfully, but these errors were encountered: