11ty/eleventy

During --serve, WebC components used in Layout files don’t apply new content

mjawn opened this issue · 16 comments

mjawn commented

Operating system

Win10

Eleventy

2.0.1

Describe the bug

When running Eleventy's dev server with --serve, saving a WebC component triggers a build (according to the terminal) but the changes are not reflected in the destination file. This only occurs with nested components. For example, a change to the root index.webc component works, but when you make a change to a component it calls, that change will not.

Reproduction steps

  1. Run 11ty with --serve
  2. Edit a nested WebC component.

Expected behavior

Changes made to a nested component should reflect in the destination

Reproduction URL

https://github.com/mjawn/11ty-serve-webc-test

Screenshots

No response

mjawn commented

It looks like the very first change made to a component after running the server is picked up, but subsequent changes are not, until the layout is saved. Also, saving the layout, even with no changes to it, reliably causes a build that picks up the changes. That's the workaround I'm using for now.

Yeah, this looks like it affects components used in layouts exclusively.

Relevant commits for the fix currently on GitHub: 0d26e57 c9c0b0c

This fix will ship with 2.0.2—thank you!

mjawn commented

Awesome, thank you for the quick fix! Happy to know it was really a defect as part of me was thinking I was doing something wrong. I'm loving WebC so far, thanks for all you do.

@zachleat thank you very much for your quick help, i also noticed this bug. Since i didn't want to wait until you release version v2.0.2, i just updated the changed files from the commits 0d26e57 c9c0b0c manually in node_modules folder.

It works 🎉 but only if I don't use nested layouts. If I use nested layouts, like this for example:

<!-- _layouts/base.webc -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body @raw="content"></body>
</html>
<!-- _layouts/main.webc -->
---
layout: base.webc
---

<site-nav webc:nokeep></site-nav>
<main @raw="content"></main>
<site-footer webc:nokeep></site-footer>

then unfortunately it doesn't work anymore. It would be really helpful for me if this can be fixed as well.

@zachleat i have just noticed something interesting, which may help you...

as a workaround I'm only working in my base.webc layout at the moment. Without restarting the dev server, I created a nested layout and have specified this in my index.webc page. Then I made some changes to my footer which is part of the nested layout, as i said without restarting the dev server. And now, the changes became visible immediately without problems.

Then when I restarted the dev server and changed something in my footer again, nothing happens, the same issue as i reported ealier

@niklasgrewe ah, thank you for that callout—I missed one small thing there, please retest with the latest GitHub version!

ah, thank you for that callout—I missed one small thing there, please retest with the latest GitHub version!

can confirm, it works now 🎉

@zachleat I'm sorry to have to tell you this, but unfortunately the bug has reappeared. As soon as I use nested layouts, the reloading doesn't work anymore, no matter if I use --incremental or not. Just tested this with version v2.0.2-alpha.1

@niklasgrewe yeah, this is a slightly different issue with how npm handles transitive dependencies. Fixed by 11ty/eleventy-plugin-webc@7ce3f8c and 11ty/eleventy-plugin-webc@79f3143 and shipping with eleventy-plugin-webc@0.11.1

Thanks, @zachleat.

That seems to be working much better for me now, using eleventy@2.0.2-alpha.2 and eleventy-plugin-webc@0.11.1, however...

If I have a markdown file that contains a webc component, updates to that component still aren't being applied. My "eleventy.config.js" file returns an object which includes the markdownTemplateEngine: 'webc' property and my site's root "index.md" file looks like this:

---
layout: "base.webc"
---
## Welcome to the website

<ul>
  <li webc:for="page of collections">
    <page-summary :@page="page"></page-summary>
  </li>
</ul>

Changes to the page-summary component aren't applied until the server is restarted.

Admittedly, I could convert this simple example into a webc file (in fact I have, and it worked correctly), but I have lots of other markdown page templates and might want to drop a webc component into these. Is this possible?

@BulletProofPoet please file a new issue! thank you!

New issue: #2924

Not sure if this is still and issue or until the fix is officially release, this may help someone. If using vscode!

Install vscode fileWatcher extension, then add the following code to settings.json. Edit the match: 'value' accordingly, could watch the whole _components directory for better coverage. "src/_includes/_components/.?/[^/]\.webc"

"filewatcher.commands": [
{
"match": "src/_includes/_components/common/[^/]*\.webc",
"isAsync": true,
"cmd": "echo ${fileBasename} 'Changes Saved' && touch ${workspaceRoot}/src/_includes/_layouts/base.webc",
"event": "onFileChange"
}
]

I have common directory for components that get nested in layout files, the 'touch' command simulates a save on base.webc whenever a component in the common directory is changed/saved. Needs to be an absolute path to work hence the use of ${workspaceRoot} making this dynamic for use in other workspaces.

I’d mention using entr in a separate shell is also a cross-platform (non VSCode-specific, cc @nic-nevell) workaround to this issue:

find src/_includes/_components/ -type f -name "*.webc" | entr sh -c 'touch src/_includes/_layouts/base.webc'

# ... of course, replace the source path and layout(s) according to your setup
4lador commented

Thanks @loup-brun, here is what I did to make it work with vite plugin (as vite were reloading the base layout edit before the webc).

Added this script in package.json

"watch:11ty-nested-webc-fix": "find src/_includes/components/ -type f -name \"*.webc\" | entr sh -c 'sleep 0.1; touch src/_includes/layouts/base.webc'"

It works as expected now

EDIT: Hmm nope that's better but I still got the issue with Vite, I will manage to find a way soon

vgpena commented

Playing off the idea of touching layout files to update them, I added this to my .eleventy.js config since I didn't want to specify the layout name. This touches all of the layouts in my project. So far it's working well!

// at top of file
const { exec } = require("child_process");

// within 11ty config export
eleventyConfig.on('eleventy.beforeWatch', (changedFiles) => {
  if (!changedFiles.some((filePath) => filePath.includes('./_layouts'))) {
	  console.log('🤠 Component files updated -- coercing layout reload.')
	  exec('find _layouts/*.webc -type f -exec touch {} +');
  }
});