Skip to content

An experiment to create Gutenberg blocks using Mitosis and compile them to both a Liquid template and a React component that hydrates the server-rendered HTML.

Notifications You must be signed in to change notification settings

michalczaplinski/hydration-mitosis-demo

Repository files navigation

Hydration Mitosis Demo

This is an experiment that uses the Mitosis compiler to create Gutenberg blocks using the Mitosis syntax and compile them to both React for frontend and a Liquid template to be rendered on the server in PHP.

This approach tackles both the problems of duplication of logic between the PHP and JS parts of the block. It also addresses the issue of hydration of blocks as the final JS that hydrates the block is generated by the compiler.

Usage

  1. Clone this project inside your wp-content/plugins directory or you can use wp-env.

  2. npm start.

  3. npm run compile - This will compile the block.mitosis.js component to both React and a Liquid template and place them in src/_generated/. You'll have to run this manually after every change to block.mitosis.js.

If you'd like to see the server rendered output, you can toggle the request blocking in your browser's DevTools like:

Screen Shot 2021-12-08 at 13 31 16

Where to go from here

Even though this repo was created with @wordpress/create-block, there is no reason why we could not generate files on the fly in the same way as Blocky does. This way, we could define our block with just a plain block.json file and a block.mitosis.js file and the rest could be generated dynamically.

I think it would also be interesting to be able to provide custom "loaders" in PHP, which could be a bit similar to getServerSideProps() in Next.js or Loaders in Remix.

Of course, this would not provide any additional functionality but rather simplify creation of blocks by requiring only the following files to create a block:

  • block.json
  • block.js - in the Mitosis format, or whaterver other format we might finally settle on.
  • loader.php - the file that defines a single "loader" function which has to return props in a JSON format. Under the hood, this function is used on the server side to pass the props to the generated template.

I could imagine that while for now those "loaders" would return JSON, they could also in the future return React Server Components!

Q&A

Could it work with frameworks other than React?

Yup, Mitosis could output code for Vue, Svelte, Solid and a couple other frameworks.

Ok, this is nice, but I'm concerned about javascript bloat. Like, when I create 5 blocks, I will generate 5 bundles and each one of them will include React?

Good point. Currently, each block does its own bundling which means that yes, you would include React 5 times on your page. You could configure webpack to output shared libraries to shared chunks if you are the author of each of the block. However, if you'd like to just use third-party blocks where you don't control the bundling, you're out of luck.

I think the real solution (which is beyond the scope here) would be to output ESM and import maps which has started being discussed in WordPress/gutenberg#36716.

Limitations and weaknesses

  • The compiled output is far from perfect. The generated react component does not actually work out-of-the-box and needs a few search-and-replace regexes in order to run fine (look in the ./compile.sh file). Mitosis also does not generate the correct Liquid tags if we pass a more complex expression to <For each={} /> like e.g. <For each={someObject.items.concat(otherItems)}>.

  • For some reason, Mitosis wants to by default handle state with mobx-react and CSS with Emotion. I see no inherent reason for that, but I'm sure it could be configured to output more vanilla components.

  • Mitosis syntax is meh. The syntax is similar to React but it's not React and it kinda shows. It's definitely a bit more tedious to define your components this way and there are some gotchas, too.

Inspiration

About

An experiment to create Gutenberg blocks using Mitosis and compile them to both a Liquid template and a React component that hydrates the server-rendered HTML.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published