netzo / fresh-netzo

Full-stack Deno Fresh meta-framework for building business web apps like internal tools, dashboards, admin panels and automated workflows.
https://netzo.io
MIT License
51 stars 3 forks source link

[plugins/unocss] `presetUno` significantly slows down CSR hydration #172

Open miguelrk opened 7 months ago

miguelrk commented 7 months ago

TLDR: enabling CSR mode will significantly slow-down hydration due primarily to the presetUno preset included by the presetNetzo preset (same goes for presetMini()). At first is was though that this was due to the presetNetzo including the entire MDI icons collection, which is then base64-encoded to be loaded as an ESM import in the plugin's entrypoint script which initializes the unocss runtime, but the huge icons bundle is not the issue, but simply the presetUno itself, which somewhow slows the unocss' runtime init() function from ~500ms to ~30s.

Workaround

The current workaround is to simply delete the @unocss/preset-uno registration before setting the window.__unocss = config; (note that this registration could be several levels deep, within other presets).

import config from "data:application/javascript;base64,${
  btoa(Deno.readTextFileSync(configURL))
}";
import initUnocssRuntime from "https://esm.sh/@unocss/runtime@0.59.0";

// IMPORTANT: removes the uno-preset to avoid ~30s slow-down in hydration for CSR
const SKIP = ["@unocss/preset-uno"];
config.presets?.forEach((p, i) => {
  if (SKIP.includes(p.name)) delete config.presets[i];
  config.presets?.[i]?.presets?.forEach((p, j) => {
    if (SKIP.includes(p.name)) delete config.presets[i].presets[j];
  });
});
export default function() {
  globalThis.__unocss = config;
  initUnocssRuntime();
}

Additionally, the "safelist" property is used in presetNetzo to force-include all dynamically injected classes for components which mount/unmount dynamically (e.g. dialogs, sheets) so that these also work (more or less) despite having CSR disabled. Additional dynamic classes can always be included in the "safelist" of the uno.config file as well. This way, netzo/components can be used without having to enable CSR mode for the netzo.unocss plugin, thus avoiding slowing down hydration.

The lists of classes required by each dynamic shadcn component was generated with the following GPT prompt:

"List all unique classNames in an array[] format fot the tsx file: <FILE>"

Alternatives

We could also try running the unocss runtime off the main thread via partytown, however, we couldn't get that to work easily despite an existing fresh plugin for partytown.