git clone https://github.com/iansinnott/react-static-boilerplate my-static-site
cd my-static-site && rm -rf .git
npm startto run a dev server
npm run buildto minify, package and generate static HTML files from your routes
Now you're all set to deploy to your favorite hosting solution 🍻
NOTE: It's important to run
npm run build and not
npm build. The latter will silently exit because it is a native NPM command.
Iportant Note: This boilerplate does not yet support generating static sites for dynamic routes such as
post/:id. That's the next major feature addition (see the Roadmap below) but it hasn't been implemented yet.
For more info see this issue on the react-static-webpack-plugin repo.
There is certainly no need to use Stylus for styling your static pages. Use whatever you like best. But Stylus does support standard CSS syntax so if you don't want to set up anything new just start writing CSS in any of the
*.styl files and watch it compile as expected 😆
This boilerplate uses Stylus for page styling by default. It's pretty simple to swap out stylus for Sass, Less or even plain CSS. Just update the Webpack config files (both
webpack.config.prod.js) to use your loader of choice. If you're not sure how to do this check out the Webpack loaders documentation.
CSS Modules are provided as part of the css-loader itself. For more info check out the CSS Loader docs. If you haven't heard of CSS Modules check out GitHub repo. Basically it lets you write styles local to any component or file. In my experience it makes styling much more pleasant and much less error prone.
Of course if you don't want to use this feature you don't have to.
To disable CSS modules you just need to replace to Webpack config lines for dev and prod:
// webpack.config.dev.js// Replace this...'css?modules&importLoaders=2&localIdentName=[name]__[local]__[hash:base64:6]'// ...with this.'css'
// webpack.config.prod.js// Replace this...loader: ExtractTextPlugin// ...with this.loader: ExtractTextPlugin
This project will generate all the static files you need to server a full, production-ready website. However your server will likely need some configuration so that it maps the same URLs React Router uses to actual static files. For example, the "about" page might have the following URL according to React Router:
However, a static server without any configuration would see the URL
/about and return a 404 because it expects a URL of
/about.html to actually server the file. There are many ways to handle this on different systems. Here is how you might handle it with Nginx.
This project contains a script to help generate a usable Nginx config. To run it:
npm run -s conf
This will output the config to stdout. Redirect it as you see fit to save it to disk:
npm run -s conf > my-site.conf
Once you've saved the file you can sym link it into place and reload Nginx. This is just an example, your path to Nginx will vary based on system:
ln -s $PWD/my-site.conf /path/to/nginx/conf-files/static-fun.confnginx -s reload
First, make sure you have Docker installed and running on your system. Then proceed.
This repository includes a Docker Compose config file for quickly setting up an Nginx server to test your static site. To run it, simply run:
npm run -s conf > nginx.confdocker-compose up
docker ps to get the IP address and port where the container is running. If you're using Docker Machine this will likely be something like
If you don't have Nginx yet install it with
brew install nginx
Now generate an Nginx config file using the script in this project:
npm run -s conf > nginx.conf
Then link that file we just created in to the global Nginx config file and reload Nginx:
mkdir -p /usr/local/etc/nginx/serversln -s $PWD/nginx.conf /usr/local/etc/nginx/servers/static-fun.confnginx -s reload
For further reading on the primary tech used in this boilerplate see the links below:
BABEL_ENV is not set to
development when building. If it is babel will likely throw a hot module replacement error since HMR transformations are getting run on everything that goes through babel.
font-awesome-webpack module does not seem to work with the approach of generating files as UMD modules then requiring them from the public dir. It throws an error about window not being defined.