I made a react library converting menu data returned by microservice to dynamic route.
project structure image is below:
--react-app
----node_modules
------ ...
------ rb-react ---> my react library
------ ...
----src
------pages
--------Dashboard.js
--------Prod.js
--------User.js
-------- ...
library rb-react can not import pages, ie 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
Here is some code of my project
dynamic import class
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;
}
dynamic route
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;
Exception Message at Chrome Console
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])));
If you are trying to use async import, you would need to specify the path to the file that you are trying to import. Only then , webpack would be able to create a separate chunk for that file. Here, the way i understand, you are trying to make your import statements dynamic. That would not work. You would need to specify the full path of each of the async import that you make. (this path needs to be available at build time)
Could you please check out require.context if you need to load all modules in a directory. https://webpack.js.org/guides/dependency-management/
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments