outer

React Router & Webpack in Production

I’ve been working on a pretty large react-router codebase at work. Currently it has around 50~ code splits, which as you can imagine, is a lot of routes. This is going to be a post on the things I’ve learned throughout building out my development / production config and how we are using webpack in production.

###Initial Setup

Before I really dive into how my webpack config is setup and the problems I’ve found, I’ll quickly go over how this app is setup. Currently, there’s one entry point and it looks like this:

import React from 'react'
import { render } from 'react-dom'
import { match, Router, browserHistory } from 'react-router'
import AsyncProps from 'async-props'
import routes from '../routes/index'
/* globals document, window */

const { pathname, search, hash } = window.location
const location = `${pathname}${search}${hash}`

match({ routes, location }, () => {
  render(
    <Router
      render={props => <AsyncProps {...props}/>}
      routes={routes}
      history={browserHistory}
    />,
    document.getElementById('app')
  )
})

It looks like a standard react-router setup, except a couple things are different. For one, there’s way too many routes to have them all in this file, so we are importing the main route object into this file. Second, we are using match on the client side. Without matching first, the client side would try to render before the splits were downloaded causing an error. You can read a little more about match on the client here.

Next, we are using Ryan Florence’s awesome async-props library for loading data into components. It allows me to load data from an api before the server renders components. It will pass the data down to the client for the client-side render, and then data will load as you navigate to new pages automatically.

###Routes

Our main routes file looks like this:


export default {
  component: 'div',
  path: '/',
  indexRoute: require('./index'),
  childRoutes: [
    require('./login'),
    require('./account'),
    ...
  ]
}

There’s a lot more require’s in our app of course. And these are nested pretty deep. The files referenced in the root file have more child routes, and those use require.ensure which you can read about in the webpack docs on code splitting. It tells webpack to make a new bundle, and then load that bundle when require.ensure is called on the client. Here’s an example:

if(typeof require.ensure !== "function") require.ensure = function(d, c) { c(require) }

module.exports = {
  path: 'account',
  getComponent(location, cb) {
    require.ensure([], (require) => {
      cb(null, require('../../views/master/index.jsx'))
    })
  },
  childRoutes: [
    require('./settings'),
  ]
}

There’s a few things going on here. First, we have a function at the top that will polyfill require.ensure. Why? Well, on this project we are server rendering our whole site as well, which I would rather not do, but due to the type of site we are building: we have to. The next thing is the relative require path. I’m using this awesome babel resolver plugin along with webpack’s resolve paths so that I can import files like this:

import Header from '../../master/header'
//becomes
import Header from 'master/header'

Why do I have to use a babel plugin AND webpack’s resolve feature? Once again, doing a server rendered app, the code is ran on the server and also through webpack. In this particular app, I haven’t had time to experiment with webpacking the server. Anyways, if I didn’t use the babel plugin, errors would be thrown on the server, but webpack would work fine. This is one of the common things I have ran into while building this app.

Realizing some things need to be done slightly different on the server or client. You may still be wondering why I am referencing the component as a relative path in the above route example, and that’s because the babel plugin I’m using only works with import and not require. My route objects are the one place that I have these “nasty” looking paths.

##Webpack

I was prompted to make this article after tweeting this out:

A couple people wanted a better explanation as to what’s happening here. When I was first building my production webpack config, even after using all of these plugins:

new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
  compress: { warnings: false },
  comments: false,
  sourceMap: false,
  mangle: true,
  minimize: true
}),

My bundle looked like this:

That’s pretty huge if you think about it. And I’m not talking about the amount of bundles. I’m talking about the file size. After searching everywhere for a solution to get the bundle size down further, I found webpack’s AggressiveMergingPlugin. This thing is a life saver. As you may have seen from the tweet, the output turns into this:

Just having the main, vendor, and one other bundle brings the whole site under 1MB. I’m using the plugin to only merge files if the size reduction is more than 50%, which is the default.

People talk about code splitting in webpack and think it’s really amazing to load the JS for the page you’re on and nothing more. It sounds great. The problem is that the file size is immensely bigger. If someone more familiar with webpack has a better idea as to why this is, I’d like a better explanation. It isn’t feasable to keep the splits instead of merging them. This site is pretty large, with a lot of routes as you can tell from the screenshots. Codesplitting without merging would cause way more waiting on the client side every time you navigate to a new page. Even if the JS was heavily cached, the first time you hit these pages it will have to load a 300kb bundle for some of them.

##Caching

That takes us to caching. We are about a month away from publicly launching this site, so we haven’t setup the workflow for pushing updates through a cdn, but that will be the end result. For now, in my webpack config, my output object looks like this:

output: {
  path: __dirname + '/public/assets/js/[hash]/',
  filename: '[name].js',
  chunkFilename: '[id].js',
  publicPath: '/assets/js/[hash]/'
},

This is in the production config of course. This way I can cache the files and when I update the code, the hash will change and the browser won’t be caching the old code. I pass in the hash as an env variable at runtime to that the server has the correct path to the assets folder.

