Web Component Paths Root

I create a web component using my own implementation, in which the html template has links to images. However, these links only work if they are absolute or relative to the main document, which means that this component cannot be reused or transferred. In addition, it is very controversial.

I am currently adding the data-url_prefix attribute to all elements that should use images. Then, creating a shadow root for my custom item, I replaced {{URL_PREFIX}} with the value of this argument.

My decision seems very bad. I would be very happy if you would recommend something better, thanks.


I found an interesting quote at http://webcomponents.org/polyfills/html-imports/ :

POLYFILL NOTES

In imported documents, the href and src attributes in the HTML and the URL of the property in the CSS files refer to the location of the imported document, not the main document.

why does a polyfill use different logic to make a native implementation?


Web components Ideally, they should encapsulate all their dependencies, but if the web component requires an image, it should know the absolute URL of this image, which does not allow you to simply move the component in the file structure.

Say, for example, I have the following structure:

  • index.html
  • CSS
    • main.css
  • Js
    • main.js
  • web_components
    • cool_web_component
      • cool_web_component.html
      • icon.png

If I changed it to the following:

  • index.html
  • CSS
    • main.css
  • Js
    • main.js
  • cool_web_component
    • cool_web_component.html
    • icon.png

I will need to change the pointer to icon.png somewhere in these files. My question is how to avoid this, or solve it in an elegant way. Also, why is the actual native implementation in conflict with the poly-regiments?

+10
javascript html polymer custom-element web-component
source share
3 answers

The web component specification defines that URLs always refer to the main document. This, of course, violates the encapsulation of web components, as you correctly concluded. In other words, the specification is wrong, and many people complain about it. This is why the polyfill is out of specification: it fixes the problem.

The specification will change. However, since this is not so difficult, it may take some time. See the following links:

โ€ข https://lists.w3.org/Archives/Public/public-webapps/2014OctDec/0013.html

โ€ข https://www.w3.org/Bugs/Public/show_bug.cgi?id=20976#c8

At this point, the solution is for your component to change the URL of its template images from absolute. You can get templateBaseUrl as follows:

 (function (window, document) { var proto = Object.create(HTMLElement.prototype); var template = document.currentScript.ownerDocument.querySelector("template"); var templateBaseUrl = template.baseURI; proto.createdCallback = function () { // Now find all images inside the template and change their src attribute, // using templateBaseUrl. Also you must change CSS background-image: url(...); ... }; document.registerElement('test-element', {prototype: proto}); })(window, document); 

Another way to resolve this with small images, such as icons, is to embed image data directly in the document using data URIs . This also saves HTTP requests (we don't have Http / 2 yet). For example:

 <img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" /> 
+5
source share

This behavior appears to be image specific.
For script and link tags, relative paths from the imported document work as expected.

I also noticed that this is not something specific for poly regiments, even for my own implementation (chrome) this problem (?) Seems to exist.

It seems that the only option is to include the script in the imported html, which will convert these relative paths to their absolute copies.
To make this convenient, you can avoid hardcoding URLs in your script and generate it using the URL of your importing document. You can get this from document.currentScript.ownerDocument (or document._currentScript.ownerDocument in a multi-task script).

So, to answer your second question, I see no difference in the native and multitask implementation, at least in terms of the behavior of the src and href attributes.
The quote you mentioned from http://webcomponents.org/polyfills/html-imports/ seems to be specific to the href / src script and binds the tags and they work as they are written.

Hope this helps.

+1
source share

The reaction to my own previous comment on MarcG's answer - the need for the modules to know their own path, has become widely accepted, and is currently available through import.meta.url !

So now itโ€™s much easier to write a utility to extract the HTML / CSS component.

Also, if CSS is NOT retrieved, but a new link to the stylesheet is dynamically added to the document, this CSS also works very well with relative paths.

Having this, today, expecting some standard way to point my base reference to the component, my approach is to provide component 2 with resources:

  • The main / only HTML is extracted through the fetch API, converted to a template, cached, and then cloned into the component each time its new instance is attached to the DOM
  • Basic CSS linked by a standard link element
  • the names of these 2 coincide with the names of the main JS file that provides the component class, which simplifies turning this whole mess into a utility with a dozen lines
  • additional CSS resources, if necessary, are added as regular relative import into the main CSS
  • images, if possible, are added as background URLs using relative imports
  • obviously no more than a separate HTML resource
0
source share

All Articles