This is a boilerplate React project that allows you to start creating an Universal PWA. It is based on a flexible setup of create-react-app script without any external framework such as Next.js or GatsbyJS.
An universal PWA is an app that:
Moreover it's preconfigured to have:
GraphQL and REST ready
and many other useful features allowing you to develop at the best!
So please, use VSCode, try to be DRY, comment your code with JSDocs, learn to use React contexts and all Javascript ES6 and React best practices and patterns!
Note: we're using 4 spaces (instead of 2 that is common in javascript because of callback hell) because it discourages nesting. In fact reducing the spaces to fit more levels in is a counterproductive idea. Use async/await as much as possible.
You can edit this project on your needs, even ejecting CRA to have a full configurable project. However in most cases you just need to edit following files:
you can use npm run serve:screen to run the process in background with linux screen utility
NOTE: to improve SEO enable prerender feature for SSR (Read dedicated paragraph below)
With this base you can build 3 kind of projects:
A CSR application is totally rendered by the client via Javascript. The client will receive only a small index.html and the bundled javascript application will render the content.
To build this kind of app you don't need any kind of requirement since you could develop and start/build your app directly with npm commands.
Pros:
Cons
You should use it as a web app not as a blog or any other website that needs indexing and high compatibility.
A Static Site Generation is a technique that allow you to pre-render your app pages/routes during the build process creating a version of that page that contains the content to index and the bundler will only attach event-listener to pre-existing html (hydration). This will allow you to deploy a static site that will be fully indexable by the crawlers.
To use SSG you should install react-snap globally using npm install -g react-snap then you can use: npm run build:ssg instead of normal build command. We don't include it in our package.json because it downloads the entire chromium engine that is quite big, so you will download it on your needs.
Pros
Cons
More info Here: React Static
The approach above (CSR+SSG) already allows you to develop an app/website that can be modern and indexable, but it's not yet an Universal PWA. There are a lot of websites that changes their contents very often (a blog) or even in real-time depending on some parameters (search engine). Such apps cannot be totally static generated at build time of course so we need an extra layer to handle the "crowling problem". This is called Static Server Rendering. The SSR is the method used by old web apps (often written in PHP or Java Servlets) to serve the entire content to the client directly rendered by the server. This method can be used now as an helper to CSR and SSG serving pre-rendered and not dynamic static page only to some kind of clients (such as Web-Crawlers).
To use SSR you need to install following packages:
npm install prerender prerender-node
We don't include it in our package.json because it downloads the entire chromium engine that is quite big, so you will download it on your needs.
then you have just to configure your conf.js and enable prerender conf.
Pros
Cons
NOTE: Of course you can even use CSR+SSG with a 3rd party CDN service that will prerender your pages allowing you to host your app everywhere, but mostly such services are not free.
This project follows partially the hw-core directory structure on (CRA folder structure)https://facebook.github.io/create-react-app/docs/folder-structure
With following specs:
For internal deps and modules we're using subrepo instead of subtree/submodule that are not enough to both include a git based dependency and working on it at the same time. You can check the app.sh script to see how to sync your dependencies.
We're monkey-patching the CRA via craco library allowing us to create some useful path alias to avoid relative path hell: ( ../../ )
So you can use paths defined in cra-config.js file:
"@this/src": path.resolve(__dirname, 'src/'),
"@this/conf": path.resolve(__dirname, 'src/conf'),
"@hw-core": path.resolve(__dirname, 'src/deps/hw-core')