When packaging a React project, if asynchronous component handling is not performed, all JavaScript required for all pages is compiled into a single file (bundle.js). This makes the entire JS file very large, causing the initial page load time to be too long.Therefore, components can be loaded asynchronously. Typically, react-loadable can be used.
Using react-loadable For example, for the detail component in the project (/src/pages/detail/), create a new loadable.js in the detail directory:
import React from 'react'; import Loadable from 'react-loadable';
const LoadableComponent = Loadable({ loader: () => import('./index.js'), loading() { return <div>Loading</div> }, });
export default () => <LoadableComponent/> Then in app.js, import the detail component:
// Import method without react-loadable: // import Detail from './pages/detail/index';
// Import method with react-loadable: import Detail from './pages/detail/loadable';
... ...
class App extends Component { render() { return ( <Provider store={store}> <Fragment> <BrowserRouter> ··· ··· <Route path='/detail/:id' exact component={Detail}></Route> ··· ··· </BrowserRouter> </Fragment> </Provider> ) } } However, in the /pages/detail/index.js file, if you want to access the match, location, and history objects of the current route, they will be inaccessible. You need to use withRouter and handle /detail/index.js as follows:
import { withRouter } from 'react-router-dom';
class Detail extends Component { render() { ··· ··· }
componentDidMount() { // After using withRouter, you can get the match object here console.log(this.props.match); this.props.getDetail(this.props.match.params.id); }}
··· ···
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Detail)); withRouter can wrap a non-route component into a route component, allowing the non-route component to access the match, location, and history objects of the current route.
Unified Handling The above method implements dynamic loading for the detail component, but if there are multiple components, you would need to create a loadable.js in each component directory, which is cumbersome. Therefore, we can create a unified wrapper for dynamic loading of all components.
Create a new directory /src/utils and a new file /src/utils/loadable.js
import React from 'react'; import Loadable from 'react-loadable';
export default (loader) => { return Loadable({ loader, loading() { return <div>Loading</div> }, }); } In app.js:
import loadable from './utils/loadable'; import Header from './common/header';
<!--Asynchronously load components--> const Home = loadable(() => import('./pages/home')); const Detail = loadable(() => import('./pages/detail')); const Login = loadable(() => import('./pages/login')); const Write = loadable(() => import('./pages/write'));
class App extends Component {
render() { return ( <Provider store={store}> <Fragment> <BrowserRouter> <div> <Header /> <Switch> <Route exact path="/" render={() => <Redirect to="/home" />} /> <Route path='/home' exact component={Home}></Route> <Route path='/login' exact component={Login}></Route> <Route path='/write' exact component={Write}></Route> <Route path='/detail/:id' exact component={Detail}></Route> <Route render={() => <div>Not Found</div>} /> </Switch> </div> </BrowserRouter> </Fragment> </Provider> ) } }
export default App;
暂无评论。