plentico / plenti

Static Site Generator with Go backend and Svelte frontend
https://plenti.co
Apache License 2.0
1k stars 48 forks source link

Configurable entrypoint #211

Open jimafisk opened 2 years ago

jimafisk commented 2 years ago

From the docs:

The layouts/global/html.svelte file is important and changing its name will break your app.

It would be nice if that wasn't necessarily the case. We could potentially add an optional entrypoint key to the plenti.json sitewide configuration file that you could set to whatever you'd like:

{
  "entrypoint": "global/wrapper.svelte"
}

If the entrypoint key is omitted, it should just default to layouts/global/html.svelte. We'd also need to account for this in router.svelte: https://github.com/plentico/plenti/blob/17c8c3a9f62897d92cdc91c02efd3538b3769e60/cmd/defaults/ejected/router.svelte#L5

We would also need to adjust data_source.go to render() HTML using the custom entrypoint: https://github.com/plentico/plenti/blob/17c8c3a9f62897d92cdc91c02efd3538b3769e60/cmd/build/data_source.go#L423

danedavid commented 1 year ago

Hi 👋🏾 I would like to work on this, and already had a go at it. I've raised a PR, but I kind of don't think it's final (although build and new site commands work fine). I have questions about:

Greate project by the way :)

jimafisk commented 1 year ago

Hey @danedavid, welcome to the Plenti project :wave: I appreciate you hopping right in!

I saw you defined reEntryPoint regexp in Gopack to replace public/spa/ejected/router.js. That totally makes sense why you would start there, the router is the true entrypoint for the project (it's called directly from main.js). Since we abstract the router into the hidden "core" I'd actually like to target one level up as the "entrypoint" even though it's technically just the first component that actually renders any HTML. We're only really using Gopack to attempt to make things ESM friendly, it converts .svelte file extensions to .js and creates full import paths for npm modules from your project, so I don't think we'll have to change it for this particular task.

My plan was to leave the router intact - if folks want to manipulate this, they can plenti eject in their project. I was mainly attempting to give the user more flexibility over their layouts/ structure. Currently layouts/global/html.svelte is required, but this would allow that file to be defined by the user. So I think we'll have to expose the entrypoint in the client, we could use the env magic prop for this (gets imported in main.js). Then in router.svelte we'll need to use a dynamic <svelte:component> instead of hardcoding the import of the <Html> component like we're doing currently.

The SSR is done in data_source.go, it looks like you did the replacement correct there. The config reading stuff looks good too. Entrypoint was just the term I was familiar with, looks like esbuild uses it and snowpack might use it as well? Thanks!

jimafisk commented 1 year ago

This should be available in v0.5.21. Thanks for the help on this @danedavid!

jimafisk commented 1 year ago

Using a dynamic component to hydrate the full document throws console errors:

Chrome error ``` Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': Nodes of type '#text' may not be inserted inside nodes of type '#document'. at append (https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:288:20) at insert (https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:300:9) at Object.m (https://localhost:3000/spa/core/router.js:198:4) at mount_component (https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:1598:26) at init (https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:1690:9) at new Component (https://localhost:3000/spa/core/router.js:330:3) at https://localhost:3000/spa/core/main.js:3:1 ```
Firefox error ``` Uncaught DOMException: Node.insertBefore: Cannot insert a Text as a child of a Document [index.mjs:288](https://localhost:3000/spa/web_modules/svelte/internal/index.mjs) append https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:288 insert https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:300 m https://localhost:3000/spa/core/router.js:198 mount_component https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:1598 init https://localhost:3000/spa/web_modules/svelte/internal/index.mjs:1690 Component https://localhost:3000/spa/core/router.js:330 https://localhost:3000/spa/core/main.js:3 ```

I've tried to mitigate this while still allowing configurable entrypoints to no avail:

{#if env.entrypoint === 'global/html.svelte'}
  <Html
    {path}
    {params}
    {content}
    {layout}
    {allContent}
    {allLayouts}
    {env}
    {user}
    {shadowContent}
  />
{:else}
  <svelte:component
    this="{allLayouts['layouts_' + env.entrypoint.replace('/','_').replace('.','_')]}"
    {path}
    {params}
    {content}
    {layout}
    {allContent}
    {allLayouts}
    {env}
    {user}
    {shadowContent}
  />
{/if}

The sites should generally still work even with the console errors being thrown, but I've had a couple of folks reach out with concerns.

Unfortunately I think I'm going to have to revert this feature for now, unless we can think of a way around this.

jimafisk commented 1 year ago

The configurable entrypoint was removed in v0.6.8.

The scaffolding for setting an entrypoint is still there (so you can see it in env), it just won't actually use it in your templates.