README
Getting started
This project depends on components from @islandsbanki/ui-kit. You will need to clone that project and symlink it into this project to update the components. Here are instructions for doing so:
- Make sure you can access the ui-kit NPM package (NPM authentication)
- Run
yarn link
in these folders- ./node_modules/react
- ./node_modules/react-dom
- ./node_modules/react-router
- ./node_modules/react-router-dom
- In the root of ui-kit run
yarn link-to-isb-web
to connect the above modules to ui-kit. - In the root of ui-kit run
yarn link
- Build the ui-kit files and watch for changes by running
yarn dev
- In the root of this project run
yarn link @islandsbanki/ui-kit
You can edit ui-kit files and have the changes reflected in this project.
Updating ui-kit
When a pull request on ui-kit is accepted a new version should be published to NPM. Strict semVer should be followed to not break other projects that might depend on ui-kit.
NPM Authentication
NOTE: You will need to access the islandsbanki organisation on NPM to continue. Ask your project lead to add you to the organisation on NPM if you arent a member yet.
- Create an authentication token with
Read and publish
access. - Store the token in the
NPM_TOKEN
environment variable
# This is one way to do so
echo NPM_TOKEN="REPLACE_WITH_TOKEN" >> ~/.bash_profile
API Gateway Authentication
This application communicates with the รslandsbanki API Gateway (APIGW). This requires that you keep a copy of a certain certificate on your local machine.
- Obtain the certificate files and store them on your local machine (how?)
- Set the following environment variables:
API_GW_URL=https://api-test.islandsbanki.is
API_GW_CERT=/Users/haraldurka/certs/ApiGwIAZTest.pem # Replace with correct path and filename
API_GW_KEY=/Users/haraldurka/certs/ApiGwIAZTest.key # Replace with correct path and filename
Publishing new release
Follow these steps for a correct release
ui-kit:
- Checkout the master branch and pull latest changes
- If there are changes, update version:
npm version major/minor/patch
(if there are no changes, go directly to web below) - Publish new version of package to NPM:
npm publish
- Push changes (no commit needed)
web:
- Checkout the master branch and pull latest changes
- Make a branch from master with the semver naming convention:
release/major.minor.patch
(e.g.release/4.13.2) - Checkout the develop branch and pull latest changes
- Merge develop into the release branch
IF UI KIT WAS NOT UPDATED, SKIP STEP 5 AND 6 - Update UI-kit dependency:
yarn upgrade @islandsbanki/ui-kit
- Commit changes with the message
upgrade ui-kit
- Push changes
- Update web version (ui-kit step #2)
- Create pull request from release to master and have it reviewed.
๐ฅ Hotfix ๐ฅ
- Create a new branch from
master
(make sure to pull the latest changes first, and follow the naming conventionhotfix/[name_of_branch]
) - Commit, push your changes and create a PR
- Have your PR reviewed, accepted and merged into
master
ย ย ย ย ย ย ย โ ๏ธ Make sure you don't merge it intodevelop
โ ๏ธ - Follow steps
10
and11
in the list above. - Make sure you apply your changes to the
develop
branch as well ย ย ย โ ๏ธ otherwise your changes will be overwritten on next release โ ๏ธ
Development
> yarn
> yarn dev
...
Server listening on http://localhost:3000
Hot reloading with state and decorators
By default we're using react-jobs
for async stuff with server-side rendering. If we mix that with mobx
and decorators suddenly hot reloading with state will stop working. This is due to a bug in react-hot-loader
when higher-order components are composed. So instead of doing:
@inject('store')
@withJob({ work: ({ store }) => store.fetch() })
export default class Thing extends PureComponent {}
and not have stateful hot reloading, instead do
class Thing extends PureComponent {}
const thingWithJob = withJob({ work: ({ store }) => store.fetch() })(Thing);
export default inject('store')(thingWithJob);
If your stateful component withJob
doesn't contain another component in its sub-tree, you can get away with having a @withJob
decorator.
Dev tools
Dev tools (vertical and horizontal grids, mobx devtools) are hidden by default. To show them use ctrl + k
. Horizontal grid can be toggled via ctrl + l
.
Password protecting
By setting a PASSWORD_PROTECT
env variable, the server will ask the client to authenticate with basic auth. If the string contains a :
it will be split and set the username as the first part and the password as the second part, e.g. Aladdin:OpenSesame
. If no :
is in the string (or it starts with a :
), the username will be empty and the password the given string.
Single route development
If youโre working on a single route and donโt want to build the entire app you can do so by using the --route
argument, for example:
> yarn dev --route=about
about
being the folder name of the targeted route (inside shared/routes
). This can be very useful when the app gets bigger and rebuilds and HMR start to get slower.
Notes
- When adding configuration values and environment specific values, use the project config
- In development vendor DLLs are created (see
devVendorDLL
inconfig/values.js
) to speed up builds, for large projects you can add your own deps there
Production build
yarn build
yarn start
Code splitting
Code splitting is enabled by default. We use react-universal-component
and other related modules to do both JS and CSS chunks. To code split, all you have to do is wrap a component with react-universal-component
. An example of this can be found in shared/routes/grid/index.js
. To disable code splitting you just need to change the file to:
export default from './Grid';
Static site build
You can generate a static site by configuring the appropriate staticSiteGeneration values in config/values.js
. Then run yarn build:static
and the static pages will be generated in build/static.
To see the generated site, use yarn start:static
or copy the build/static
directory to the web server of your choice. Note that any error pages (e.g. 404.html) will not work without some server intelligence to send requests to the correct file.
More information on the internals of the static site build are in the directory's README.
Updating from upstream
Make sure you have the upstream
remote:
> git remote -v # should show..
...
upstream git@github.com:ueno-llc/starter-kit-universally.git (fetch)
...
# if not, run...
git remote add upstream https://github.com/ueno-llc/starter-kit-universally.git
git remote set-url --push upstream no_push # disable push to upstream
Then, update:
git fetch upstream
git merge upstream/master
# These are the usual conflicts
git rm -r -f shared/components/DemoApp
git checkout --ours package.json
Remote development
There are two ways of doing remote development:
- Providing IP address via
HOST
to run on local network - Using ngrok to expose localhost to the internet
> HOST=192.168.1.1 yarn dev # run from IP address
> HOST=$(ipconfig getifaddr en0) yarn dev # one-liner on mac
...
Server listening on http://192.168.1.1:3000
# run ngrok via script
> yarn dev-remote
...
Server listening on https://xyz.ngrok.io
Environment variables
.env_example
should contain all environment variables, required or not. All environment variables should default to development values.
Paths, must be absolute URLs because of axios
and the server not knowing its hostname
BASE_URL
- Used for compiling canonical urls and local api url (for internal requests)
publicPath
is set by the following environment variables:
- In development the
publicPath
is set by these variables: REMOTE_URL
- Only set when runningyarn dev-remote
HOST
andCLIENT_DEV_PORT
- Generates a url pointing to the dev server- Otherwise itโs set to
/client/
localApiUrl
is set by the following environment rules:
HEROKU_APP_NAME
- Injected into an Heroku app url string
BASE_URL
-/api
is appendedHOST
andPORT
- Used to compile a local api url
This allows for the build to work in dev, on Heroku PR apps and Heroku prod. See ./config/values.js
for details.
Stricter development
For those so inclined, pre-commit linting hooks can be added by changing lint-stage
in package.json
to:
"lint-staged": {
"*.{js,jsx}": "./node_modules/.bin/eslint",
"*.{css,scss}": "./node_modules/.bin/stylelint"
}
Testing can be enabled by adding to scripts
:
"test": "jest"
Measuring performance
At some point during your projects lifetime, it will suddenly become slow. It might be some silly dependency, missed configuration or the alignment of the stars. After suffering through long build times one time to many, you'll start tweaking and tearing stuff apart. While doing that it's nice to know if you're having any effect, so there are some scripts included to help with that, located in ./internal/performance
.
Before starting, set PERFORMANCE=true
in the env so the build spits out timings.
Measuring initial build times, runs the dev build, kills it, runs it again N times. When finished it writes the average of all the runs to stdout.
> chmod +x ./internal/performance/build.sh # allow execution
> ./internal/performance/build.sh
Running "yarn dev" 5 times
2627.793
2697.435
4140.478
2911.944
2846.027
2175.239
Measuring hot reload rebuilds, runs the dev task and waits for changes that trigger rebuilds. When the script is interrupted (e.g. by ctrl+c) it writes the average of all runs to stdout.
> chmod +x ./internal/performance/hot.sh # allow execution
> ./internal/performance/hot.sh
Running "yarn dev" watching for hot reloads
Build complete
794.079
518.700
500.460
492.716
^C
576.488
React, Universally
A starter kit for universal react applications.
About
This starter kit contains all the build tooling and configuration you need to kick off your next universal React project, whilst containing a minimal "project" set up allowing you to make your own architecture decisions (Redux/MobX etc).
NOTICE: Please read this important issue about the behaviour of this project when using
react-async-component
, which is by default bundled with it.
Features
- ๐
react
as the view. - ๐
react-router
v4 as the router. - ๐
express
server. - ๐ญ
jest
as the test framework. - ๐ Combines
prettier
and Airbnb's ESlint configuration - performing code formatting on commit. Stop worrying about code style consistency. - ๐ Very basic CSS support - it's up to you to extend it with CSS Modules etc.
- โ๏ธ Code splitting - easily define code split points in your source using
react-async-component
. - ๐ Server Side Rendering.
- ๐ Progressive Web Application ready, with offline support, via a Service Worker.
- ๐ Long term browser caching of assets with automated cache invalidation.
- ๐ฆ All source is bundled using Webpack v3.
- ๐ Full ES2017+ support - use the exact same JS syntax across the entire project. No more folder context switching! We also only use syntax that is stage-3 or later in the TC39 process.
- ๐ง Centralised application configuration with helpers to avoid boilerplate in your code. Also has support for environment specific configuration files.
- ๐ฅ Extreme live development - hot reloading of ALL changes to client/server source, with auto development server restarts when your application configuration changes. All this with a high level of error tolerance and verbose logging to the console.
- โ SEO friendly -
react-helmet
provides control of the page title/meta/styles/scripts from within your components. - ๐ค Optimised Webpack builds via HappyPack and an auto generated Vendor DLL for smooth development experiences.
- ๐ Tree-shaking, courtesy of Webpack.
- ๐ฎ Security on the
express
server usinghelmet
andhpp
. - ๐ Asset bundling support. e.g. images/fonts.
- ๐ Preconfigured to support development and optimised production builds.
- โค๏ธ Preconfigured to deploy to
now
with a single command.
Redux/MobX, data persistence, modern styling frameworks and all the other bells and whistles have been explicitly excluded from this starter kit. It's up to you to decide what technologies you would like to add to your own implementation based upon your own needs.
However, we now include a set of "feature branches", each implementing a technology on top of the clean master branch. This provides you with an example on how to integrate said technologies, or use the branches to merge in a configuration that meets your requirements. See the
Feature Branches
documentation for more.
Getting started
git clone https://github.com/ueno-llc/starter-kit-universally my-project
cd my-project
npm install
npm run dev
Now go make some changes to the Home
component to see the tooling in action.
Docs
- Project Overview
- Project Configuration
- Package Script Commands
- FAQ
- Feature Branches
- Deploy your very own Server Side Rendering React App in 5 easy steps
- Changelog
Who's using it and where?
You can see who is using it and how in the comments here. Feel free to add to that telling us how you are using it, we'd love to hear from you.
Contributors
Thanks goes to these wonderful people (emoji key):
Andrรฉs Calabrese ๐ป |
Andrey Luiz ๐ป |
Alin Porumb ๐ป |
Benjamin Kniffler ๐ป |
Birkir Rafn Guรฐjรณnsson ๐ฌ ๐ ๐ป ๐ |
Carson Perrotti ๐ฌ ๐ป ๐ ๐ |
Christian Glombek ๐ ๐ป |
---|---|---|---|---|---|---|
Christoph Werner ๐ฌ ๐ ๐ป ๐ |
David Edmondson ๐ป |
Dion Dirza ๐ฌ ๐ ๐ป ๐ ๐ |
Evgeny Boxer ๐ ๐ป |
Joe Kohlmann ๐ ๐ป |
Lucian Lature ๐ ๐ป ๐ |
Mark Shlick ๐ป |
Ryan Lindskog ๐ป |
Steven Enten ๐ฌ ๐ ๐ป ๐ |
Sean Matheson ๐ฌ ๐ ๐ป ๐ ๐ก ๐ โ ๏ธ ๐ง |
Steven Truesdell ๐ฌ ๐ ๐ป ๐ โ ๏ธ |
Thomas Leitgeb ๐ ๐ป |
Tyler Nieman ๐ป |
This project follows the all-contributors specification. Contributions of any kind welcome!