Using Create React App with Phoenix

phoenix

#1

Hey all,

I recently wrote a couple articles on using Create React App alongside Phoenix to quickly get up and running building single page apps.

I’m using this approach of letting CRA manage and build a standalone front-end application within /priv and then tweaking my Phoenix endpoint to serve assets from within that React app’s /build folder.

I also wrote a follow-up article that talks about using Apollo client with Absinthe which digs into how to pass configuration-specific data (staging/production endpoints, etc…) into your React app.

So far I’m a huge fan of this approach. There’s no need to spend time tweaking configs to get your Phoenix application working with Webpack, or getting Brunch to work with React. Using CRA lets you start cooking with gas almost immediately, and Phoenix is flexible enough to gracefully work with it.

Is anyone else running this kind of setup?

Hopefully this helps a few folks looking to use React (and/or Apollo) with Phoenix.


#2

Thanks for this tip! I’m a huge fan of unbrella apps (not a typo!) and this method allows me to organize my phoenix web API server, because that’s what it is, and my react web API client as equal first class citizens. Having all the complex dependancy overlaps between the client and the server was a nightmare.


#3

The only problem with that approach is that by keeping everything in /priv it means that everything will be packaged into a release, including all of node_modules, which is huge for react apps.

That’s probably the primary reason for the default approach of keeping the front-end sources outside of priv.


#4

Our react setup is somewhat similar but we separate the server and client parts completely.

We have top level dirs for server (phoenix), web (spa) and native (react native app) in the repo and deploy the server and web parts to separate servers. Server has api (websocket) and some admin functionality, all with phoenix and brunch. Web part is an spa that uses create-react-app and communicates with the server using api only.

This kind of separation lets us port features from web to native without too much drama.


#5

Ah yeah, good point.

I guess a solution would be to pull the CRA app completely out of the Phoenix app like @yurko suggests. The only downside is that it couldn’t be directly served by Phoenix without another build step to copy the static bundle into /priv/static.

If only there were a way to include/exclude assets from release bundles. Than again, that would probably just be overcomplicating things.


#6

I guess you could try symlinking the /assets/build dir to /priv/static


#7

Is anyone else running this kind of setup?

Yep, I did some custom webpack configs to support TypeScript and all that fancy stuff in the past and also exported the app from app_web/priv/static -> webapp.
But I still coupled the app with phoenix views, so I used webpack only to bundle my js / css.

However, I finally came across you solution with cra and phoenix as the API. This is so much simpler and a pleasure to work with, this way you have the best from each and its much much simpler then trying to combine everything in one place, but still not really.

Having all the complex dependancy overlaps between the client and the server was a nightmare.

exactly!

You can write tests much more specific, you can launch the webapp standalone and work on some styling without to start the server.

Great Post, Thank you!


#8

Another option I found is to deploy your frontend /build to a CDN, and deploy your backend as you normally would with some configurations.


#9

Yes, but I mainly built it by hand. My react app went in app.jsx (renamed app.js) in the assets folder and brunch config with an npm whitelist to allow including react and react-dom in the generated app.js. I used apollo-boost to talk to an Absinthe GraphQL API. Everything is bundled in a single Phoenix app and nothing from /priv/static is committed to git. I used uberauth to login using github and bodyguard for authorization of the Absinthe endpoint.

I’ve been thinking about writing some posts on how to put all this together and making the repository public so others can see how all this fits together. (And to tell me all the places I got things wrong. :slight_smile: )

Ooo, I just realized how old this thread is. I’m way late here.


#10

One question: if I only use static assets generated by CRA, do I still need to run mix phx.digest before deployment? I’ve tried both (digest v.s. simply copy assets to /priv/static/), they both work, except the cache of the common chunk generated by webpack 4 just misses (though the file name of the chunk has not change).