This is a fork of kartiknair/dhow with some additional features.
From the original README:
JSX-powered SSG for Node.js. Write logic like React with a directory-structure like Next.js but generate plain HTML with no client side JS.
The changes in this fork are made in the hope that the modifications will eventually be included in the upstream repository.
The interface to the dhow command is
$ npx @fsoc/dhow --help
Usage
$ dhow <command> [options]
Available Commands
build Compiles your pages for deployment
dev Rebuilds your pages on change and hosts them locally
For more info, run any command with the `--help` flag
$ dhow build --help
$ dhow dev --help
Options
-i, --indir Sets the directory where files will be read from (default pages)
-v, --version Displays current version
-h, --help Displays this message
By default, dhow expects a directory structure like
├── pages
│ ├── about.js
│ └── index.js
└── public
└── dhow.jpg
and, given the above, generates a directory like
out
├── about
│ └── index.html
├── dhow.jpg
└── index.html
which can be statically hosted using any webserver. The content of the public directory is simply copied over, the JavaScript files in the pages directory are transpiled to HTML and then copied to an appropiate location based on the file path.
Pages (the JavaScript files in the pages directory) are expected to export a function which returns JSX.
const Home = () => (<>
<img src={'/dhow.jpg'} alt={'Dhow'} />
<p>
JSX-powered SSG for Node.js. Write logic like React with a directory-structure like Next.js but generate plain HTML with no client side JS.
</p>
</>)
export default HomeIn addition to the required default export, pages can export the (optionally async) function getProps, which can be used to dynamicaly fetch content at build time. Its return value is passed to the default-exported function.
export default ({ buildTime }) => (<>
<p>
This page was built on <time datetime={buildTime.toISOString()}>
{buildTime.toDateString()}
</time>.
</p>
</>)
export const getProps = async () => ({
buildTime: new Date()
})By default each page is mapped to a route, determined by its file path. One can map a single page to multiple routes by wrapping its file name in brackets, like pages/post/[pid].js.
In order to define the possible routes, a page can export the (optionally async) function getPaths, which is expected to return an array of strings. The file name is ignored and can be thought to be replaced with each item in the array.
export default ({ content }) => (<>
<p>
{content}
</p>
</>)
const data = {
'about': /* ... */,
'contact': /* ... */,
'privacy': /* ... */,
}
export const getProps = async (slug) => ({
content: data[slug]
})
export const getPaths = async () => Object.keys(data)As can be seen in the example above, each item in the returned array is also passed to getProps (if it was exported). Assuming the above code is in the pages root, this would result in the routes /about, /contact and /privacy being available.
Analogous to NextJS, one can override the default App or Document through providing an _app.js or _document.js in the pages directory.
The App is a wrapper around every page, it receives the component that is exported from every page and the result of the getProps function (undefined if it was not exported).
const App = ({ Component, pageProps = {} }) => (<>
<Component {...pageProps} />
<Footer />
</>)
export default AppThe Document is the actual DOM tree into which the built HTML of every page will be inserted, it should, at minimum, include
const Document = () => (<>
<html>
<head>
</head>
<body>
{/* Pages will get inserted here. */}
</body>
</html>
</>)
export default DocumentNote that, if provided, this is a complete replacement of the internal default tree (which looks like the above), so make sure it is complete.
A Head component is exported which can be used to modify the contents of the document head on a per-page basis.
import { Head } from '@fsoc/dhow'
export default () => (<>
<Head>
<title>Page title</title>
</Head>
</>)It's fine to have multiple Heads in one document, but note that (unlike NextJS, for example) the content of the Head will be appended to what is already in it (i. e. what was provided in Document or App).
A number of internal variables are exposed through process.env for the consumption of pages.
__DHOW_STAGING_PATHthe absolute path to the internal staging folder__DHOW_PAGE_PATHthe absolute path to the internal page file corresponding to the current file__DHOW_PAGE_DIRthe absolute path to the directory in which the current page file is in, for convenience__DHOW_ROUTE_PATHthe name of the current route, this is the path to which theindex.htmlfile which is generated for the current page will be written to, relative to the output directory
Debug is used to provide debug logs, enable it through setting the environment variable DEBUG=dhow:*.
CSS is processed using PostCSS, dhow will attempt to read a postcss.config.js file from the root of the project and pass it to PostCSS. If none is found, nothing is passed through.