How to build web components custom elements to work with both specs
Asked Answered
N

2

9

I need to build a component that should need to work with both specs, custom elements spec v0 which got deprecated and custom elements spec v1, latest stable version.

If I build components with custom elements v0 spec some apps will face issues since they are using polymer 2 and above and the same problem with polymer 1 applications which will not work with custom elements v1 spec.

I do not have control over applications to change polyfills, some applications have to use polyfills supports old spec and some uses new polyfills.

I am looking for a solid solution to combine both the specs to run my custom elements in all the applications irrespective of polyfills version. I can add any piece of polyfill or snippet to my components so that they can run anywhere, I have not found any such library or polyfill which support both specs in my research.

I am planning to write an adapter that can combine both the specs like mapping mentioned below for attached callback, inputs on this thought will be much appreciated.

connectedCallback(){
    this.attachedCallback();
}

I tried to use stenciljs but it can work only with the latest version of custom elements spec. I have not found any way to tweak it to make it work with earlier spec.

Please suggest some viable alternatives and feasible solutions to the above-mentioned situation.

Nootka answered 9/10, 2019 at 6:39 Comment(1)
V0 and V1 are 2 distinct technologies; if you are asking for a meta language that runs both (since in the commments below you do not want to maintain 2 code bases), there is none. V0 and V1 are like coal and petrol... or petrol and battery power if you are a Tesla fan... no engine runs on bothKippar
O
1

Basically your component has some dependencies which are defined in the polyfills either directly, or indirectly. If we consider these dependencies as nodes of a dependency graph, then we have the problem of the graphs being different. It's possible that a node exists in both graphs, but behaving different (older and newer implementation of the same function) and it's also possible that some nodes which are present in a graph are missing in another one. You can of course put in some polyfills of your own or something of the like, but then you would need to maintain polyfills, which might be less than helpful.

A better approach in my opinion is to implement a function, like

function getWebComponentsVersion() {
    //Return v1 if it's v1 and v0 if it's v0
}

I'm not sure how to implement this function, but if there is either a function which yields the proper version, or some evident differences between functionalities, then you can implement the function above accordingly. And then, run this code:

if (getWebComponentsVersion() === "v1") {
    //code for v1
} else {
    //code for v0
}
Overcheck answered 16/10, 2019 at 16:50 Comment(2)
thanks for your answer, in this case I need to maintain two versions of component code which would be a pain while adding features and in long term fixing issues would become hectic process.Nootka
@KongaRaju that's a drawback indeed, but if you manage to narrow down the version-specific problem space and widen the area of code which can be applied to both versions, then you might find this problem less disturbing than you might think at first glance.Overcheck
M
-1

I suspect you are aware that Custom Elements v0 is deprecated at M70, and will be removed in M80, by February, 2020..

What you could do is to go to Can I use website and check the browser support versions to see which browser should load which custom elements version...

Afterwards implement the below to check the browser and version and load correct custom element for desired browser accordingly (more here) if you don't want to use external libraries.

If you are ok with using external libraries try Bowser to detect version, platform etc.

navigator.browserSpecs = (function(){
    var ua = navigator.userAgent, tem, 
        M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
    if(/trident/i.test(M[1])){
        tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
        return {name:'IE',version:(tem[1] || '')};
    }
    if(M[1]=== 'Chrome'){
        tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
        if(tem != null) return {name:tem[1].replace('OPR', 'Opera'),version:tem[2]};
    }
    M = M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
    if((tem = ua.match(/version\/(\d+)/i))!= null)
        M.splice(1, 1, tem[1]);
    return {name:M[0], version:M[1]};
})();

console.log(navigator.browserSpecs); //Object { name: "Firefox", version: "42" }

if (navigator.browserSpecs.name == 'Chrome') {
    // Do something for Chrome.
    if (navigator.browserSpecs.version > 76) {
        // Do something for Chrome versions greater than 76 like load v1.
    }
}
else {
    // Do something for all other browsers.
}
Menashem answered 17/10, 2019 at 8:5 Comment(2)
First of all, thank you for your answer. The real problem lies in building a component once you detect the browser version? Adding a check to detect the browser version would be an extra step.Nootka
Seems I went to far in assumptions - my idea above was to build 2 separate components and load in appropriate browsers.Menashem

© 2022 - 2024 — McMap. All rights reserved.