...or Page
, or Main
context, to avoid ambiguity.
~~~Context~~~ (ahem) use case
I’m currently trying to provide context to certain deep nodes which I expect to use on most/all pages, and which require an async initialization. (Specifically, to give credit to another couple awesome projects: Shiki and remark-shiki-twoslash.)
I’m also trying to use inline markdown with a template literal because I’m a weird person who wants the inverse of MDX: I want markdown in JSX, not the other way around, because it gives me all the cool Remark/Rehype stuff but with all the cool tooling that comes relatively for free in a .tsx
file. Plus I’m kind of obsessive about collocation of component definitions which is why I put all that effort into getting Fela working.
I’ve tried setting up in a custom document or even in a page’s getStaticProps
, then providing the (now synchronous) highlighter instance with a context provider, but that appears to be optimized out at build time. I’d essentially have to hydrate the entire page to keep it, or move a lot of boilerplate down through props.
Caveats filing the issue
-
As always I’m doing weird custom stuff so it’s entirely possible I’m fighting my own setup/not using tooling properly. I ran out of steam debugging and felt like it’s more productive to start a discussion.
-
This could potentially be addressed by #99 in ways I’ll handwave about to avoid derailing my own issue; I think this hypothetical API could be valuable and a better DX than yet another build plugin.
Proposal
I know there’s an internal doc context used at the SSG stage to provide various details for the final full HTML render, much like the internal head context.
I don’t want to overload this for end users, but provide a distinct (opt in of course) API for sites to define their own document/page context that’s guaranteed to be available during build/stripped out unless explicitly hydrated.
In fact I might even want to go one step further and suggest a general API/DX improvement over the Next/Gatsby style interface (which should be backwards compatible unless I’ve failed to think of something), and say that props supplied in a custom document or getStaticProps
could automatically provide context consumable by deeper components. This would address very similar issues I had with those doc/page APIs that don’t allow per-component data fetching at build time.
Addressing problems and risks I can anticipate
-
More API, more to document, more to maintain and risk breakage; but this kind of API is especially useful and viable for a static-first library.
-
I’m not especially fond of context (or hooks) because they make reasoning about components harder; for the DX it’s a huge win, allowing more build-time work in the normal flow without more tooling.
-
The biggest risk I see is accidental deoptimization by making build-time stuff part of the bundle; there’s already safeguards in place distinguishing build/bundle and this could follow suit.
-
Type safety is a major concern for me, and anything automated/implicit could lead to magic and assumptions; definitely an argument against automating any of this, probably easier to target doc-global and/or a very specific API for context overall. Or a useDocument
/usePage
hook but I’m losing it even suggesting that 🙃
-
I already said the context API isn’t my favorite, is it actually right for this? I’m just trying to use prior art. Open question IMO.