Monday, September 25, 2017

React router 4 - routing + code splitting, with webpack 1.9

Leave a Comment

I'm trying to upgrade a 2 year old react codebase to use the latest react and react-router. I haven't touched the webpack config at all, and I'm assuming I wouldn't need to. I'm new to the react world, so please bear with me. I have a few questions that I'll bundle into this one question, so it'll be fairly long.

  1. Bundles:

The webpack config loads a js file as an entry point.

var entry = { appBundle : ["./src/index.js"] } 

and in index.js, we're doing something like:

var mainRoutes = {     component: "div",     childRoutes: [     {        path: "/",        component: require("./components/LandingPage.jsx"),        childRoutes: [             require("./components/dashboard"),             ..             ..        ]     } } 

and then,

React.render(    React.createElement(Router, { history: browserHistory, routes: mainRoutes }),    document.getElementById("app-container")  ); 

I've kept the entry point same, but I've changed the content of index.js to something like:

ReactDOM.render((    <BrowserRouter>      <LandingPage />    </BrowserRouter>  ), document.getElementById("app-container")); 

and inside LandingPage.jsx, I've defined all top-level routes like so:

render() {     return (            <main>         <Switch>           <Route path='/dashboard' component={Dashboard}/>            ..         </Switch>       </main>      );   } 

The routing works fine and everything is ok. But the difference I see is that webpack used to emit something like:

    Asset              Size                 Chunks           Chunk Names                                             14      appBundle.js       xxx kB               0                appBundle     dashboard.js       xxx kB               1                dashboard  .. and so on for most components 

but now it's at:

Asset              Size                 Chunks           Chunk Names                                         1  appBundle.js       xxx kB               0                appBundle 

so Q1: am I missing some configurations for creating the bundles as before?

  1. getComponents

In each of our component folder, we have a index.js file, which has content like so:

"use strict";   module.exports = {    path: "dashboard",     getComponents(location, cb) {      require.ensure([], (require) => {        cb(null, require("./Dashboard.jsx"));      }, "dashboard");    }  }; 

I know getComponents isn't supported anymore in react router v4. Did this piece of code load the component asynchronously (and that created the different bundles?)?

Q2: What should replace getComponents and index.js files?

  1. Nested routes

React router 4 doesn't support nested routes, and I'm supposed to add the components wherever I need nested routes. But I'm not sure where. Say, our components look like so:

"use strict";   // import stuff  class DashboardContainer extends React.Component {    render() {      return (        <Dashboard {...this.props} />      );    }  }   class Dashboard extends React.Component {         render() {      return (        <div></div>        <SomeOtherComponent/>      );    }  }   export default DashboardContainer; 

I changed this to (with all other code the same)

class Dashboard extends React.Component {             render() {          return (            <div>                <div></div>                <SomeOtherComponent/>                <Route path='/childComponent' component={ChildComponent}/>            </div>          );        }      } 

but the child component does not render.

Q3: Where do I need to define the child/nested component route?

Let me know if there's any more information needed. Thanks.

1 Answers

Answers 1

A1: That is called code splitting. I am not too familiar with it, but the general concept is splitting the main components into separate bundles in order to increase the load speed of your application. This article does a good job of explaining how that used to function with the older react-router versions.

Also, there is a small guide in the new react-router-dom docs that discusses code splitting in v4 as well.

A2/A3: As you mentioned, v4 has really changed the way we render our routes. With the push of more dynamic routes and new components such as Switch, we must now do all our nested routing within the parent components of each nested route. For example you could do the following:

Main.js

ReactDOM.render((   <BrowserRouter>     <App/>   </BrowserRouter> ), el) 

First, we declare the BrowserRouter component to handle the browser history to keep the UI in sync.

App.js

const App = () => (   <div>     <Nav />      <Switch>       <Route exact path="/" component={Home}/>       <Route path="/dashboard" component={Dashboard}/>     </Switch>      <Footer />   </div> ) 

Second, we declare our main switch statement within our App container which will handle the routing of all the parent routes.

Dashboard.js

const Dashboard = () => (   <div>     <h1>Welcome to the Dashboard!</h1>     <Switch>       <Router exact path="/dashboard component={MainView}/>       <Route path="/dashboard/child-one" component={MainChildOne}/>       <Route path="/dashboard/child-two" component={MainChildTwo}/>     </Switch>   </div> ) 

Lastly, within our parent route, we declare another switch statement that will handle all the nested child routes within our parent.

Good luck!

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment