我制作了一个反应库,将微服务返回的菜单数据转换为动态路由。
项目结构图如下:
--react-app
---- node_modules
------ ...
------ rb-react --->我的React库
------ ...
---- src
------页
-------- Dashboard.js
-------- Prod.js
-------- User.js
-------- ...
库rb-react无法导入页面,即Dashboard.js
let rootPath = path.resolve(__dirname, '../src/pages');
let menuPath = menuCommand.replace('#', '');
let importObject = asyncComponent(() =>
import(rootPath + '/' + menuCommand.split('/')[1])
);
if (isEmpty(routeResultArray)) {
routeResultArray.push(
<Route key={menuKey} exact path='/' component={importObject} />
);
}
node --version
v12.6.0
npm --version
6.11.3
这是我的项目的一些代码
动态导入类
export default function asyncComponent(importComponent) {
class RbImport extends Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : <></>;
}
}
return RbImport;
}
动态路线
import React from 'react';
import path from 'path';
import { HashRouter, Route, Switch } from 'react-router-dom';
import ScrollToTop from './ScrollToTop';
import App from '../../App';
import { RbLibraryComponent } from './RbLibraryComponent';
import { RbLocalStorage } from '../util/RbLocalStorage';
import { NotFound } from '../notfound/NotFound';
import { isEmpty } from '../util/RbUtil';
import asyncComponent from '../util/RbImport';
export class RbRoute extends RbLibraryComponent {
constructor() {
super();
this.state = {};
this.RbLocalStorage = new RbLocalStorage();
this.composeRoute = this.composeRoute.bind(this);
this.recursiveComposeRoute = this.recursiveComposeRoute.bind(this);
}
composeRoute() {
let routeResultArray = [];
let userMenus = this.RbLocalStorage.loadUserMenu();
this.recursiveComposeRoute(routeResultArray, userMenus, null);
return routeResultArray;
}
recursiveComposeRoute(routeResultArray, menuDataList, prefixKey) {
if (isEmpty(menuDataList)) {
return;
}
prefixKey = isEmpty(prefixKey) ? '' : prefixKey;
let userMenuCount = menuDataList.items.length;
for (let idx = 0; idx < userMenuCount; idx++) {
let userMenu = menuDataList.items[idx];
if (isEmpty(userMenu)) {
continue;
}
let menuKey = isEmpty(prefixKey) ? idx : prefixKey + '-' + idx;
let menuCommand = userMenu.command;
if (isEmpty(menuCommand)) {
//nothing
} else {
let rootPath = path.resolve(__dirname, '../src/pages');
let menuPath = menuCommand.replace('#', '');
let importObject = asyncComponent(() =>
import(rootPath + '/' + menuCommand.split('/')[1])
);
if (isEmpty(routeResultArray)) {
routeResultArray.push(
<Route key={menuKey} exact path='/' component={importObject} />
);
}
routeResultArray.push(
<Route key={menuKey} path={menuPath} component={importObject} />
);
}
if (isEmpty(userMenu.items)) {
//nothing
} else {
this.recursiveComposeRoute(routeResultArray, userMenu, menuKey);
}
}
}
render() {
let { menu, productionName, userName } = this.props;
if (menu === null || menu === undefined) {
return <></>;
}
return (
<HashRouter>
<ScrollToTop>
<App menu={menu} userName={userName}>
<Switch>
{this.composeRoute()}
<Route component={NotFound} />
</Switch>
</App>
</ScrollToTop>
</HashRouter>
);
}
}
export default RbRoute;
Chrome控制台上的异常消息
Uncaught (in promise) Error: Cannot find module '/src/pages/Dashboard'
at webpackContextResolve (^.*$:29)
at webpackContext (^.*$:24)
at RbRoute.js:221 --> (Compiled Source) return _interopRequireWildcard(require("".concat(rootPath + '/' + menuCommand.split('/')[1])));
答案 0 :(得分:0)
如果您尝试使用异步导入,则需要指定要导入的文件的路径。只有这样,webpack才能为该文件创建一个单独的块。以我的理解,您正在尝试使导入语句动态化。那行不通。您将需要指定所进行的每个异步导入的完整路径。 (此路径必须在构建时可用)
如果您需要将所有模块加载到目录中,是否可以签出require.context。 https://webpack.js.org/guides/dependency-management/