1 | # Microsite
|
2 |
|
3 | `microsite` is a fast, opinionated static-site generator (SSG) that outputs extremely minimal clientside code using **automatic partial hydration**. Pages are written with Preact, Typescript, and CSS Modules and compiled with `esbuild`.
|
4 |
|
5 | [See the demo](https://microsite-demo.nmoo.vercel.app/)
|
6 |
|
7 | > Microsite is output as ESM, so it needs to run in a Node environment which supports it (like node@12)
|
8 | > You can add a script such as this to your project:
|
9 | > `node --experimental-modules --experimental-specifier-resolution=node node_modules/.bin/microsite build`
|
10 |
|
11 | ## Automatic Partial Hydration (APH)
|
12 |
|
13 | The most exciting feature of Microsite is automatic partial hydration. Current solutions send the entire component tree, which has already been rendered server-side, to the client for hydration.
|
14 | Microsite, on the other hand, uses a hint from the author (the `withHydrate` HOC) to strip away any unnecessary code and ship highly optimized code to the client.
|
15 |
|
16 | ```tsx
|
17 | import { withHydrate } from "microsite/hydrate";
|
18 |
|
19 | const Counter = () => {
|
20 | const [count, setCount] = useState(0);
|
21 |
|
22 | return (
|
23 | <>
|
24 | <button onClick={() => setCount((v) => v - 1)}>-</button>
|
25 | <span>{count}</span>
|
26 | <button onClick={() => setCount((v) => v + 1)}>+</button>
|
27 | </>
|
28 | );
|
29 | };
|
30 |
|
31 | export default withHydrate(Counter, { method: "idle" });
|
32 | ```
|
33 |
|
34 | There are a few rules to keep in mind when leveraging APH:
|
35 |
|
36 | - Hydrated components cannot contain any other hydrated component, as hydration is controlled by the top-level component.
|
37 |
|
38 | - Hydrated components should be placed as deep as possible in your app's tree for the most efficient bundles.
|
39 |
|
40 | - Hydrated components can't accept _rich_ children, because it's non-trivial to serialize them, though I have some ideas to address this. For now, strings and numbers as children are fine.
|
41 |
|
42 | #### `withHydrate` Options
|
43 |
|
44 | **method**
|
45 |
|
46 | As a developer, you know exactly how your site is structured, so Microsite allows you to tweak how hydration occurs, optimizing for your specific use cases.
|
47 |
|
48 | - `idle` (default) hydrates the component as soon as possible, when the browser executes [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback) code.
|
49 |
|
50 | - `visible` hydrates the component as soon as it enters the viewport, via [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver).
|
51 |
|
52 | - `interaction` hydrates the component as soon as the user interacts with it (via `focus` or `pointerenter` events.)
|
53 |
|
54 | ## Pages
|
55 |
|
56 | Microsite uses the file-system to generate your output, meaning each component in `src/pages` outputs a corresponding HTML file.
|
57 |
|
58 | Page templates are written as `.tsx` files with [Preact](https://preactjs.com/).
|
59 |
|
60 | ## Styles
|
61 |
|
62 | Styles are written using CSS Modules. `src/global.css` is, as you guessed, a global CSS file injected on every page.
|
63 | Per-page/per-component styles are also inject on the correct pages. They are modules and must be named `*.module.css`.
|
64 |
|
65 | ## Project structure
|
66 |
|
67 | Microsite cares about the structure of your project. It should look like this:
|
68 |
|
69 | ```
|
70 | project/
|
71 | ├── src/
|
72 | │ ├── global.css
|
73 | │ ├── global.ts // shipped entirely to client, if present
|
74 | │ ├── pages/ // fs-based routing like Next.js
|
75 | │ │ └── index.tsx
|
76 | │ └── public/ // copied to dist/
|
77 | └── tsconfig.json
|
78 | ```
|
79 |
|
80 | ## Acknowledgments
|
81 |
|
82 | - [Markus Oberlehner](https://twitter.com/maoberlehner), [`vue-lazy-hydration`](https://github.com/maoberlehner/vue-lazy-hydration)
|
83 | - [Markus Oberlehner](https://twitter.com/maoberlehner), [Building Partially Hydrated, Progressively Enhanced Static Websites with Isomorphic Preact and Eleventy](https://markus.oberlehner.net/blog/building-partially-hydrated-progressively-enhanced-static-websites-with-isomorphic-preact-and-eleventy/)
|
84 | - [Lukas Bombach](https://twitter.com/luke_schmuke), [The case of partial hydration (with Next and Preact)](https://medium.com/@luke_schmuke/how-we-achieved-the-best-web-performance-with-partial-hydration-20fab9c808d5)
|
85 | - [Jason Miller](https://twitter.com/_developit) and [Addy Osmani](https://twitter.com/addyosmani), [Rendering on the Web](https://developers.google.com/web/updates/2019/02/rendering-on-the-web)
|