A real-life, hot-reloading Express + React application quickstart
A hot-reloading Express/React quickstart. (c) 2017 Ionut-Cristian Florescu.

A real-life, hot-reloading Express + React application quickstart

Looks like React.js is the new jQuery. World + dog talks about it, and everyone is writing a "better react application starter". Here's my take on a combined live/hot-reloading development experience for Express.js and React.

The story below is the actual GitHub repo readme:

Motivation

TL;DR

While a simple, webpack-only based development scenario is perfectly suited for building SPAs, building multipage applications or websites require a different, more elaborated approach.

Background

While most React tutorials and quickstarts are focused exclusively on building SPAs (single-page applications), in real life your React application will often be running as part of a "classic" multipage application / website.

There's been lots of talk recently about server-side rendered React components or even about building your entire website as a client-side application. But rendering React components on the server is still unacceptably slow (as of December 2016), especially for websites that need to handle lots of traffic.

Also, we still need our server-generated content to be available and parsable by search engines. Admittedly, Google became smarter in regards to interpreting and client-side generated content, but it's not safe to completely rely on it, and other search engines are not so powerful yet.

That's why we still need to generate content on the server using tried & tested, fast, specialized template engines such as PugEJSVashDust, etc.

Also, the webpack-based hot-reloading solution provided by most tutorials and available quickstarts completely ignore the API your application is connecting to. But in real-life not all projects are developed by multiple teams; sometimes there's a single full-stack developer or team writing the entire codebase for an app or website, including the webpage templates, client-side JS code and server-side APIs.

Trying to use webpack hot-reloading for template-generated pages and API endpoints is possible to a certain degree, but it feels like trying to fit a square peg in a round hole: it requires you to structure your code in a certain way and make use of unsafe artifacts such as require cache busting, and it often results in FOUC when applying CSS changes.

Hence the need of a functional, truly general-purpose hot-reloading approach integrating the best of all worlds.

Features

  • Restart / full-page reload on server-side code change using nodemon and browsersync;
  • Full-page reload on template change using browsersync's watch mechanism;
  • Smart HMR on client-side code change using webpack@2.1.x;
  • Seamless CSS reloading with browsersync.


Starting

  • In development mode: npm run dev, then edit code and enjoy the auto-reload magic on localhost:3000;
  • In production mode: npm run build, then npm start.

Notes & Customisations

  • For demo purposes, server-side views are generated with Vash template engine, but you can use PugEJS, or anything else, as long as you make the necessary amendments in dev.js to instruct the browser to reload when one of your views changes.
  • A very simple/non-scalable JSON persistence mechanism based on lowdb and underscore-db is used as a server-side "database", for demo purposes. Make sure to npm uninstall -S lowdb underscore-db and replace with an appropriate data persistence layer.
  • A very simple gulp scenario is used for the sole purpose of transforming SCSS with node-sass and applying autoprefixer transformations with sourcemaps support in a single step. You can adapt it according to your own needs, or even fully replace it with a simple npm script if you're using Stylus with autoprefixer-stylus plugin or write your styles in plain CSS.
  • package.json contains simple npm scripts for running in development and production mode.
  • The quickstart provides a simple, yet efficient asset versioning mechanism based on package.json version: the static assets are served from a "virtual" root /static/x.x.x.x, where x.x.x.x is the package version. Just make sure to do an npm version bump as part of your deployment scenario (not provided here).
  • Efficient ES6 on the server with babel-preset-latest-minimal – configured in index.js.
  • In development mode, webpack-dev-middleware and webpack-hot-middleware are running as browsersync middlewares. This way we end up keeping the main Express application uncluttered by development-related code.
  • Webpack babel-loader is using stage-2 and react presets and react-hot-loader@3 – configured in webpack.config.js.
  • On the server, the global.Promise is replaced with bluebird for performance reasons – this is configured in index.js. Simply remove it if you don't like the idea.

Contributing

PRs are welcomed, but keep in mind this is just one of the many quickstart alternatives available in the wild, and it's not intended to cover all possible use-cases (or yours in particular).

Before raising issues or asking for help

I'm getting lots of questions from people just learning to do web development or simply looking to solve a very specific problem they're dealing with. While I will answer some of them for the benefit of the community, please understand that open-source is a shared effort and it's definitely not about piggybacking on other people's work. On places like GitHub, that means raising issues is encouraged, but coming up with useful PRs is a lot better. If I'm willing to share some of my code for free, I'm doing it for a number of reasons: my own intellectual challenges, pride, arrogance, stubbornness to believe I'm bringing a contribution to common progress and freedom, etc. Your particular well-being is probably not one of those reasons. I'm not in the business of providing free consultancy, so if you need my help to solve your specific problem, there's a fee for that. If you understand that and wish to employ my services, don't hesitate to drop me a line on my GitHub email account.

Credits

If you find this repo useful, don't hesitate to give it a star, spread the word or even endorse me on LinkedIn.

License

ISC-licensed by Ionut-Cristian Florescu. Feel free to use and abuse.


To view or add a comment, sign in

More articles by Ionut-Cristian Florescu

  • The future of Mantine DataTable

    I am kind of tired, but really satisfied. After a month of assiduous work, I just released the new version of Mantine…

  • Introducing PocketBaseUML

    You’re probably aware that PocketBase is currently the newest cool kid on the block when it comes to micro-backends…

    1 Comment
  • Today is NOT "business as usual"

    Nor will it be for a while. Today is not about Typescript, React, Next.

  • Please read before approaching me for work

    Useful information for recruiters and technical people looking to employ my services Hi there! First off, thank you for…

  • How we've built swapp.ro without external financing

    A story about the idea, development process, and tech-stack behind swapp.ro First of all, who are "we"? I'm a…

  • De ce am construit swapp.ro

    Când ai o problemă cu care s-au confruntat și alții, te interesezi cum au rezolvat-o și încerci să aplici aceeași…

  • The first Next.js global user conference

    October 27, 2020. It's finally happening.

  • Fă ceva

    Peste trei zile vom da un test care va dovedi dacă România a ieșit sau nu din Evul Mediu. Dacă nu-l vom trece, va fi…

  • Why I decided to become a Google Local Guide in my spare time

    A brief story about nature, people, and technology. I live in Romania, one of the most beautiful and picturesque…

  • How I’m planning to ditch Apple

    Note: I've initially published this article on HackerNoon, but since Medium and Medium publications are not yet as…

Insights from the community

Others also viewed

Explore topics