##Problems

There were a few big problems I came across while building out a server rendered app with dynamic routes. The first was page titles. How am I supposed to have the right title on the client and on the initial server render? Thankfully, Ryan has yet another solution. react-title-component solves this perfectly.

The next was, how do I hit an api, wait for the response on server render, load new data on route changes, and of course, do this at the component level. As I mentioned before, async-props solves this problem too. It will give you route info so that you can make requests based on things in the url.

The next problem is one that I haven’t fully solved. Webpack is getting really slow. It takes around 20 seconds on a maxed out macbook 15” to build code in production. On the server, it takes more like a minute! If I’m in development mode, it takes around 10 seconds to make the initial build, and sometimes it lags on building the splits on code change. If anyone has insight into this I would love to hear it.

This one goes along with the webpack one, and it is reloading the server. I haven’t tried to webpack the server but I hear doing so works great for this. I don’t think it would fix the problem with webpack being slow though, and in fact it would probably make it even slower.

##Folder structure

I almost forgot to throw this one in here! I’m really happy with the structure of this project. I have a views folder that has all of the same folders and file names as the routes folder. It makes it really easy to find things. These also correspond with the URL to the page. /account/settings will be in views/account/settings.jsx and routes/account/settings.js. The same is true for my tests folder.

##Conclusion

I hope this gave you a good glimpse at how webpack and react router work at a larger scale than you see most blog posts cover. If you have any questions or things that you would like me to talk about that I haven’t already, please leave a comment below and I will update this post! I’m sure that I forgot a few problems and tips writing this. I was thinking this would be a short post but it blew up on me!




outer

Japan Imports of Men S & Boy S Outer Garments

Imports of Men S & Boy S Outer Garments in Japan increased to 47646.06 JPY Million in March from 32755.64 JPY Million in February of 2020. Imports of Men S & Boy S Outer Garments in Japan averaged 36655.74 JPY Million from 1988 until 2020, reaching an all time high of 77269.29 JPY Million in September of 2015 and a record low of 5424.11 JPY Million in June of 1988. This page includes a chart with historical data for Japan Imports of Men S & Boy S Outer Garments.




outer

Commuters in India squeeze onto buses while police in Nepal arrest lockdown flouters

The coronavirus pandemic has affected more than half a million people worldwide, with more than 28,000 deaths recorded.




outer

Peek-a-boo! How to pull off the underwear as outerwear trend this fall like supermodel Gigi Hadid

Gigi Hadid is the latest celeb to get on board with the underwear as outerwear trend. Over the weekend, the supermodel was spotted in New York City putting her own spin on the provocative look.




outer

Kaia Gerber and Gigi Hadid model oversized outerwear on the runway for Proenza Schouler's NYFW show 

They are two of the busiest models in the middle of New York Fashion Week. And Kaia Gerber joined Gigi Hadid on the runway for Proenza Schouler's Monday show.




outer

Putin brings in drones to spot lockdown flouters as Russia suffers record rise with 10,633 new cases

Deaths from coronavirus rose by 58 to 1,280, official figures show, as Russia is now recording more new infections than any European country. New infections rose with 10,633 cases in the past 24 hours.




outer

A flaw in chips powering Wi-Fi routers left more than ONE BILLION devices open to being hacked

A patch has been issued, but researchers, who revealed the flaw for the first time at a security conference, say it exposed data being sent from a device over at-home and enterprise networks.




outer

Tenda Launches F6 V4.0 Wi-Fi Router With Qualcomm Chipset In India

Tenda launches its latest F6 V4.0 Wi-Fi router today in the Indian market. The newly launched router is a successor to the existing series and the company claims it comes with better performance strengthening the existing portfolio of the brand. F6




outer

Outer Ring Road Delhi

Outer Ring Road Delhi




outer

The moon: from inner worlds to outer space / edited by Lærke Rydal Jørgensen and Marie Laurberg ; translations, Glen Garner, James Manley, Jane Rowley

Barker Library - NX650.M6 M663 2018




outer

[ASAP] Potentiation of Antibiotics against Gram-Negative Bacteria by Polymyxin B Analogue SPR741 from Unique Perturbation of the Outer Membrane

ACS Infectious Diseases
DOI: 10.1021/acsinfecdis.9b00159




outer

International organizations and member state responsibility : critical perspectives / edited by Ana Sofia Barros, Cedric Ryngaert, Jan Wouters




outer

NASA Tests Robotic Gas Station Attendant for Outer Space

See how NASA tests a robotic gas station attendant for outer space.




outer

5-Year-Olds Ask an Astronaut What It’s Like to Be in Outer Space

Why don’t space shuttles float away? How do you know when to go to sleep? Astronaut Kjell Lindgren answers questions about life in space from a few intrepid kindergartners.




outer

Achieving ultrahigh volumetric performance of graphene composite films by an outer–inner dual space utilizing strategy

