Without CRA.
I was quite annoyed at how difficult it was to integrate React with Express. The process goes something like:
- Setup your Express app in one directory
- Use CRA to generate the frontend in another directory
- Develop backend
- Use a proxy for the frontend and mess with CORS
- Done. Production? Squash together... mess
Sounds simple? Not for me. This was even... hacky. Creating React apps with Express shouldn't be hard. It's been a long time since React and Express came out, and nothing could be better?
Oh well. I'll just use NextJS or something. Until things get messy. Websockets? Uncheck. Elegant routing? Double uncheck. I just find it hard to work with. The server-side is hard(er than Express; perhaps I'm just lazy though) to configure too.
So, we're now officially stuck. So what's the option? Back to Express...
I set off to make a template. A template to use Express and React—with no mess.
Let's dive in.
To start off, let's fork the template.
git clone https://github.com/codingjlu/express-react-template.git
Then move to the directory:
cd express-react-template
Now we'll have install all the dependencies. Run the install
command:
npm install
Then we have to install all the dependencies for the frontend.
cd client
npm install
Now that everything's installed we can start the development server:
npm run dev
Now once stuff stops printing in the console you can open up http://localhost:3000. Boom! Our React app is now up and running, powered by Express. You should see something like this:
We're using React Router, so if you click on the link we should see an instant change to the new location. Cool!
We have also defined a API endpoint using POST at /hello
. You should see some JSON like this:
Yay! Our Express React app is up and running, with no junk. We can customize our server and client.
Let's go to index.js
in the root of our file and replace
app.post("/hello", (req, res) => {
res.json({
hello: "world"
});
});
With
app.get("/hello/:name", (req, res) => {
const { name } = req.params;
res.json({
message: `Hello, ${name}!`
});
});
Now visit http://localhost:3000/hello/Bob and see what happens. Experiment and change Bob to something else. When you're comfortable with Express (which you probably already are) you can go ahead and change the server however you like. You can create new files, edit the file, perform backend operations, and more!
We can also customize the client-side (React). Let's make a button on the home page that let's you say hello.
Go to your code and and open up /client/src/routes/home.js
and let's add a button to our <Home />
component. Inside of the parentheses after return change the value to:
<>
<Hello><Link to="/hello">Hello</Link>, world!</Hello>
<button onClick={() => alert("Hello!!")}>Say hello</button>
</>
Now save the file and reload localhost on your browser. Click on the button and you should get a hello message!
Sounds great? Great!
For the template, the frontend stack uses Styled Components. You can change it to something else, but you might have to edit the webpack config (like if you wanted to do modules or something). Importing images (including SVG) also works.
That's it. If you used the template please tell me what cool things you made with it!
The template repository is https://github.com/codingjlu/express-react-template.
Top comments (1)
Thanks buddy, this was really helpful. Though I was moving from an already functional CRA that I had to eject but going through your article set me on the right direction plus some other random researches.
A bit of an advice for those who might stumble upon this and are in the same situation (coming from an existing application) as I was is that requiring the webpack.config in the dev.js or wherever you will like to put that block of code loads it as a function so you will have to execute the function with "development" as an argument for it to return the config object.
Then you can now pass the object (in this case 'webpackConfig') to the webpack and the webpackDevMiddleware functions.
I hope this comes out well and it helps.