UNPKG

@umijs/plugins

Version:
175 lines (162 loc) 5.24 kB
// @ts-nocheck /* eslint-disable */ /** * @author Kuitos * @since 2019-06-20 */ import React, { ReactComponentElement } from 'react'; import { Navigate, type IRouteProps } from 'umi'; export const defaultMountContainerId = 'root-subapp'; // @formatter:off export const noop = () => {}; // @formatter:on export function toArray<T>(source: T | T[]): T[] { return Array.isArray(source) ? source : [source]; } function testPathWithStaticPrefix(pathPrefix: string, realPath: string) { if (pathPrefix.endsWith('/')) { return realPath.startsWith(pathPrefix); } const pathRegex = new RegExp(`^${pathPrefix}([/?])+.*$`, 'g'); const normalizedPath = `${realPath}/`; return pathRegex.test(normalizedPath); } // function testPathWithDynamicRoute(dynamicRoute: string, realPath: string) { // // FIXME 这个是旧的使用方式才会调到的 api,先临时这么苟一下消除报错,引导用户去迁移吧 // const pathToRegexp = require('path-to-regexp'); // return pathToRegexp(dynamicRoute, { strict: true, end: false }).test( // realPath, // ); // } // // export function testPathWithPrefix(pathPrefix: string, realPath: string) { // return ( // testPathWithStaticPrefix(pathPrefix, realPath) || // testPathWithDynamicRoute(pathPrefix, realPath) // ); // } export function patchMicroAppRoute( route: any, getMicroAppRouteComponent: (opts: { appName: string; base: string; routePath: string; masterHistoryType: string; routeProps?: any; }) => string | ReactComponentElement<any>, masterOptions: { base: string; masterHistoryType: string; routeBindingAlias: string; }, ) { const { base, masterHistoryType, routeBindingAlias } = masterOptions; // 当配置了 routeBindingAlias 时,优先从 routeBindingAlias 里取配置,但同时也兼容使用了默认的 microApp 方式 const microAppName = route[routeBindingAlias] || route.microApp; const microAppProps = route[`${routeBindingAlias}Props`] || route.microAppProps || {}; if (microAppName) { if (route.children?.length) { const childrenRouteHasComponent = route.children.some( (r: any) => r.element, ); if (childrenRouteHasComponent) { throw new Error( `[@umijs/plugin-qiankun]: You can not attach micro app ${microAppName} to route ${route.path} whose children has own component!`, ); } } // 自动追加通配符,匹配子应用的路由 if (!route.path.endsWith('/*')) { route.path = route.path.replace(/\/?$/, '/*'); } const { settings = {}, ...componentProps } = microAppProps; const routeProps = { // 兼容以前的 settings 配置 settings: route.settings || settings || {}, ...componentProps, }; const opts = { appName: microAppName, base, routePath: route.path, masterHistoryType, routeProps, }; route.element = React.createElement(getMicroAppRouteComponent(opts), null); } else if (route.redirect) { // patchClientRoutes 插入的 redirect 不会被转换,所以这里需要手动处理成重定向组件 route.element = React.createElement(Navigate, { to: route.redirect, replace: true, }); } } const recursiveSearch = ( routes: IRouteProps[], path: string, parentPath: string, ): [IRouteProps, IRouteProps[], number, string] | null => { for (let i = 0; i < routes.length; i++) { if (routes[i].path === path) { return [routes[i], routes, i, parentPath]; } if (routes[i].children && routes[i].children?.length) { const found = recursiveSearch( routes[i].children || [], path, routes[i].path, ); if (found) { return found; } } } return null; }; export function insertRoute(routes: IRouteProps[], microAppRoute: IRouteProps) { const mod = microAppRoute.appendChildTo || microAppRoute.insert ? 'appendChildTo' : microAppRoute.insertBefore ? 'insertBefore' : undefined; const target = microAppRoute.appendChildTo || microAppRoute.insert || microAppRoute.insertBefore; const [found, foundParentRoutes = [], index = 0, parentPath] = recursiveSearch(routes, target, '/') || []; if (found) { switch (mod) { case 'appendChildTo': if ( !microAppRoute.path || !found.path || !microAppRoute.path.startsWith(found.path) ) { throw new Error( `[plugin-qiankun]: path "${microAppRoute.path}" need to starts with "${found.path}"`, ); } found.exact = false; found.children = found.children || []; found.children.push(microAppRoute); break; case 'insertBefore': if ( !microAppRoute.path || !found.path || !microAppRoute.path.startsWith(parentPath) ) { throw new Error( `[plugin-qiankun]: path "${microAppRoute.path}" need to starts with "${parentPath}"`, ); } foundParentRoutes.splice(index, 0, microAppRoute); break; } } else { throw new Error(`[plugin-qiankun]: path "${target}" not found`); } }