11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.09k stars 494 forks source link

JSON Watch Output #1786

Open Snugug opened 3 years ago

Snugug commented 3 years ago

Is your feature request related to a problem? Please describe. I'm trying to integrate Eleventy with Vite without having Eleventy compile HTML to file during development.

Describe the solution you'd like The ability to use Eleventy programmatically in 1.0 is great, but the watch option only allows for HTML output. I'd like to see JSON output as an option, with an option for the compiled JSON to not be written to disk but instead sent as an argument to an event. I've jury-rigged this in my current plugin by overriding watch and _watch with toJSON() and a custom event instead of write(), but not needing to do this would be great and make maintenance much easier.

Describe alternatives you've considered I tried calling toJSON() from a singleton instance of Eleventy whenever I needed a file compiled, but there appears to be some caching happening somewhere that prevents changes from being properly compiled during long-running tasks; aka it'll work the first time, and compile without error subsequent times, but the output will never differ from the first run. This problem isn't present in watch.

I also abandoned this route because letting Eleventy run the watch and keeping an in-memory cache of the results was better for performance than running 11ty on-demand because there doesn't appear to be a way to run 11ty for a single file and get the expected output; TemplateWriter appears to only be able to produce things like collections correctly if all included files are passed into it, and there's no way to separate file context from just what should be compiled.

Additional context I'm happy to take a swing at writing a PR for this against 1.0. I think it may require an additional command-line option, something --no-output. Alternatively, not writing to disk could be entirely a programatic option, but the --json CLI option would still apply to watch.

zachleat commented 3 years ago

Newer canaries do have a config API method for disabling all template caches, fwiw: https://github.com/11ty/eleventy/blob/d19257350887c9f670f8652039555d9460f69f79/src/UserConfig.js#L670

It is true that TemplateWriter can only build collections from files that are present in the input. I don’t really consider that to be ideal and has other implications for future --incremental support.

You’re absolutely right that programmatic Eleventy watch doesn’t work with JSON outputs. Maybe we should add a prop to Eleventy to set the default output format. And then move this code from cmd.js into Eleventy.js instead: https://github.com/11ty/eleventy/blob/d19257350887c9f670f8652039555d9460f69f79/cmd.js#L120

Snugug commented 3 years ago
Snugug commented 3 years ago

Hey @zachleat! I'm going to have some cycles to look into this soon, and wanted to know if you were OK with me writing a PR to resolve this; I'd love to see this get into 1.0

ghost commented 2 years ago

@Snugug Ah yes been meaning to ask about this! Working on a similar 11ty + Vite project called Slinkity (which brings Astro-like capabilities via shortcodes). Hasn't been fun maintaining a 2 step build process with 11ty writing all HTML files to the file system. Curious what your approach to event emitters has been or what PR you're planning to make 👀

Snugug commented 2 years ago

Hey @Holben888! I wrote https://github.com/Snugug/vite-plugin-eleventy to deal with that; I patch 11ty 1.0 to include a JSON output and use that to store an in-memory cache. Lots of great energy around Slinkity (I stalk Discord 😝 ) and would be more than happy to work with you to make sure that plugin works with it.

ghost commented 2 years ago

Thanks @Snugug! I've checked out that plugin too 😄

Now I will say... I don't think vite-plugin-eleventy would be compatible with our approach to 11ty x Vite integration. There's a fundamental difference here: vite-plugin-eleventy attaches eleventy Vite's existing dev server, while Slinkity attaches Vite to 11ty's existing dev server.

Core reason for this difference: we want control over Vite's server rendering / prerendering. Vite's SSR setup requires us to bring our own server and integrate Vite's live reloaders, so integrating into Vite's out-of-the-box dev server wouldn't give us all the features we want. But approaching things 11ty first, we were happy to find that Vite can attach itself to 11ty's existing browsersync server as middleware! This means 11ty devs can keep using the development experience they're already use to, with Vite's fast reloading and HMR as an added bonus. This 11ty-first-Vite-second mindset also let us pull off component shortcodes for easily embedding clientside JS (and SSR!) for your component framework of choice.

That said, I will absolutely look into your approach to using 11ty in-memory! Curious what lessons we can learn from vite-plugin-eleventy, even if we don't end up using that plugin directly.