A generator for creating sophisticated enterprise level universal React SPAs. Have server side rendering, lightening fast pages, SEO support and much much more...
Are you exhausted by the exercise of stitching together all the essential pieces to constitute a comprehensive SPA? Are you frustrated by getting painted into corners with bloated frameworks and mired in their black boxes? Whether you're looking to create a SPA application, jump-start your own enterprise framework, or simply want to see and learn how all the magic works, you're in the right place.
Paragons brings together some of the top tooling, modules, and approaches of modern SPA development and combines them into a simple elegant box.
Dislike a particular aspect or need to tack in something else? Begin by reading the Walkthrough below and then dig in. You will find valuable documentation on all major components.
- React v16, React Router v4, and Redux with Thunk Middleware and Redux DevTools
- Webpack v4 with Hot Module Replacement (HMR) and pre-configured webpack-bundle-analyzer
- Server Side Rendering (SSR) with pre-render task support
- Code Splitting
- Styling (CSS, Sass)
- Testing (Jest with Enzyme) and Code Coverage (Istanbul)
- Internationalization (i18n)
- SEO Support
- Secure routes
- Deferred Rendering (aka Above the Fold Rendering)
- Demos Optionally install a collection demonstrations that show and explain the various features. This is an excellent way to explore how things work.
- Docmentation (JSDoc)
For further information and discussion see corresponding sections below.
In development mode modifications are automatically detected and made available via HMR without restart. Neither the server bundle nor the client chunks are not emitted. Source maps are inlined.
npx -p yo -p generator-paragons generator-paragons my-appcd spa-my-appnpm start
Then open http://localhost:3000
npx is available on
npm 5.2+ and higher. If you are on a previous version see Alternative Installations
In production mode the server bundle and the client chunks are emitted to the dist directory. In addition the client chunks are optimized(minification, tree shook, etc.). Source maps are emitted per chunk.
npm run buildnpm run start-prod
- Single simple webpack.config.js which handles both the client and the server side.
Server Side Rendering (SSR)
Pages are built on the server side and can be immediately rendered in the clients browser. Not only can this be a huge performance gain but, it is absolutely essential for SEO.
Pre-render Task Support
There can be a number of operations which need to be performed prior to inducing the SSR. One of the main challenges is
pre-loading data in to the Redux store before the SSR cycle is invoked. That can be easily accomplished by
preloadData thunk function whic returns a
Promise on your component. server.js will
automatically pick up all
preloadData promises and add them to the pre-render tasks. This capability is demonstrated
Code splitting allows you to beak up your application into chunks. In practice this is usually done per route so each page is served with only what it needs to render. Thanks to dynamic imports and React Loadable this becomes a simple game. This capability is demonstrated by CodeSplitPage.js.
Webpack is a static module bundler. That is given an entry point it will walk the imports and requires bundling everything in to JS file. The key is to break that static path by using Dynamic imports. Simply use Webpacks import() function as opposed to the import statement.
Styling (CSS, Sass)
Out of the box CSS and Sass support with autoprefixing.
Tests are located in the
tests directory. As a matter of practice it is recommended to mirror the
React components can be tested with Enzyme
test env of the root .babelrc ensures the code is transpiled.
Components can use the React Intl API right out of the box. All translations are maintained under `src/i18n/. This capability is demonstrated by i18nPage.js.
The users locale is determined via the Express middleware express-locale
in server.js and both stored into the Redux store and feed to
<IntlProvider> in HostPage.js.
The translations are loaded by Webpacks import() function which is very cool because they are automatically encapsulated in a chunk and can be dynamically loaded. Plus they will be cached via the standard browser caching and only downloaded initially or if they are updated!
This SEO game is really only applicable to publicly available pages which can be sever side rendered. That is because the crawlers walk the site by following all the available links. As they request them, the titles, meta tags, keywords, etc. need to be appropriately set for the page / route.
These capabilities are embedded into PurePage.js which component pages can extend.
PageSupport.js is a singleton per request/response cycle which centralizes critical page data points including the title and meta tags.
Note: Although it is possible to update the the DOM on the client side; that is update the title, meta tags, keywords, etc. once the SPA is in effect, it's useless as the crawlers as they can't navigate the SPA. That being said the title is a special case as it is reflected in the browser and impacts the users experience. Therefore PageSupport.js does update it in real time.
For some routes/pages the user needs to be authenticated. This can be accomplished by setting
secure="true" on the
route. See the
/profile route for example usage. When the user attempts to access a secure route, they are redirected
to the login page for authentication. After successful authentication, the user is then redirected to the route
they were initially trying to access...
_Note: The actual authentication implementation in
LoginPage.js.handleLogin is stubbed for example purposes and
will accept any password except "fail" which can be used to test drive a failed login scenario. That being said it
does give you a solid starting point to work with including preparation of password hash, seeding profile information
in the Redux store, a logout route, and a profile page.
Deferred Rendering (aka Above the Fold Rendering)
This is a technique for increasing the page render time. The idea is that you only take the cost of rendering the content which the user will see or what is considered to be above the fold.
This capability is demonstrated by DeferRenderPage.js which leverages the DeferRender.js component.
Note(1): In practice the cost is usually the the supporting service operations not the actual render.
Note(2): If you are truly concerned with the visible portion, see react-loadable-visibility.
An inbound request is first handled by Express in server.js
which does some up front work like determining the users locale, setting the root directory from which to serve static
assets, and configures middleware. If the mode is
development then hot reloading is also setup.
Next serverRenderer.js checks to see if the requested path matches a configured route. If so it determine users locale and language, creates the Redux store, loads the international locale data and the translations, and performs all pre-render tasks like data loading. Finally it delegates to HostPage.js which performs the actual server side render and assembles the initial HTML is sent to and rendered immediately in the clients browser. In the background, the SPA is hydrated into a fully functional client side application by client.js.From there the SPA is in full effect.
Local Installation (preferred)
Here you install
generator-paragons locally and then invoke
generator-paragons. This approach is generally
more acceptable because each time you do it your ensured to be working with the latest and greatest Paragons generator
because you are starting fresh each time (
npx is much fancier).
mkdir spa-my-appcd spa-my-appnpm i yo generator-paragons./node_modules/.bin/yo paragons
Global Installation (use npx or local install; this is just here for educational purposes)
generator-paragons is installed globally but, that is not optimal because you could be out of sync
with the latest and greatest.
npm i -g yo yeoman-generator generator-paragonsmkdir my-appcd my-appyo paragons my-app
Copyright (c) 2018-present, Joseki Technologies Inc.
Licensed under the Apache License, Version 2.0.