当前位置: 首页 > 后端技术 > Node.js

React原理探索-@providesModule模块系统

时间:2023-04-03 17:22:05 Node.js

React原理探索-@providesModule模块系统@providesModule什么是react?文件目录结构无疑是一个很好的解释组件嵌套关系的方式,但是目录层级的加深也让require文件路径变得头疼。大多数公司会使用自己定制的别名工具,为脚手架入口配置文件中对应的filePath分配别名,打包时统一替换。#ykit.config...alias:{'Common':'./src/util/index.js','Component':'src/components/index.js'}...当然也可以这么写在文件中输入一个唯一的标识位,打包时将该标识位与当前声明的标识位的filePath建立联系。facebook提供的@providesModule就是这个策略。用法如下:#a.js/***@providesModuleCommon*/exportconstisArray=()=>{...}exportconstisObject=()=>{...}#b.jsimport{isArray}from'Common'isArray([])如何实现@providesModulefbjs-script/gulp:shared/provides-module.js提供了这样一个regex来匹配文件中是否有@providesModule这样的标识符module.exports={正则表达式:/\r?\n\*\@providesModule(\S+)(?=\r?\n)/,};在modules-map.js中:如上调用transform函数解析读取的文本,并建立alias的别名与filePath的映射关系。flush函数对前面获取到的映射表进行处理,加上统一的前缀,导入到json文件中。functiontransform(file,enc,cb){if(file.isNull()){cb(null,file);返回;}if(file.isStream()){cb(newgutil.PluginError('module-map','Streamingnotsupported'));返回;}//获取文件的@providesModule片段并保存。varmatches=file.contents.toString().match(PM_REGEXP);如果(匹配){varname=matches[1];if(moduleMap.hasOwnProperty(name)){this.emit('error',newgutil.PluginError(PLUGIN_NAME,'发现重复模块:'+name+'at'+file.path+'and'+moduleMap[name]));}moduleMap[name]=file.path;}this.push(文件);cb();}functionflush(cb){//保持ABC顺序以便更好地比较。varmap=Object.keys(moduleMap).sort().reduce(function(prev,curr){//在这里重写路径,因为我们不再需要完整路径。prev[curr]=prefix+path.basename(moduleMap[curr],'.js');returnprev;},{});fs.writeFile(moduleMapFile,JSON.stringify(map,null,2),'utf-8',function(){//避免使用fs.write回调数据调用cb();});}最后导出如下json(以fbjsbuild为例){"BrowserSupportCore":"fbjs/lib/BrowserSupportCore","CSSCore":"fbjs/lib/CSSCore","CircularBuffer":"fbjs/lib/CircularBuffer","DOMMouseMoveTracker":"fbjs/lib/DOMMouseMoveTracker","DataTransfer":"fbjs/lib/DataTransfer","延迟":“fbjs/lib/Deferred”,“ErrorUtils”:“fbjs/lib/ErrorUtils”,“EventListener”:“fbjs/lib/EventListener”,“ExecutionEnvironment”:“fbjs/lib/ExecutionEnvironment”,“堆”:“fbjs/lib/Heap","IntegerBufferSet":"fbjs/lib/IntegerBufferSet","Keys":"fbjs/lib/Keys","Locale":"fbjs/lib/Locale","Map":"fbjs/lib/Map”,“PhotosMimeType”:“fbjs/lib/PhotosMimeType”,“PrefixIntervalTree”:“fbjs/lib/PrefixIntervalTree”,“Promise”:“fbjs/lib/Promise”,“PromiseMap”:“fbjs/lib/PromiseMap",}那么大家就知道怎么做了。要么node脚本替换文件中require的别名对应的路径,要么通过babel替换。当然facebook是通过babel玩的。实际上,目前别名系统提供的两种方式各有优缺点。fb提供的方法使用起来更加方便,但是由于到处都存在alias,声明冲突成了家常便饭(当然可以通过统一的前缀来解决)。传统的在脚手架配置文件中声明的方式虽然可以一目了然的声明别名,但是使用起来也繁琐很多