Hi, I'm trying to move our team to web components, but I got this problem - all paths inside a template and style should be absolute, so if I move component around or decide to put it on server it stops working.
e.g. having such component test-hi.html
<template>
<link rel="stylesheet" href="./test-hi.css"> <!-- THIS RELATIVE PATH WON't WORK -->
<p>Hello <span id="name"></span>!</p>
</template>
<script src="./test-hi.js"></script> <!-- this relative path works because it is part of a component document which has correct baseURI -->
and script test-hi.js
const innerDocument = document.currentScript.ownerDocument; // We need a link to a component's document to be able to query for a template
class TestHi extends HTMLElement {
static get observedAttributes() {
return [ 'name' ];
}
get name() {
return this._name;
}
set name(val) {
this._name = val;
this.setAttribute('name', this.name);
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
// However it still works with webcomponents.js polyfill in Safari (just document.querySelector, relative paths are broken as well)
const { content } = innerDocument.querySelector('template'); // document.querySelector('template') will return template from root document or null, but not component template
const instance = content.cloneNode(true); // instance will have baseURI equals to root document baseURI rather then component's document baseURI so all relative paths will be broken
this.shadowRoot.appendChild(instance);
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'name': {
const nameField = this.shadowRoot.querySelector('#name');
if (nameField) nameField.textContent = newValue;
break;
}
}
}
}
window.customElements.define('test-hi', TestHi);
And importing it like this
<link rel="import" href="/test-hi/test-hi.html"> <!-- here should be absolute path to the component from the project root -->
I will have problems with loading correct styles (same for images and all resources with relative paths).
But as component suppose to be independent and may be put in different places or even servers it is not possible to specify absolute (from the main project root) paths.
Well it is possible to parse CSS and DOM inside component's constructor and correct all relative paths to absolute ones, or alternatively put everything together into single HTML template, but there should be more elegant solution.
Please share it if you know it.