I am looking for a clean solution to split web components into JS, HTML and CSS files and host them on a CDN. I try to avoid the webpack html and css-loader as they dont allow me to export my web component as a plain ES module.
The goal is to use a web component from any frontend app just by importing it from a spcified URL. Thereby seperation of concerns should be preserved. Individual files for style, markup and logic also allow for syntax highlighting.
In a local dev environment I found the following to work great:
WebComponent.js:
export default class WebComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const style = new CSSStyleSheet();
const template = document.createElement("template");
fetch("./WebComponent.css").then((res) =>
res.text().then((css) => {
style.replaceSync(css);
this.shadowRoot.adoptedStyleSheets = [style];
})
);
fetch("./WebComponent.html").then((res) =>
res.text().then((html) => {
template.innerHTML = html;
this.shadowRoot.appendChild(template.content.cloneNode(true));
})
);
}
}
WebComponent.css:
button {
/* Some styling */
}
WebComponent.html:
<button>Custom buttom</button>
I can import the component by using browser native ES module imports:
index.html:
<!DOCTYPE html>
<html>
<body>
<web-component></web-component>
<script type="module">
import WebComponent from "./WebComponent";
customElements.define("web-component", WebComponent);
</script>
</body>
</html>
This works until I move the web component files to a different location (a google cloud storage bucket) than my index.html and import WebComponent.js from there.
<!DOCTYPE html>
<html>
<body>
<web-component></web-component>
<script type="module">
import WebComponent from "https://storage.googleapis.com/storage-bucket/WebComponent.js";
customElements.define("web-component", WebComponent);
</script>
</body>
</html>
WebComponent.js gets imported correctly but it then tries to fetch WebComponent.css and WebComponent.html from a URL relative to localhost where index.html is served. However it should fetch from a URL relative to where it is hosted (https://storage.googleapis.com/storage-bucket/).
Any ideas how something like that can be achieved? Without hard coding the url into both fetch calls. That's not an option as the url can change automatically from time to time.