React route dynamic import and bootstrap cdn

Thank you MDG for dynamic imports and the bundle-visualizer!
I understand that the first render of the app is important hence my signin page needs to be fast.

I see that the two largest node_modules in my app is react-dom (178kB) and bootstrap (151kB).
How can I optimize my app wrt these packages? I already optimized reactstrap from 113kB to 30kB by changing my import statements from import {Link} from ‘react-router-dom’ to: import Link from ‘react-router-dom/Link’; avoiding loading the whole module.

Is there performance to be gained by dynamically importing each route component in react-router4?
Presently my route layout looks like this

const App = appProps => (
  <Router>
    <div className='App'>
      <Switch>
        <Route exact name='index' path='/' component={Signin} {...appProps} />
        <Bidder exact path='/application' component={ApplicationContainer} {...appProps} />
        <Procurer exact path='/procurement' component={ProcurementPage} {...appProps} />
        <Public path='/signup' component={Signup} {...appProps} />
        <Public path='/signin' component={Signin} {...appProps} />
        <Route name='verify-email' path='/verify-email/:token' component={VerifyEmail} />
        <Route name='verify-your-email' path='/verify-your-email' component={VerifyYourEmail} />
        <Route name='recover-password' path='/recover-password' component={RecoverPassword} />
        <Route name='reset-password' path='/reset-password/:token' component={ResetPassword} />
        <Route name='reset-your-password' path='/reset-your-password' component={ResetYourPassword} />
        <Route name='thankyou' path='/thankyou' component={Thankyou} />
        <Route component={NotFound} />
      </Switch>
    </div>
  </Router>
);
1 Like

Hi,
Benjamin referred to this react-router link https://reacttraining.com/react-router/web/guides/code-splitting
That link shows that the componentDidMount lifecycle call can be used to preload the remaining components after first render. I am just not sure what ‘preloadTheRestofTheApp’ is in the last line ReactDOM.render(<App/>, preloadTheRestOfTheApp)

Taking that example further, I have read that in some cases one would like to have the landing page on a separate server from the server hosting the meteor app (less traffic for meteor etc). Can this landing page be used to load the view layer libraries (react, bootstrap) for first render and then preload the libraries on the client that meteor, hosted on another server, would use (eg momentjs, pdfviewers etc)? The preloaded components could be dummy components that simply cache the support libraries on the client.

Below a meteor app that works with cdn links, for bootstrap, react, react-router-dom.
The app size is 392kB (its basically approaching the meteor create --bare size).
My big assumption is that the user visited the landingpage first and that the meteor app is using locally the libraries that the landingpage obtained…
Can the meteor pro’s tell me what the disadvantages are in using this landingpage/cdn approach?

client/main.html

<head>
  <meta charset="utf-8">
  <title>TEST</title>
  <meta name="description" content="Test App">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
  <link rel="shortcut icon" type="image/png" href="favicon.png?v1" sizes="16x16 32x32 64x64">
  <link rel="apple-touch-icon" sizes="120x120" href="apple-touch-icon-precomposed.png">

  <script src="https://unpkg.com/react@latest/dist/react.js"></script>
  <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.1.1/react-router-dom.min.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
  <script src="https://unpkg.com/reactstrap/dist/reactstrap.min.js"></script>

</head>

<body>
  <div id="react-root"></div>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
</body>

imports/startup/client/index.js

// import React from 'react';
// import { render } from 'react-dom';
import { Meteor } from 'meteor/meteor';
import App from '../../ui/layouts/App.js';

Meteor.startup(() => {
  ReactDOM.render(<App />, document.getElementById('react-root'));
});

imports/ui/layout/App.js

// import React from 'react'
// import {
//   BrowserRouter as Router,
//   Route,
//   Link
// } from 'react-router-dom'

const Router = ReactRouterDOM.BrowserRouter;
const Route = ReactRouterDOM.Route;
const Link = ReactRouterDOM.Link;

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
)

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>
          Rendering with React
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>
          Components
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>
          Props v. State
        </Link>
      </li>
    </ul>

    <Route path={`${match.url}/:topicId`} component={Topic}/>
    <Route exact path={match.url} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)
export default BasicExample