{"id":13596912,"url":"https://github.com/manuelbieh/react-ssr-setup","last_synced_at":"2025-05-15T01:07:12.718Z","repository":{"id":38272129,"uuid":"76994636","full_name":"manuelbieh/react-ssr-setup","owner":"manuelbieh","description":"React Starter Project with Webpack 4, Babel 7, TypeScript, CSS Modules, Server Side Rendering, i18n and some more niceties","archived":false,"fork":false,"pushed_at":"2025-03-27T07:56:36.000Z","size":3083,"stargazers_count":782,"open_issues_count":68,"forks_count":200,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-04-13T22:39:39.044Z","etag":null,"topics":["babel","css-modules","eslint","express","hmr","i18n","postcss","prettier","react","react-router","redux","reselect","typescript","webpack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/manuelbieh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-20T21:56:41.000Z","updated_at":"2025-03-06T18:15:47.000Z","dependencies_parsed_at":"2023-11-25T15:21:24.737Z","dependency_job_id":"da028e45-b901-403d-9730-9a94b0184c88","html_url":"https://github.com/manuelbieh/react-ssr-setup","commit_stats":{"total_commits":212,"total_committers":12,"mean_commits":"17.666666666666668","dds":"0.25943396226415094","last_synced_commit":"3f4bf31cdbc353bd9944b7201b2da11f83b4e809"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelbieh%2Freact-ssr-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelbieh%2Freact-ssr-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelbieh%2Freact-ssr-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelbieh%2Freact-ssr-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/manuelbieh","download_url":"https://codeload.github.com/manuelbieh/react-ssr-setup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254041,"owners_count":22039792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babel","css-modules","eslint","express","hmr","i18n","postcss","prettier","react","react-router","redux","reselect","typescript","webpack"],"created_at":"2024-08-01T16:02:56.851Z","updated_at":"2025-05-15T01:07:12.682Z","avatar_url":"https://github.com/manuelbieh.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# ⚛ React + Express – SSR Setup with TypeScript\n\n[![Maintainability](https://api.codeclimate.com/v1/badges/085d871cd62fe4435865/maintainability)](https://codeclimate.com/github/manuelbieh/react-ssr-setup/maintainability)\n[![dependencies Status](https://david-dm.org/manuelbieh/react-ssr-setup/status.svg)](https://david-dm.org/manuelbieh/react-ssr-setup)\n[![Known Vulnerabilities](https://snyk.io/test/github/manuelbieh/react-ssr-setup/badge.svg)](https://snyk.io/test/github/manuelbieh/react-ssr-setup)\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![CircleCI](https://circleci.com/gh/manuelbieh/react-ssr-setup/tree/master.svg?style=svg)](https://circleci.com/gh/manuelbieh/react-ssr-setup/tree/master)\n\n**Advertising**: I wrote a book about React. There's a German and an English version. Buy one if you like this project and you want to support my work!\n\n| **English**                                                                           | **German**                                                                        |\n| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| [![English](./src/shared/assets/book-cover-en-small.png)](https://book.react-js.dev/) | [![German](./src/shared/assets/book-cover-small.png)](https://buch.react-js.dev/) |\n\n**New!** You can now use this project as template! [Click here to create a new repo on GitHub with this project as template.](https://github.com/manuelbieh/react-ssr-setup/generate)\n\n## TOC\n\n- [Motivation](#motivation)\n- [Goals](#goals)\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Tricks](#tricks)\n  - [Client side version (opt-in)](#client-side-version-opt-in)\n  - [Component scaffolding using plop](#client-side-version-opt-in)\n  - [📕 Storybook support](#-storybook-support)\n  - [Keep your project up to date](#keep-your-project-up-to-date)\n  - [Avoid source map generation for faster builds](#avoid-source-map-generation-for-faster-builds)\n  - [Change the port of the dev environment](#change-the-port-of-the-dev-environment)\n  - [Import SVGs as ReactComponent](#import-svgs-as-reactcomponent)\n  - [Use plain JavaScript instead of TypeScript](#use-plain-javascript-instead-of-typescript)\n- [Caveats](#caveats)\n- [Todo](#todo)\n- [Changelog](#changelog)\n\n## Motivation\n\nThis is just another React Starter Project as there are literally [hundreds of others out there](https://www.javascriptstuff.com/react-starter-projects/). The reason I created this one was to have one central repo I can base my own future projects on, which contains most of the packages I usually use, is easily extendable, easy to understand, supports server side rendering, and uses all the configs and settings I made good experiences with in the past.\n\nAnother reason I created my own starter project was because I was setting up two new long term projects and I wanted to be able to use **Webpack 4** and **Babel 7** long before it was stable. None of the bigger and well known starter projects were supporting both by the time I created this starter project. So the idea was born to create my very own. And here we are 🎉\n\nA few things might be familiar when you've worked with other starter projects before. I borrowed many ideas (and will continue to do so) from [Create React App](https://github.com/facebook/create-react-app), [React Starter Kit](https://github.com/kriasoft/react-starter-kit) and other great starter projects because my intention was to create an **up-to-date starter project** for myself **based on best practices** and not to completely reinvent the wheel in every possible way just for the sake of it.\n\n## Goals\n\nMy goal is to provide a **well-tested, regularly maintained, easily configurable and adjustable React Starter Project** with support for server side rendering that gives you a good basis to start your own project on. As minimal as possible with as much functionality as necessary.\n\nI use this Starter Project in several real-word projects so it is battle-tested and everytime I fix a bug or add a feature I find useful I will also update this Starter Project. I will also keep the dependencies up-to-date on a regular basis and will also stay updated with all the latest and greatest best practices in the React world and integrate them if possible and useful!\n\nIf you have any questions you can always [open an issue on Github](https://github.com/manuelbieh/react-ssr-setup/issues) or reach out to me on [Twitter](https://www.twitter.com/manuelbieh)!\n\n## Features\n\nThis project has out-of-the-box support for the following things:\n\n- General Setup\n\n  - 🔥 Babel 7\n  - 📦 Webpack 4\n  - 🔥 ESLint 7 (with a set of custom rules which may be mostly identical to AirBnB with some personal flavor added)\n  - 🔥 TypeScript (via Babel)\n  - 🔥 Prettier\n  - 🔥 Jest\n  - 🐐 React Testing Library\n  - ✅ React i18next for multi language support\n  - ✅ Server Side Rendering with Express\n  - 🏎 React Fast Refresh\n  - ✅ CSS Modules\n  - ✅ PostCSS\n  - ✅ Precommit hooks via lint-staged + Husky\n  - ✅ Optional static build without the need for Node.js on the server\n  - 📕 Support for [Storybook](https://storybook.js.org/) (\u003e= 5.0.0)\n\n- Libs and Dependencies\n\n  - ✅ React i18next for multi language support\n  - ⚛ React 16.x (latest), with Hooks!\n  - ✅ Redux + Thunk middleware\n  - ✅ Immer\n  - ✅ Reselect\n  - ✅ React Router 5\n  - ✅ React Helmet\n\nSince it's only using standard APIs so far it is ready to be used with the new React Suspense feature coming in React 17!\n\n## Installation\n\nAs a general recommendation you should create a **fork** of this project first or use GitHub's [use this template](https://github.com/manuelbieh/react-ssr-setup/generate) function so you can adjust it to your own needs, add all the dependencies you need and commit everything back into your own repository.\n\nOnce you've forked the repository here on Github, clone it, `cd` into the directory and run `yarn` (or `npm install`) on your command line to install all the dependencies. You're ready to go now!\n\n## Usage\n\nThere are npm scripts for all the relevant things. The server will always be started on port 8500 unless otherwise specified in `process.env.PORT`. You can use a `.env` file to specify env vars. If you want to use them in your client side code, don't forget to add them in [config/env.js](config/env.js#L37).\n\n### Noteworthy scripts:\n\n#### `yarn start`\n\nStarts the app in development mode: creates a new client and server dev build using webpack, starts the Express server build (for both file serving and server side pre-rendering) and keeps webpack open in watchmode. Updates the app (if possible) on change using HMR.\n\n#### `yarn build`\n\nCreates a new build, optimized for production. Does **not** start a dev server or anything else.\n\n#### `yarn test`\n\nRun all tests using jest.\n\n#### `yarn test:update`\n\nUpdate all Jest snapshots (if there are any)\n\n#### `yarn lint:js`\n\nRun ESLint for all JavaScript and TypeScript files\n\n#### `yarn lint:css`\n\nRun Stylelint for all CSS files\n\n#### `yarn lint`\n\nRun lint:js and lint:css in parallel\n\n#### `yarn analyze`\n\nStarts `webpack-bundle-analyzer` to give you the opportunity to analyze your bundle(s)\n\n#### `yarn depgraph`\n\nCreates an image of your dependency graph. Requires [GraphVIZ](https://www.graphviz.org/) to be in your system's `PATH`\n\n#### `yarn plop`\n\nRun plop to create new React components or Redux reducers via CLI\n\n## Environment Variables\n\nThere are a few environment variables you can set to adjust the setup to your needs\n\n| Variable         | Default            | Description                                                                                                                                                                                                                                                                                      |\n| ---------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `PORT`           | `8500`             | Port number your application will be served on.                                                                                                                                                                                                                                                  |\n| `HOST`           | `http://localhost` | Host (including protocol!) your application will be served on. This is usually neglectable as most of the time your application will be served via remote proxy (e.g. Nginx) on localhost. **Note:** this is only for convenience. The server itself will not be bound exclusively to that host. |\n| `DEVSERVER_HOST` | `http://localhost` | Optional. Different host for the Webpack Dev Server to be served on.                                                                                                                                                                                                                             |\n\n## Tricks\n\n### Client side version (opt-in)\n\nBeginning with v1.3.0, a **static** `index.html` is also generated and written to your `clientBuild` directory. You are now able to deploy the `build/client` directory to a static webhost (such as Netlify or AWS S3) and serve your application from there!\n\nFor the generation of the `index.html` the server side build gets started right after building, a headless Chrome then visits the site and writes the content of the server side response to your client directory. So you still need the `src/server` directory and the server side build but you're now flexible and can decide on your own whether you want to have the full server side experience or only deploy your completely static app somewhere.\n\n### Component scaffolding using plop\n\nAlong with this starter kit comes `plop` - a great command line tool to keep the structure of your Redux components and Redux reducers consistent. Run `yarn plop` (or `npm run plop`) to have components and Redux reducers created for you automatically! Just enter a name, answer a few questions and you're ready to go! You can of course adjust everything to your needs. All Plop templates can be found in the `config/plop` directory.\n\n### 📕 Storybook support\n\nI've successfully tested Storybook and it integrates seamlessly and without any issues into this setup. If you want to add Storybook to your project, install Storybook `^4.0.0` and run `getstorybook` to have the basic setup created for you. You must then replace all the content in `.storybook/webpack.config.js` with the following line:\n\n```js\nmodule.exports = require('../config/webpack.config.js/storybook');\n```\n\nAfterwards you should be able to run `yarn storybook` to start the Storybook Dev Server.\n\n### Keep your project up to date\n\nIf you want _your_ project to stay up to date with recent changes to _this_ project, you can add **React SSR Starter** as remote to your local git repo. Use the following line:\n\n```\ngit remote add upstream git@github.com:manuelbieh/react-ssr-setup.git\n```\n\nMore on that can be found on Github: [Syncing a fork](https://help.github.com/articles/syncing-a-fork/).\n\n### Avoid source map generation for faster builds\n\nIn some cases you might not want to generate source maps for the generated files. In this case you can set the `OMIT_SOURCEMAP` environment variable to `true`. No source map files will be generated then. This works no matter if you're in devmode or building for production.\n\n### Change the port of the dev environment\n\nBy default if you run `yarn start` the development server will use port 8500. You can change this by specifying a `PORT` environment variable.\n\n### Import SVGs as ReactComponent\n\nYou can import SVG files as React components exactly the way you can do it in Create React App 2.0:\n\n```\nimport { ReactComponent as Logo } from './Logo.svg';\n```\n\nThen you can use it in JSX like `\u003cdiv\u003e\u003cLogo /\u003e\u003c/div\u003e`.\n\n[Here is a video](https://egghead.io/lessons/react-add-svgs-as-react-components-with-create-react-app-2-0) that explains that a bit more.\n\n\u003c!--\n### Managing i18n translation files\n\n_(WIP: this is not quite working, yet!)_\n\nThis project comes with i18n support out of the box. It's using i18next and react-i18next to provide comprehensive tooling and mechanisms to translate your app. Additionally I've started to add support for translation management for external online translation services (currently lokalise.co is the only available provider). You can use the Lokalise web interface to handle all your translations, export them to use them in your app and also import them from your app via a simple `yarn i18n:push`.\n\nYou have to define two new env variables to be able to import/export translations to/from Lokalise: `LOKALISE_TOKEN` and `LOKALISE_PROJECT_ID`. Afterwards you can create new translations via their web interface or collect all static translation strings from your app using `yarn i18n:scan` and then push them to Lokalise using `yarn i18n:push`.\n--\u003e\n\n\u003c!--\nThis following section is no longer fully true since I decided to go all-in on TypeScript. I leave it in here for now for historical reasons.\n\n### Use plain JavaScript instead of TypeScript\n\nYou can just do it‬™. Really. Name your files `.js` instead of `.ts`/`.tsx` and you should not be bothered by TypeScript anymore. If you want to _fully_ remove TypeScript:\n\n- remove the `@babel/typescript` preset from `babel.config.js`\n- uninstall TypeScript: `yarn remove typescript @babel/preset-typescript`\n- uninstall all dependencies beginning with `@types/`\n- delete `tsconfig.json` and `src/global.d.ts`\n- remove `wiremore/typescript` from the `extends` section in `.eslintrc.js`\n- remove all types from all files if there still are any\n- remove `tsConfig` option from `.dependency-cruiser.js`\n--\u003e\n\n## Caveats\n\n- ~~[1] MiniCSSExtractPlugin doesn't play nicely with consecutive builds in Webpack's watchmode yet ([Github issue here](https://github.com/webpack-contrib/mini-css-extract-plugin/issues/23)). So I'm using ExtractTextWebpackPlugin until this is fixed~~ Fixed! [490e6e9](https://github.com/manuelbieh/react-ssr-setup/commit/490e6e95fc811b0ce42d1bbc1252d3f26c4bd1ab)\n- ~~[2] Hot Module Replacement is still a bit buggy. Not all components have been configured and updated to play nicely with HMR (namely Redux and React-Router)~~ Seems to be fixed (still validating) [66875a1](https://github.com/manuelbieh/react-ssr-setup/commit/66875a108e6a23d704a117b0ef686db644832589)\n- Running the build in production: I **strongly** recommend to serve your static assets using **Nginx** or **Apache** instead of the `Express.static` middleware. That's how I usually do it and that's why you won't see any assets when starting the production server build with Node. If you still want to use `Express.static` in production despite the warning, have a look at the first few lines of `./src/server/index.js`. There's a short comment with a description what you need to do.\n\n## Todo\n\n- [x] Replace `ExtractTextWebpackPlugin` with `MiniCSSExtractPlugin` once it's working properly\n- [x] Get HMR working (done, mostly)\n- [x] Add HMR for Redux\n- [x] Add HMR for CSS Modules (depends a bit on MiniCSSExtractPlugin) (using ExtractTextWebpackPlugin)\n- [ ] Add React Error Overlay from Create-React-App\n- [x] ~~Add `react-loadable` or `react-universal-component` (or both, still investigating what makes most sense). **Update:** `react-loadable` is out due to [questionable license change](https://github.com/jamiebuilds/react-loadable/commit/c3272b3132e4fe25937c3610b7cd0dd2da48c5e9)~~ Just use React.lazy which was introduced in React 16.6.\n- [x] Improve server side template\n- [x] Add (and use) `react-helmet`\n- [ ] ~~Add/improve server side chunk loading~~ - Wait for the new React Fizz Renderer to land\n- [x] Add test setup using Jest\n- [ ] Add `optimize-css-assets-webpack-plugin` and `postcss-safe-parser` similar to how CRA 2 is doing it\n- [x] Modify ~~`svg-loader`~~ `babel-loader` so SVGs can be imported as React component (see CRA 2)\n- [ ] Add proper [offline support using Workbox](https://webpack.js.org/guides/progressive-web-application/)\n- [ ] Document i18n functionality (scan, pull, push, ...)\n- [ ] Move i18n scripts to an external package to clean up the dependency tree\n- [ ] Fine tuning different minor things (ongoing task)\n\n## Changelog\n\nMoved to its own file: [CHANGELOG.md](CHANGELOG.md)\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanuelbieh%2Freact-ssr-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanuelbieh%2Freact-ssr-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanuelbieh%2Freact-ssr-setup/lists"}