Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Layout modules #70

Open
aleclarson opened this issue Jun 30, 2022 · 0 comments
Open

[RFC] Layout modules #70

aleclarson opened this issue Jun 30, 2022 · 0 comments
Labels
in progress Actively being worked on roadmap

Comments

@aleclarson
Copy link
Contributor

aleclarson commented Jun 30, 2022

Frontend developers are familiar with the concept of layouts, so let's align with that. This feature would replace the concept of "renderers" and the render module would be no more. At the same time, we'll remove support for having multiple renderers/layouts in one file (which is what the render module encouraged). That feature requires complex parsing of the render module to determine which statements are used by which renderers. It'll be nice to remove that complexity.

How are layouts defined?

Layouts are defined with the defineLayout function and typically exported with export default. Layouts can optionally wrap the defineLayout call with an arrow function so the layout can be customized by the developer for specific routes.

From the routes module, the developer can…

  • set the default layout for all routes or a set of routes (via setLayout call)
  • set the layout of a single route (via chained method call, or maybe the route config?)

What do layouts do?

Layouts control…

  • the <html> and <head> elements (via object or string)
  • how the route module is rendered to HTML
  • how the page is hydrated (if at all)
  • the Vite config for each route

Layouts can use the RenderRequest object to influence any of its behavior. Access of route props (via req.props) within the layout's render method is tracked, so only the props needed for hydration are sent to the client. If the layout has no hydrator, then route props are never sent to the client.

Example layout module

export default (options) =>
  defineLayout((req) => {
    return {
      // Can be a string or object.
      head: {
        title: "",
        language: "",
        description: "",
        viewport: {},
        meta: [{ property: "og:title", content: "" }],
        styles: [{ media: "", innerText: "" }],
        scripts: [{ src: "", async: true }, { innerText: "" }],
        links: [{ rel: "icon", href: "/favicon.svg" }],
      },
      // Provide a Vite config.
      config: async () => (await import("./config")).default(options),
      // Provide a client hydration function.
      hydrator: () => import("./hydrator"),
      // Render a route module.
      render(module, { nested }) {
        // Prop access is observed, so only props needed for hydration are sent to the client.
        const layout = <div>{req.props.foo}</div>;

        // The `nested` flag tells the layout to skip stringification.
        return nested ? layout : renderToHtml(layout);
      },
    };
  });
@aleclarson aleclarson added roadmap proposal An idea not set in stone labels Jun 30, 2022
@aleclarson aleclarson added in progress Actively being worked on and removed proposal An idea not set in stone labels Jul 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in progress Actively being worked on roadmap
Projects
None yet
Development

No branches or pull requests

1 participant