Skip to content

Instantly share code, notes, and snippets.

@ryanoglesby08
Last active April 4, 2024 13:25
Show Gist options
  • Star 70 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save ryanoglesby08/1e1f49d87ae8ab2cabf45623fc36a7fe to your computer and use it in GitHub Desktop.
Save ryanoglesby08/1e1f49d87ae8ab2cabf45623fc36a7fe to your computer and use it in GitHub Desktop.
A node.js SPA server that serves static files and an index.html file for all other routes.
/*
Incredibly simple Node.js and Express application server for serving static assets.
DON'T USE THIS IN PRODUCTION!
It is meant for learning purposes only. This server is not optimized for performance,
and is missing key features such as error pages, compression, and caching.
For production, I recommend using an application framework that supports server-side rendering,
such as Next.js. https://nextjs.org
Or, if you do indeed want a Single Page App, the Create React App deployment docs contain a lot
of hosting options. https://create-react-app.dev/docs/deployment/
*/
const express = require('express');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();
// serve static assets normally
app.use(express.static(__dirname + '/dist'));
// handle every other route with index.html, which will contain
// a script tag to your application's JavaScript file(s).
app.get('*', function (request, response) {
response.sendFile(path.resolve(__dirname, 'index.html'));
});
app.listen(port);
console.log("server started on port " + port);
@cloudcompute
Copy link

cloudcompute commented Jan 5, 2022

Thanks for the confirmation. Yes, I can understand your example is just for illustration.

Somewhere you said, in production you should use a framework like Next.js. Are you not in favour of SPAs? I believe that the SPA technique comes really handy for building apps that are going to be used by a handful of users like Enterpise CRM, ERP, etc. What SPAs lack are SSR and SEO but there are workarounds for these two as of now. I believe that the genius would be able to overcome these two limitations completely in future.

One more question pl.

A user browses to the my-site.com for the first time:

  1. The static assets (excluding index.html) are served first to the browser because the Express server invokes the app.use(express.static..) global middleware first before serving index.html.

  2. Then app.get ("*", ...) route is hit next which sends the index.html to the browser.

  3. The browser reads the index.html and when it comes across the script tags that contain pointers to to the JS and CSS files, it comes back to the server. The server serves it using the global middleware mentioned in Step 1.

Is this how the process works? If yes, it means one unnecessary call to the server.

I think the browser must be smart enough to pick the JS and CSS assets from the user's machine itself which were served in step 1 and the step 3 won't be executed.

Your viewpoints pl.

With Regards

@ryanoglesby08
Copy link
Author

Somewhere you said, in production you should use a framework like Next.js. Are you not in favour of SPAs? I believe that the SPA technique comes really handy for building apps that are going to be used by a handful of users like Enterpise CRM, ERP, etc. What SPAs lack are SSR and SEO but there are workarounds for these two as of now. I believe that the genius would be able to overcome these two limitations completely in future.

I think fully client-side rendered apps have their place, but SSR frameworks are generally a better choice because they allow for more flexibility. For example, with Next.js you can do client-side rendering, server-side rendering, or static generation on a page by page basis. With CRA, you are limited to only client-side rendering. One of the biggest downsides to a fully client-side rendered app is performance, the user has to wait for ALL the JS to be downloaded, parsed, and executed before they can even see anything on the page.

Is this how the process works? If yes, it means one unnecessary call to the server.

Not quite. When a user browses to www.my-site.com for the first time their browser makes a request for the index.html page: GET /. The index.html is returned to the user's browser and the browser starts parsing the HTML. When it encounters <script> or <link> tags referring to JS or CSS assets, the browser will request those from the server: GET /bundle.js, GET /styles.css. That's it, no unnecessary requests. The Express routes are all middlewares, so they don't generate additional requests when they execute on a single incoming HTTP request.

I blogged about this awhile ago: http://ryanogles.by/conceptualizing-how-a-modern-single-page-app-is-served/

@cloudcompute
Copy link

I blogged about this awhile ago: http://ryanogles.by/conceptualizing-how-a-modern-single-page-app-is-served/

The sequence diagram has helped me understand "clearly" how SPAs actually work and what exactly happens after the user requesting the browser to load a SPA.

You helped me quite a lot.

@cloudcompute
Copy link

cloudcompute commented Jan 9, 2022

Hi @ryanoglesby08

One more query, Hope you'd answer.

Rewrites allow you to map an incoming request path to a different destination path. Next has built-in functionality for this. But how to implement it in React SPA.. just give an idea.

Source /api/*
Destination /index.html
Effect All requests → /index.html

Thanks

@ryanoglesby08
Copy link
Author

Hi @Ramandhingra,

Any server-side routing is done using standard Express features. Please check the docs for Express.
All client-side routing/rewriting/redirecting is done using React Router (or whatever client-side router you are using). Please check the docs for React Router.

In the future, please direct your questions to any of the community resources available, such as StackOverflow. https://www.reactiflux.com/ is a great learning tool for React. You could join the discord and ask questions there. Good luck!

@cloudcompute
Copy link

cloudcompute commented Jan 14, 2022

Hi @ryanoglesby08

Thank you so much for your reply and letting me know about these resources. In the future, if I have any questions, I will surely write over the discussion forums.

@shubhamkr1
Copy link

shubhamkr1 commented Feb 10, 2022

Hi @ryanoglesby08
what is the folder structure that is assumed that your project has, in order to use this piece of code ?

@TulshiDas39
Copy link

Thanks.

@aderchox
Copy link

Thanks.
(Just realized you haven't posted on your blog in the past 4 years, considering the quality of your content, I recommend continuing it, I've subscribed through RSS.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment