This site runs best with JavaScript enabled.

Hosting multiple React applications on the same document

December 02, 2018

Software Development

Hosting multiple React applications on the same document. Should be easy ...

One simple/naive approach to break up a big single page application is to split it into different single page applications which then are loaded on the same html document.

Unfortunately it is not possible to run several create-react-app applications on the same document., because the JavaScript bundles resulting from a cra project is not without side-effects: The bundled WebPack runtime writes an object on the global scope, which prevents to load several such bundles.

The following steps illustrate the problem and show how to fix it:

The Setup

1npx create-react-app react-app1 --use-npm
2npx create-react-app react-app2 --use-npm

Changing the second React app to run on another port in development mode:

1// package.json
2scripts: {
3 "start":"PORT=3001 react-scripts start"
4..}

Change the DOM node on which the second React app is bootstrapped:

1<!-- index.html -->
2<div id="app2-root"></div>
1// index.js
2ReactDOM.render(<App />, document.getElementById('app2-root'))

Run the first React application:

1cd react-app1
2npm start

first app

Run the second React application:

1cd react-app2
2npm start

second app

Load the second React app on the document of the first React app:

1// index.html
2<div id="app2-root"></div>
3
4<script src="http://localhost:3001/static/js/bundle.js"></script>
5<script src="http://localhost:3001/static/js/1.chunk.js"></script>
6<script src="http://localhost:3001/static/js/main.chunk.js"></script>

Unfortunately this does not have the expected result: We only see the second React app bootstrapped on the page. problem

The Problem

Somehow loading the scripts of the second React app has a side effect and prevents the bootstrapping of the first React app!

It turns out that the WebPack runtime is the problem here. The WebPack runtime adds an object to the global scope which is used to lazy-load chunks. The default name for this function is webpackJsonp. problem

The Solution

The name of this object can be configured in the WebPack config.

To get access to the WebPack config of a create-react-app project, you need to eject or use another customization mechanism like customize-cra.

Then you can change the Webpack config like this:

1// webpack.config.dev.json
2...
3output {
4 ...
5 jsonpFunction: 'jsonpApp2'
6}

Once you have changed the jsonpFunction of your second React app to a unique value, you must restart the development server (npm start)

Make sure that the document of the first app still references the correct scripts from the second app. Sometimes WebPack decides to rename the chunks…

And voilà: Both applications are bootstrapped on the same document: solution

Note: I only showed here how to adjust the WebPack configuration for the development build. The same change is needed for the production WebPack configuration. For production the project also has to solve the challenge of adding the correct script names to the integrating document, since WebPack (i.e in create-react-app) is configured to add a hash of the script content to the script name.

This post is originally published at jonasbandi.net.

Discuss on TwitterEdit post on GitHub

Share article
Jonas Bandi

Jonas Bandi is an enthusiastic software professional. He is passionate about technology and methodologies - always trying to learn, improve and share knowledge.