J. Mater. Chem. A, 2020, Advance Article
DOI: 10.1039/C9TA13585E, Paper
Cong Huang, Qunli Tang, Qiushui Feng, Yanhua Li, Yali Xu, Yan Zhang, Aiping Hu, Shiying Zhang, Weina Deng, Xiaohua Chen
An outer–inner dual space utilizing strategy is reported for the fabrication of an ultrahigh volumetric performance polydopamine-coated dopamine/reduced graphene oxide composite film.
To cite this article before page numbers are assigned, use the DOI form of citation above.
The content of this RSS Feed (c) The Royal Society of Chemistry




outer

Language, grammar, and erudition: from antiquity to modern times: a collection of papers in honour of Alfons Wouters / edited by Pierre Swiggers

Hayden Library - P63.L37 2018




outer

[ASAP] Beta-lactam-Induced Outer Membrane Alteration Confers <italic toggle="yes">E. coli</italic> a Fortuitous Competitive Advantage through Cross-Resistance to Bacteriophages

Environmental Science & Technology Letters
DOI: 10.1021/acs.estlett.0c00318




outer

Enhancing catalytic alkane hydroxylation by tuning the outer coordination sphere in a heme-containing metal–organic framework

Chem. Sci., 2020, Accepted Manuscript
DOI: 10.1039/D0SC01796E, Edge Article
Open Access
David Zhi Hong Zee, T. David Harris
Catalytic heme active sites of enzymes are sequestered by the protein superstructure and are regulated by precisely defined outer coordination spheres. Here, we emulate both of these protective functions in...
The content of this RSS Feed (c) The Royal Society of Chemistry




outer

Report on the 2007 Western Australian Museum, Department of Maritime Archaeology, Batavia land sites National Heritage listing archaeological survey / edited by Corioli Souter with contributions by Ross Anderson and [four others]




outer

Direct transfer of soil in the wet season as a method to establish resprouter species in rehabilitated bauxite mines / M.A. Norman, J.M. Koch

Norman, M. A




outer

Chemistry in Pictures: Crystals from outer space




outer

Superconductors from outer space

Some meteorites contain superconducting alloys




outer

Limiting outer space: astroculture after apollo / Alexander C. T. Geppert, editor

Dewey Library - TL789.8.G477 2018




outer

The Outer label of Flor de Alvarez a cigar label for the Marcelino Perez Cigar Company.




outer

The Jerry Lind outer cigar label was a transfer to the Florida Cigar Company.




outer

The Outer cigar label of Casa Cuba a Z. Garcia and Company label.




outer

The Outer cigar label Sinceridad for Gonzales, Fisher and Company.




outer

The Outer label of San Rita for Cuesta and Rey Cigar Company.




outer

The Outer label for the "Leila" cigar brand of Miguel Suarez Cigar Company.




outer

The Outer cigar label for La Flor de Ramon Alvarez y Ca cigars.




outer

An Outer cigar label for A. C. Padella Cigar Company named Danny.




outer

An Outer cigar label for the Lopez, Alvarez and Company.




outer

The Flor de Menendez outer label for the Manuel menendez Cigar Company.




outer

The Outer label of Julia Marlowe for Corral ,Wodisky and Company.




outer

El Carpio; a very ornate outer label.




outer

F. Garcia & Bros. : an outer box cigar label.




outer

F. Garcia and Bros: a very ornate outer cigar label




outer

An Outer label for F. Garcia and Brothers Cigar Company.




outer

An outer label for A. Santaella&apos;s Optimo cigar brand.




outer

The Outer label for the Cervantes brand of the Marcelino Perez Cigar Company.




outer

An Outer label for the Columbia Club brand of cigars for the Arguella, Lopez, and Brothers Cigar Company.




outer

An Outer label for the Archimedes brand From the Arguelles, Lopez, and Brothers Cigar Company.




outer

Same scene as #630 but with stouter man with mustache wearing glasses, hat, three piece suit and watch chain, standing on corner of Central Avenue and 2nd Street North. Cars, sign for Detroit Hotel Grill. This may be Elon Robison, who had a competing came




outer

Red mangroves on outer margin, Eleanour [Eleanor] Island




outer

Island on Outer Part of Suwanee River Delta




outer

Simple models for predicting dune erosion hazards along the Outer Banks of North Carolina




outer

The role of subaerial geomorphology in coastal morphodynamics of barrier islands, Outer Banks, NC




outer

Crustacés des eaux souterraines karstiques des montagnes de Vitocha et de Golo bardo (Bulgarie Occidentale): composition taxonomique, caractéristique générale et répartition spatiale dans le karst




outer

Large-scale karst features and open taliks at Vardeborgsletta, outer Isfjorden, Svalbard




outer

[ASAP] A Positive Charge in the Outer Coordination Sphere of an Artificial Enzyme Increases CO<sub>2</sub> Hydrogenation

Organometallics
DOI: 10.1021/acs.organomet.9b00843