【前端工程化】对于@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);