UNPKG

@ali-i18n-fe/dada-component

Version:
259 lines (227 loc) 7.72 kB
const { getProgram, } = require("@ali-i18n-fe/react-docgen-typescript-loader-add-tag/dist/loader"); const { withDefaultConfig, } = require("@ali-i18n-fe/react-docgen-typescript-loader-add-tag/dist/docgen-typescript"); const requireFromString = require("require-from-string"); const { buildVisionFromTypes } = require("@ali-i18n-fe/json-2-vision").default; const path = require("path"); const fs = require("fs"); const throttle = require("lodash/throttle"); const set = require("lodash/set"); const { getStoryPathByFilePath, getPreviewPathByFilePath, } = require("../utils"); const { wrapJsDom } = require("../../utils/wrapWindow"); const localVisionPaths = []; const pluginName = "VisionConfigPlugin"; // const Module = require("module"); // get the instance and original require // let firstInstance; // const originalRequire = Module.prototype.require; // Module.prototype.require = function() { // if (!firstInstance) { // firstInstance = this; // } // return {}; // }; // require(""); // Module.prototype.require = originalRequire; class VisionConfigPlugin { constructor(options = {}) { this.name = pluginName; this.options = Object.assign( {}, { // 是否排除没有在 src/index.ts 中导出的组件类型 isFilterExport: false, }, options ); } apply(compiler) { // 循环寻找dependency性能影响太大,暂不开启 // const requireNormalModule = normalModule => { // const { dependencies } = normalModule; // // // rewrite require to load modules // const originalRequireChild = Module.prototype.require; // Module.prototype.require = function(moduleName) { // if (/core-js|babel-runtime/.test(moduleName)) { // return {}; // } // if (/@ali|moment|lodash/.test(moduleName)) { // return {}; // } // // const dependency = dependencies.find( // ({ request }) => request === moduleName // ); // const { module: moduleFound } = dependency || {}; // // if (/^\./.test(moduleName)) { // if (moduleFound && moduleFound._source) { // try { // return requireNormalModule(moduleFound); // } catch (e) { // debugger; // } // } // } // // try { // return originalRequire.apply(this, arguments); // } catch (e) { // debugger; // } // }; // Module.prototype.require.originalRequireChild = originalRequireChild; // // const source = normalModule._source._value; // const exportModules = requireFromString(source); // // Module.prototype.require = originalRequireChild; // // return exportModules; // }; // // const indexModule = compilation.modules.find(module => // new RegExp(path.resolve(context.rootPath, "/src/index.ts") + "x?$").test( // module.resource // ) // ); let parser, program; compiler.hooks.emit.tap(pluginName, (compilation) => { // Add file dependencies const getSource = throttle(() => { let moduleNames; const targetMap = {}; try { // const { default: exportModules } = wrapJsDom(requireNormalModule)( // indexModule // ); // dev 环境下收到webpack-dev-server的影响,暂不开启Map过滤 if ( compiler.options.mode === "production" && !!compilation.assets["index.js"] ) { const exportModules = wrapJsDom(requireFromString)( compilation.assets["index.js"].source() ); if ( (typeof exportModules === "function" || (typeof exportModules === "object" && typeof exportModules.$$typeof === "symbol" && typeof exportModules.render === "function")) && "displayName" in exportModules ) { // single component moduleNames = new Set([exportModules.displayName]); } else { moduleNames = new Set(Object.keys(exportModules)); } } } catch (e) { // console.log(e); } const filePaths = program .getRootFileNames() .filter((fileName) => !/docs\.tsx?$/.test(fileName)) .filter((fileName) => !/\.d\.ts$/.test(fileName)); filePaths.forEach((filePath) => { const componentDocs = parser.parseWithProgramProvider( filePath, () => program ); componentDocs.forEach((compDocs) => { const { displayName, tags } = compDocs; const annotationConfig = Object.entries(tags).reduce( (previousValue, [key, value]) => { if (/^vision\./.test(key)) { const { vision } = set({}, key, value); return Object.assign(previousValue, vision); } return Object.assign(previousValue, { [key]: value, }); }, {} ); // 过滤未暴露的组件 if (!moduleNames || moduleNames.has(displayName)) { const previewFile = path.resolve(filePath, "..", "docs.tsx"); const isExistPreview = fs.existsSync(previewFile); const typeVisionConfig = buildVisionFromTypes(compDocs, { defaultConfig: Object.assign( {}, { __previewPath: isExistPreview && getPreviewPathByFilePath( { _compiler: compiler, }, filePath ), __storyPath: isExistPreview && getStoryPathByFilePath( { _compiler: compiler, }, filePath ), }, annotationConfig, getVisionDefault(filePath) ), }); targetMap[typeVisionConfig.componentName] = typeVisionConfig; } }); }); return targetMap; }, 10000); parser = withDefaultConfig({}); program = getProgram(path.resolve(process.cwd(), "src")); const targetPath = "vision.config.json"; compilation.assets[targetPath] = { size() { return JSON.stringify(getSource()).length; }, source() { return JSON.stringify(getSource()); }, }; }); compiler.hooks.afterEmit.tap(pluginName, (compilation) => { // Add file dependencies compilation.fileDependencies.add("vision.config.json"); // console.log("#################", localVisionPaths); localVisionPaths.forEach((filePath) => { compilation.fileDependencies.add(filePath); }); }); } } function getVisionPath(filePath) { return path.resolve(filePath, "..", "vision.config.json"); } function getVisionDefault(filePath) { const visionPath = getVisionPath(filePath); try { if (!fs.existsSync(visionPath)) { return null; } const visionResult = JSON.parse(fs.readFileSync(visionPath, "utf8")); if (!localVisionPaths.includes(visionPath)) { localVisionPaths.push(visionPath); } return visionResult; } catch (e) { return null; } } module.exports = VisionConfigPlugin;