react抛出组件化的概念后,对于开发者而言,为了提升代码的可读性与结构性,经过文件目录结构去阐述组件嵌套关系无疑是一个很好的办法,可是目录级别的加深,同时让require的文件路径让人头疼。绝大多数公司会使用本身定制的alias工具,在脚手架入口配置文件中给相应的filePath赋予别名,pack时,进行统一替换。node
#ykit.config ... alias:{ 'Common':'./src/util/index.js', 'Component':'src/components/index.js' } ...
固然也能够在文件中写入惟一的标识位,pack时将该标识位与当前声明标识位的filePath创建联系,facebook提供的@providesModule的就是这一策略。使用方法以下:react
#a.js /** * @providesModule Common */ export const isArray = () => { ... } export const isObject = () => { ... } #b.js import { isArray } from 'Common' isArray([])
fbjs-script/gulp:json
shared/provides-module.js中提供了这样一段正则,用于匹配文件中是否有相似@providesModule的标识符gulp
module.exports = { regexp: /\r?\n \* \@providesModule (\S+)(?=\r?\n)/, };
modules-map.js 中:babel
transform函数调用如上正则对读入文本进行解析,并将alias的别名与filePath创建映射关系ide
flush函数将前面拿到的映射表进行处理加上统一前缀,并导入到json文件中函数
function transform(file, enc, cb) { if (file.isNull()) { cb(null, file); return; } if (file.isStream()) { cb(new gutil.PluginError('module-map', 'Streaming not supported')); return; } // Get the @providesModule piece of out the file and save that. var matches = file.contents.toString().match(PM_REGEXP); if (matches) { var name = matches[1]; if (moduleMap.hasOwnProperty(name)) { this.emit( 'error', new gutil.PluginError( PLUGIN_NAME, 'Duplicate module found: ' + name + ' at ' + file.path + ' and ' + moduleMap[name] ) ); } moduleMap[name] = file.path; } this.push(file); cb(); } function flush(cb) { // Keep it ABC order for better diffing. var map = Object.keys(moduleMap).sort().reduce(function(prev, curr) { // Rewrite path here since we don't need the full path anymore. prev[curr] = prefix + path.basename(moduleMap[curr], '.js'); return prev; }, {}); fs.writeFile(moduleMapFile, JSON.stringify(map, null, 2), 'utf-8', function() { // avoid calling cb with fs.write callback data cb(); }); }
最后导出以下json(以fbjs build为例)工具
{ "BrowserSupportCore": "fbjs/lib/BrowserSupportCore", "CSSCore": "fbjs/lib/CSSCore", "CircularBuffer": "fbjs/lib/CircularBuffer", "DOMMouseMoveTracker": "fbjs/lib/DOMMouseMoveTracker", "DataTransfer": "fbjs/lib/DataTransfer", "Deferred": "fbjs/lib/Deferred", "ErrorUtils": "fbjs/lib/ErrorUtils", "EventListener": "fbjs/lib/EventListener", "ExecutionEnvironment": "fbjs/lib/ExecutionEnvironment", "Heap": "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玩的组件化
其实对于alias system目前提供的两种方法,各有利弊。fb提供的方法,使得使用上更加便利,可是因为alias遍地存在,声明冲突也变得屡见不鲜(固然能够经过统一前缀解决)。传统在脚手架配置文件中声明的方法,虽然能让你对alias的声明一目了然,可是使用上也繁琐不少ui