Awesome
<img width="110" src="https://user-images.githubusercontent.com/9271177/36511315-150065a8-175e-11e8-8f7a-27d3f72aa52b.png" />react-with-moxy
Opinionated boilerplate to create isomorphic react applications.
Motivation
Isomorphic JavaScript applications can be pretty challenging and hard to setup.
react-with-moxy
offers you the required tooling for your universal JavaScript application, as well as an opinionated frontend stack ready to kick-off your next project.
In the near future, we will be moving all the built-in tooling under scripts/
to a separate package. This will make it easier for projects based on this boilerplate to receive updates.
What's Included?
- React
- React Router
- we use v3 because v4 have some conceptual problems that we are trying to avoid
- Babel with babel-preset-moxy
- PostCSS with postcss-preset-moxy
- Webpack
- ESLint with eslint-config-moxy
- Stylelint with stylelint-config-moxy
- Express
- Node
- Jest and Enzyme
- Dockerfile
Table of Contents
Installation and setup
$ npm install
When the installation ends, copy .env.sample to .env
. All the supported environment variables are described in this same file, in case you need to tweak any of them. You may read more under the Environment variables section.
Commands
build
$ npm run build
Builds the project for production, producing the bundled assets at public/_build
.
Please run npm run build -- -h
for more options.
start
$ npm start
Starts a production server. You must run npm run build
before running this command.
Please run npm start -- -h
for more options.
start-dev
$ npm run start-dev
Starts a development server, opening a browser window automatically.
Please run npm run start-dev -- -h
for more options.
test
$ npm test
Runs the project tests using Jest. You may pass whatever options the Jest CLI.
lint
$ npm run lint
Runs ESlint and Stylelint on the project.
Please run npm run lint -- -h
for more options.
release
$ npm run release
We use conventional commit messages. When running this command it will run standard-version that does the following:
- Bump the version in package.json (based on your commit history)
- Uses conventional-changelog to update CHANGELOG.md
- Commits package.json and CHANGELOG.md
- Tags a new release
And after the tagging step, it will run git push --follow-tags origin master
, as defined here.
Environment variables
Your project can consume variables declared in your environment by accessing them via process.env
.
The following variables will be made available:
NODE_ENV
: One ofdevelopment
,production
ortest
.SITE_URL
: Where the web app is accessible (e.g.: http://some-project.com).PUBLIC_URL
: Where the web apppublic/
folder is being served from. This is usually the same as theSITE_URL
unless you use an external CDN to store and serve the files. You may use this to generate URLs to assets that do not go through Webpack.REACT_APP_*
: Custom variables that may be accessible in both the client and server bundles.
These will be embedded at build time, thus are read-only. This means you must rebuild your application every time you change them.
Server bundle
Besides the variables listed above, your server bundle will have access to the whole process.env
just like a regular Node.js application.
Client bundle
Only the variables listed above will be available.
If you need custom environment variables, you must prefix them with REACT_APP_
. This avoids accidentally exposing sensitive environment variables, such as a private key or a database credential.
.env file
Environment variables defined in the .env
file will be automatically loaded into process.env
.
This file is ignored in source control and it is intended to be created from .env.sample
, which is committed and anyone who clones the project can easily use it as a starting point. All the supported variables, including their description and default values, are defined there.
Here's an example of how to declare two new environment variables:
REACT_APP_FOO=foo
REACT_APP_BAR=bar
Note that relying in the .env
file is mostly useful for development. While you may still use it in production, it's advisable to pass environment variables explicitly when running commands. You may read the dotenv documentation for more information.
Passing environment variables when building a docker image
The project includes a Dockerfile
, allowing you to generate a docker image of your project. Here's an example of how to build the docker image and pass a few environment variables:
$ docker build .
--tag my-project:latest \
--build-arg $SITE_URL=http://my-site.com \
--build-arg $PUBLIC_URL=http://cdn.my-site.com
The environment variables are mapped to build args in the Dockerfile
. This means that you must update the Dockerfile
anytime you add new environment variables.
Customization
Customizing the server
You may tweak the express server on start
and start-dev
scripts:
└── scripts
├── start (production server)
└── start-dev (development server)
Customizing Webpack
You may tweak the Webpack configuration, such as adding new loaders or editing Babel plugins on config-client.js
and config-server.js
:
└── scripts
└── config
└── webpack
├── config-client.js
└── config-server.js
Customizing Jest
You may tweak the Jest configuration on jest
folder:
└── scripts
└── config
└── jest
├── index.js
├── setup.js
└── transformer.js
Customizing the manifest file
The build-manifest.json
file contains a summary of the build, including the produced assets, to be used when rendering the document on the server. You can customize its content on manifest.js
:
└── scripts
└── util
└── manifest.js
Examples
<details> <summary><b>Integration with:</b></summary> <ul> <li><a href="https://github.com/moxystudio/react-with-moxy/tree/examples/with-redux">Redux</a></li> </ul> </details>FAQ
How can I import an SVG as inline instead of adding it to the sprite?
Sometimes, you may want to import an SVG as inline either because you want to animate SVG paths or if you're just having issues with the sprite. If that is the case, you may change the file suffix from .svg
to .inline.svg
to import the SVG contents directly:
import someSvg from './some.inline.svg';
// `someSvg` is something like <svg ... />
Should Node.js be responsible for compressing responses?
Doing the compression in Node.js might hold the event loop which is not desirable for performance reasons.
That's why we employ gzip
and br
compression at build time for the built assets. We use compression-webpack-plugin to compress the assets when the project is built and the production server will attempt to serve the compressed files based on the requests' Accept-Encoding header.
For other responses, such as server-side rendered HTML, you may disable the on the fly compression and do it in a reverse-proxy server, like nginx. To do so, you may either pass the --no-compression
flag or set the COMPRESSION=0
environment variable:
npm start -- --no-compression
COMPRESSION=0 npm start