Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

danprince/melange

Repository files navigation

Melange

Go static site generator that supports a simple markdown only folder structure and partial hydration for embedded Preact/React components.

  • Files ending with .md become .html
  • Every file is templated into _theme.html if it exists, if not use the default theme
  • Files can render Preact components in 3 ways
    1. Static render {{ render "./counter.tsx" "count" 1 }}
    2. Hydrate {{ render "./counter.tsx" "count" 1 | client_load }}
    3. Dynamic render {{ render "./counter.tsx" | client_only }}

Initially these functions will replace the content with a marker token, that allows us to swap the value out for the HTML we get from actually rendering the component asynchronously later. These functions will wrap that marker token in a div with an ID that allows the component to be "rehydrated" at the client side, if necessary.

Once all pages have been rendered, esbuild will produce multiple bundles from the rendered components.

  • A static nodejs bundle that will render the static versions of the elements for each page.
  • A browser bundle for each page that will hydrate the appropriate elements at runtime.

Go has to ask a Nodejs process to evaluate the static bundle, then the response is used to replace the marker tokens in the evaluated page templates.

Finally the appropriate scripts/styles are injected into the pages and the everything is copied/written to disk.

TODO

  • Use long-running node process to prevent paying for once-per-build startup
    • Don't use stdio (prevent console.log from messing with output)
  • Support custom _theme.html files
  • Fix collisions between hydrations IDs across separate files
  • Fix rendering order to make {{ pages }} deterministic (render index.md last)
  • Figure out how to make hydration generic (preact/react swap)
  • Support build time props on components
  • Try npm free react-cdn/preact-cdn frameworks?
  • Support a sensible set of assets
  • esbuild plugin that strips non-js files from the server build?
  • Syntax highlighting
  • Bundle function that adds a script without hydrations
  • Preflight checks for dependencies
    • Node
    • Frameworks
  • Make common error presentation as friendly as possible
    • Esbuild bundler errors (probably parse related)
    • Node execution errors
    • Parse time errors inside templates
    • Runtime errors inside templates
  • Tests
    • Ignored pages aren't copied/built
    • Site is rendered from leaf to root
    • Frontmatter is parsed
    • Test that page with no elements is has no script tags
    • Test that page with static elements has no script tags

Go vs Node (Bun/Deno)

  • Faster
  • Static binary
  • Built in templates
  • Native esbuild
  • Simpler compilations (than TS)
  • Small markdown ecosystem
  • No MDX option
  • Relies on node for execution
  • Few plugins for native esbuild

Known

  • Make jsxImportSource work (might be blocked by evanw/esbuild#2349)
  • Support prod builds
  • Solve the problem of SSR components not generating CSS for client