11ty / webc

Single File Web Components
MIT License
1.33k stars 39 forks source link

Using npm packages in webc:type="render" templates #59

Closed RobinCsl closed 2 years ago

RobinCsl commented 2 years ago

Hello :wave:

I managed to use @11ty/eleventy-img in a webc:type="render" template by injecting it through a global JavaScript data file. I described the approach in my article Optimize your img tags with Eleventy Image and WebC.

TL;DR:

// _data/Image.js
const Image = require("@11ty/eleventy-img");
module.exports = function() {
  return Image;
}
// _includes/webc/img.webc
<script webc:type="render" webc:is="template">
async function() {
  let metadata = await this.Image(this.src, {
    widths: [300],
    formats: ["avif", "jpeg"],
    outputDir: "_site/img/",
  });

  let imageAttributes = {
    alt: this.alt,
    sizes: '100vw',
    loading: "lazy",
    decoding: "async",
    "webc:raw": true,
  };

  // You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
  return this.Image.generateHTML(metadata, imageAttributes);
}
</script>

After sharing this on Twitter, Zach suggested that we could do without the global data file and require Eleventy Image directly in the img.webc WebC file, in this fashion:

// _includes/webc/img.webc
<script webc:type="render" webc:is="template">
const Image = require("@11ty/eleventy-img");
module.exports = async function() {
    let metadata = await Image(this.src, {
      widths: [300],
      formats: ["avif", "jpeg"],
      outputDir: "_site/img/",
    });

    let imageAttributes = {
      alt: this.alt,
      sizes: '100vw',
      loading: "lazy",
      decoding: "async",
      "webc:raw": true,
    }; 

    // You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
    return Image.generateHTML(metadata, imageAttributes);
  }
}
</script>

However, running this (or other variants, see https://github.com/RobinCsl/11ty-webc-img-demo/pull/1, https://github.com/RobinCsl/11ty-webc-img-demo/pull/2) yields the following error:

$ npx @11ty/eleventy --serve
[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] 1. Having trouble rendering webc template ./index.webc (via TemplateContentRenderError)
[11ty] 2. Error parsing WebC scripted render function (./index.webc): Error: Cannot find module '@11ty/eleventy-img'
[11ty] Require stack:
[11ty] - 
[11ty] 
[11ty] const Image = require("@11ty/eleventy-img");
[11ty] module.exports = async function() {
[11ty]   let metadata = await Image(this.src, {
[11ty]     widths: [300],
[11ty]     formats: ["avif", "jpeg"],
[11ty]     outputDir: "_site/img/",
[11ty]   });
[11ty] 
[11ty]   let imageAttributes = {
[11ty]     alt: this.alt,
[11ty]     sizes: '100vw',
[11ty]     loading: "lazy",
[11ty]     decoding: "async",
[11ty]     "webc:raw": true,
[11ty]   };
[11ty] 
[11ty]   // You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
[11ty]   return Image.generateHTML(metadata, imageAttributes);
[11ty] } (via Error)
[11ty] 
[11ty] Original error stack trace: Error: Error parsing WebC scripted render function (./index.webc): Error: Cannot find module '@11ty/eleventy-img'
[11ty] Require stack:
[11ty] - 
[11ty] 
[11ty] const Image = require("@11ty/eleventy-img");
[11ty] module.exports = async function() {
[11ty]   let metadata = await Image(this.src, {
[11ty]     widths: [300],
[11ty]     formats: ["avif", "jpeg"],
[11ty]     outputDir: "_site/img/",
[11ty]   });
[11ty] 
[11ty]   let imageAttributes = {
[11ty]     alt: this.alt,
[11ty]     sizes: '100vw',
[11ty]     loading: "lazy",
[11ty]     decoding: "async",
[11ty]     "webc:raw": true,
[11ty]   };
[11ty] 
[11ty]   // You bet we throw an error on missing alt in `imageAttributes` (alt="" works okay)
[11ty]   return Image.generateHTML(metadata, imageAttributes);
[11ty] }
[11ty] 
[11ty]     at Function.getModule (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/moduleScript.js:66:10)
[11ty]     at Object.<anonymous> (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:119:26)
[11ty]     at AstSerializer.transformContent (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:723:42)
[11ty]     at AstSerializer.compileNode (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:1061:20)
[11ty]     at AstSerializer.getChildContent (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:579:40)
[11ty]     at AstSerializer.compileNode (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:1181:46)
[11ty]     at async AstSerializer.getChildContent (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:579:29)
[11ty]     at async AstSerializer.compileNode (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:1218:36)
[11ty]     at async AstSerializer.getChildContent (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:579:29)
[11ty]     at async AstSerializer.compileNode (file:///home/robincsl/Repositories/11ty-webc-img-demo/03-final/node_modules/@11ty/webc/src/ast.js:1218:36)
[11ty] Wrote 0 files in 0.32 seconds (v2.0.0-canary.16)

I tried a bit more and you can check the following Stackblitz: https://stackblitz.com/edit/node-7wkdsh?file=_includes/webc/use-node-fs.webc. It seems like import built-in modules like fs or path works fine, it's possible to use __filename and __dirname (which actually corresponds to where the WebC component is being used, rather than the WebC component itself). However, trying to require a package installed in the node_modules folder fails. I tried different combinations and included the error message. Hope that helps!

zachleat commented 2 years ago

Fixed by #60, right?

Thank you!!

RobinCsl commented 2 years ago

Yes indeed! Thank you!