create-react-app provides a great starting point to start a new react app fully configured with webpack, live reloading, etc. But, sadly, it doesn’t provide a way to provide different index files with a different set of entry points. This might not be an issue for many since it is supposed to be a “single page application”, but recently we had a scenario where we needed to provide a different entry point (which differed significantly from the original app) to warrant a separate SPA but had enough shared code too to make setting up a separate project redundant.

Here are the steps we followed to provide an additional Html point with a separate webpack entry point for the app.

Eject

The first step, as usual with most CRA projects that require custom configuration is to eject. If you are here for a different issue that might not require ejecting, I recommend you read this excellent post on other alternatives to ejecting. In our case though, ejecting was the only sane way forward 🚀:

yarn eject

Ejecting will generate quite a few changes, so I recommend verifying that the project runs properly and commit the initial ejected app before proceeding.

Add another entry

  1. Edit paths.js and add the second entry point html file under the entry for appHtml.

Screenshot 2020 05 13 at 2 01 16 PM u0qyqa

  1. Update entry inside webpack.config.js to include one entry per entry point.

Screenshot 2020 05 13 at 2 04 04 PM suegxb

  1. Change the generated output JS file to the name of the entry (inside webpack.config.js)

Screenshot 2020 05 13 at 2 05 33 PM qvko9s

  1. Update the plugins to generate the second file with the injected js script (also inside webpack.config.js).

Screenshot 2020 05 13 at 2 08 10 PM idvzeg

  1. Update the ManifestPlugin configuration to include the new entry point (also inside webpack.config.js):

Screenshot 2020 05 13 at 2 09 01 PM favnuw

Rewrite paths

The above setup will set up the app to build a separate html file and inject the js into that file. But if you are planning to host both on the same server, you will also need to do some path rewriting so that the paths are sent to the correct html file. In our example, we want to send all paths from the root to index.html and all paths from /admin to admin.html. For this, first, change your development config (webpackDevServer.config.js):

Screenshot 2020 05 13 at 2 12 43 PM bqf3ea

You can now write your code at src/admin/index.js.

Do yarn start and visit localhost:3000/admin and see it in action.

Production

All this is well and good for development. What about deploying the app to production? You will also need to configure path rewriting on the production side to make sure that all paths starting at /admin are forwarded to the correct endpoint. If you are using Heroku, this is easily possible by adding a static.json file at the root. Here’s how mine looks like:

{
  "root": "build/",
  "routes": {
    "/admin**": "admin.html",
    "/**": "index.html"
  }
}

I know it’s an involved set-up, so feel free to let me know in the comments if it worked for you or if you have questions about it.

Here’s a gist of the changed files if you want to take a look at the whole setup.