What's in The Box?
There's a trivial example application in Breko-hub to help you explore the features.
FooRoute component showing how to pre-load data on both server and client render (the prefetch). The
FooRoute loads data unique to the client (the defer) which replaces the universally loaded data.
BarRoute component showing how to pre-fetch route data with a promise-action.
An API to support the
BarRoute's data needs.
/private route doing a redirect on both client and server with a flash message. The flash message is then automatically removed using a redux-saga.
FlashMessage component gives an example of
action -> reducer flow. A saga removes messages after a delay (or by clicking remove). The FlashMessages component uses a Block Element Modifier (BEM) utility for managing class names in combination with CSS-modules.
There's a dispatch call in
src/app/entry.js to show how to broadcast actions to a socket. A small socket server hosted within the app is (on the same port) forwarding any broadcast actions.
test/functional/client/client-render.test.js file has tests for routes.
Breko-hub uses settings in your run-time environment, such as
DEBUG. When developing, it's nice to use a
.env file. The app loads an environment from your
.env file to give you quick and convenient control when developing.
.env file is untracked. This is important as environments contain sensitive information!
In Breko-hub, babel treats
./src/ as the default import root.
Using absolute require calls improves portability and clarity. No-one enjoys writing
../../../ and in a large application its important to give hierarchy to units of code. These two factors fight each other. By making
./src/ the default import root, you require any file without needing a relative path.
// inside `test/functional/client/client-render.test.js` import App from '../../../src/app/components/App' // becomes import App from 'app/components/App'
Babel-root-imports resolves modules according to a configurable project route. Use a prefix of
~ to your import string if you need to require from above
// inside `test/functional/client/client-render.test.js` import '../../../package.json' // becomes import '~/package.json'
Head and Body Script Loading
A big performance factor for an application is the load time. CSS links contribute to this load time because of their large filesize. One quick improvement is to defer loading of styles for below the fold or progressive enhancement. Asynchronous asset loading is a great performance gain.
There're intentionally, 2 entry points for this application,
head. This is to give the developer more control of their scripts location on the server render. The
bodyStyles array loads CSS asynchronously after the
The CSS to JS correspondence in applications are not perfect. It wouldn't be strange for JS required in the body build to require a CSS file suitable for the
head.css bundle. You configure this in
src/server/middleware/renderRouteContext.js by moving the available assets into the different arrays. The
ExtractTextPlugin grabs any CSS into the head bundle from the body build if it's common to both.
Whilst developing, CSS-modules are not caught by the
ExtractTextPlugin configuration for CSS hot reloading on the client.
You import any SCSS or CSS into a client JS file. The file extension
/.module.s?css/ instructs Webpack to import the file as a CSS-module. This gives more clarity to each CSS file and some flexibility when managing styles.
npm: "v3.x" node: "v5.x"
This project uses the above versions of npm and node. It's advised to use the same engine when using this boilerplate.
It doesn't work to develop, build, test or serve on Windows... if you want to make PRs for windows, please do!
Thanks For Ideas!
This boilerplate is shamelessly reusing some ideas from: