A simple react based static site generator built to understand static site generation.
- Clone the repo
npm i
to install the dependenciesnpm run bundle
to prepare the server side executablenpm run build
to use the bundled server side executable to generate the static site insidepublic/
serve public/
(or anything you use to serve static files)
While this supports dynamic routes, to serve dynamic routes, you need to setup your nginx/what have you to serve
the root <dynamic route>/index.html
for all dynamic routes and from there let the client side routing kick in.
- Support static routes
- Support dynamic routes (supported only client side)
- Support using data sources
- Generate nginx config to complete the dynamic routes picture
./index.js
-> project root has an index.js which exports a react component
that is used as a shell to generate all files. It's equivalent to
index.html. ReactDOMServer.renderToStaticMarkup is used to render this file.
Rendered file name depends on the route being rendered. If not found, index.default.js is used.
Though this is sort of a lie as right now index.default.js is hardcoded to be used.
App/index.js
-> This react component will be given [<Link />]
and [<Route />]
It can choose to render those arrays however and where ever it wants. It's
the shell for your application.
App/Main.js
-> This is the entry point for the client side app bundle.
Therefore, it should have a call to ReactDOM.hydrate
App/Routes
-> This folder contains all the routes. The hierarchy matches the
the name of the route. For example:
Component: App/Routes/index.js -> Route: /
Component: App/Routes/home/index.js -> Route: /home
Component: App/Routes/home/:param/index.js -> Route: /home/:param
Each route component can expose a static async getData
function that resolves to the data
needed by the route. It should be keyed by the route params. For example:
For a route such as /home/:username/product/:productId
, the getData
function should return
a data structure such as:
[
{
username: 'abc',
productId: '10',
...additional data
},
{
username: 'xyz',
productId: '20',
...additional data
}
]
The additional data will be passed in as props.data
to the component for the route.
- Generate route list relative to
App/Routes/
- Generate route manifest from route list received from step 1. Its shape is
{ ReactRouterRoute: componentModule }
-
- build
<Link></Link>
array - build
<Route />
array
- build
- Render a map from react router route to
index.html
string for that route - Render all
index.html
files for all routes. They are generated fromindex.default.js
found in the root of this project. - Generate js and css bundles using
App/Main.js
as entry for webpack and put 'em in/public/assets
. The config file used for this iswebpack.static.config.js
in the root of this project.
And you're done!
Redirects are reified. This means, while rendering if a redirect is encountered, for e.g., / redirects to /home then the redirect is followed during rendering and the final route that renders to string is put in the folder for /.
- This isn't a generic solution. It's tied to this repo.