11ty / eleventy-plugin-webc

Adds support for WebC *.webc files to Eleventy
https://www.11ty.dev/docs/languages/webc/
120 stars 10 forks source link

`getCss` doesn't bundle styles from component when using nested layouts #33

Closed rijkvanzanten closed 2 years ago

rijkvanzanten commented 2 years ago

I have a single root.webc layout that defines the <head>, and uses @raw to render just the body:

<!doctype html>
<html>
  <head>
    <!-- other meta tags / links -->
    <style @raw="getCss(page.url)"></style>
  </head>
  <body @raw="content"></body>
</html>

When using this layout directly from a page, the styles of components are correctly bundled to the <style> tag in the head. However, when I use a nested layout, like a home.webc which in turn uses the root layout like:

---
layout: root.webc
---

<header>...</header>

<main @raw="content"></main>

<my-styled-webc-component></my-styled-webc-component>

<footer>...</footer>

styles of the styled webc component aren't bundled to the head anymore, but are instead left nested under the components tag.

Reproduction

See https://github.com/rijkvanzanten/webc-style-bundle-repro

andybluntish commented 2 years ago

I have also run into this, and wanted to add that, in my experience:

  1. this also effects scripts/getJS, as well as styles/getCss
  2. this only applies to the assets in the nested layout itself, i.e.
    1. assets from pages (or components on the page) are bundled correctly
    2. assets from the nested layout (or components in that layout) are not bundled correctly, but included inline

This is using @11ty/eleventy@2.0.0-canary.18, and @11ty/eleventy-plugin-webc@0.7.0. Keen to hear if others are experiencing the same thing.

oliverjam commented 2 years ago

Yeah I'm hitting this too. As far as I can tell bundling assets just doesn't work at all for components rendered in a layout. Even the workaround of nesting layouts suggested in #11 appears to not work any more.

awmottaz commented 2 years ago

This seems to be intentional:

https://github.com/11ty/eleventy-plugin-webc/blob/51e00ae37f27c0b65535a61b92de47f9306e2c63/src/incremental.js#L26-L31

This behavior makes a lot of sense, because otherwise if the bundler mode is always enabled, this line in your layout component will be swallowed by the asset bundler:

<style @raw="getCss(page.url)"></style>

But as we've seen, this also means all other asset bundling is disabled from layout components.

On the other hand... isn't this what webc:keep is for?

<style webc:keep @raw="getCss(page.url)"></style>

IMO, this fits my mental model of how asset bundling works: all <style> and <script> tags are swallowed by the bundler, except when you webc:keep them. And the webc:keep'd tags are where you need to dump your bundled stuff.

Proposal: Set page.setBundlerMode(true) for all pages, including layouts, and adopt webc:keep as The Way™️ to render your bundled styles/scripts.

oliverjam commented 2 years ago

I like that proposal. One caveat is that assets in the root layout still don't get included in the <style webc:keep>. I assume because the HTML gets serialized at the same time the assets are bundled, so there's no final render where the layout would have access to these at the moment.

https://github.com/11ty/eleventy-plugin-webc/blob/51e00ae37f27c0b65535a61b92de47f9306e2c63/src/eleventyWebcTemplate.js#L148-L150

awmottaz commented 2 years ago

Ah, that's right. I suppose you might otherwise introduce an infinite loop if you didn't webc:keep the <style> tag where you dump the bundled styles. I can't think of a good way around that 😅

My proposal would at least reinstate a variation of the previous workaround by nesting layouts.

@zachleat I'm curious what your thoughts are on this!

zachleat commented 2 years ago

I’ve got a good workaround going involving a two pass compile render (limited only to top-most Eleventy layouts that have JS/CSS assets).

I also agree with the proposal @awmottaz listed above https://github.com/11ty/eleventy-plugin-webc/issues/33#issuecomment-1333093345

We’ll set bundler mode on for everything as a breaking change here in WebC v0.8.0.

zachleat commented 2 years ago

Shipping this with Eleventy WebC v0.8.0 (likely Monday)

zachleat commented 1 year ago

Eleventy WebC v0.8.0 is out! https://github.com/11ty/eleventy-plugin-webc/releases/tag/v0.8.0