【前端工程化】对于@babel/traverse和AST的研究
通过AST解析reExport文件,生成组件和工具路径的json文件
reExport文件
export { default as Button } from './components/Button/'; export { default as Checkbox, CheckboxGroup } from './components/Checkbox'; export { default as Chip } from './components/Chip'; export { default as DatePicker } from './components/DatePicker'; export { default as Dialog } from './components/Dialog'; export { default as DragDropFileUpload } from './components/DragDropFileUpload'; export { default as DropdownButton } from './components/DropdownButton/'; ...
path.js (可以放到其他文件里执行)
const parser = require('@babel/parser'); const traverse = require('@babel/traverse').default; const { writeFile, readFileSync } = require('fs'); const { resolve } = require('path'); const indexFile = readFileSync(resolve(__dirname, './index.js'), 'utf-8'); const ast = parser.parse(indexFile, { sourceType: 'module', plugins: ['jsx'], }); const pathObj = {}; let route = null; traverse(ast, { enter(path) { if (path.node.type === 'ExportSpecifier') { const { node: { exported: { name }, }, } = path; pathObj[name] = route[route.length - 1] === '/' ? route.substring(0, route.length - 1) : route; } if (path.node.type === 'ExportNamedDeclaration') { const { node: { source: { value }, }, } = path; route = value.replace('./', ''); } if ( path.node.type.indexOf('ExportSpecifier') < 0 && path.node.type === 'ExportAllDeclaration' ) { const { node: { source: { value }, }, } = path; route = value; let rootRoute = null; const reExportFile = readFileSync( resolve(__dirname, `${route}/index.js`), 'utf-8' ); const reExportAST = parser.parse(reExportFile, { sourceType: 'module', plugins: ['jsx'], }); traverse(reExportAST, { enter(path) { if (path.node.type === 'ExportSpecifier') { const { node: { exported: { name }, }, } = path; pathObj[name] = rootRoute[rootRoute.length - 1] === '/' ? rootRoute.substring(0, rootRoute.length - 1) : rootRoute; } if (path.node.type === 'ExportNamedDeclaration') { rootRoute = route; const { node: { source: { value }, }, } = path; rootRoute = `${rootRoute.replace('./', '')}${value.substring(1)}`; } }, }); } }, }); writeFile( resolve(__dirname, 'paths.json'), JSON.stringify(pathObj, null, '\t'), err => { if (err) throw new Error(); } );
path.json 放在src目录下
{ "CoreConfig": "config", "prefixIt": "utilities", "errorMessage": "utilities", "useClickOutside": "hooks/useClickOutside", "useFocus": "hooks/useFocus", "useForceUpdate": "hooks/useForceUpdate", "useForkRef": "hooks/useForkRef", "usePrevious": "hooks/usePrevious", "useResizeObserver": "hooks/useResizeObserver", "useEventCallback": "hooks/useEventCallback", "useTabsLoop": "hooks/useTabsLoop", "useUncontrolled": "hooks/useUncontrolled", "useIsomorphicLayoutEffect": "hooks/useIsomorphicLayoutEffect", "Button": "components/Button", "Checkbox": "components/Checkbox", "CheckboxGroup": "components/Checkbox", "Chip": "components/Chip", "DatePicker": "components/DatePicker", "Dialog": "components/Dialog", "DragDropFileUpload": "components/DragDropFileUpload", "DropdownButton": "components/DropdownButton", "DropdownMenu": "components/DropdownMenu", "DropdownItem": "components/DropdownMenu", "Error": "components/Error", "FieldPicker": "components/FieldPicker", "FormControl": "components/FormControl", "FormInput": "components/FormInput", "Container": "components/Grid", "Row": "components/Grid", "Col": "components/Grid", "Visible": "components/Grid", "Hidden": "components/Grid", "ClearFix": "components/Grid", "ScreenClassRender": "components/Grid", "ScreenClassProvider": "components/Grid", "useScreenClass": "components/Grid", "GridLoader": "components/GridLoader", "Icon": "components/Icon", "IconDefinitions": "components/Icon", "IconNames": "components/Icon", "InlineMessageBlock": "components/InlineMessageBlock", "KeyboardCapture": "components/KeyboardCapture", "Link": "components/Link", "Matomo": "components/Matomo", "matomoMiddleware": "components/Matomo", "MatomoContext": "components/Matomo", "MatomoProvider": "components/Matomo", "useMatomo": "components/Matomo", "List": "components/List", "Item": "components/List", "ItemDivider": "components/List", "Modal": "components/Modal", "NavigableList": "components/NavigableList", "Popover": "components/PopoverModal", "PopoverDialog": "components/PopoverDialog", "ProgressSpinner": "components/ProgressSpinner", "Radio": "components/Radio", "RadioGroup": "components/Radio", "RedirectConfirmation": "components/RedirectConfirmation", "ReduxFormHelpers": "components/ReduxFormHelpers", "RichTextEditor": "components/RichTextEditor", "Select": "components/Select", "SplitButton": "components/SplitButton", "StyledIcon": "components/StyledIcon", "Svg": "components/Svg", "Tabs": "components/Tabs", "Tab": "components/Tabs", "TabList": "components/Tabs", "TabPanel": "components/Tabs", "Tags": "components/Tags", "TextArea": "components/TextArea", "TextInput": "components/TextInput", "TimePicker": "components/TimePicker", "toast": "components/ToastContainer", "ToastContainer": "components/ToastContainer", "Toggle": "components/Toggle", "Tooltip": "components/Tooltip", "Fade": "components/Transition", "Typeahead": "components/Typeahead", "TypeaheadBuilder": "components/TypeaheadBuilder", "VectorGraphic": "components/VectorGraphic", "ViewAllModal": "components/ViewAllModal", "ViewAll": "components/ViewAll", "Truncate": "components/Truncate", "Skeleton": "components/Skeleton" }
读取JSON文件并使用
const data = readFileSync( path.resolve( __dirname, '../node_modules/react-core/dist/esm/paths.json' ), 'utf-8' );
const libraryObject = JSON.parse(data);