Transpiling class based web components with babel - javascript

I've a simple web component following the latest web components v1 class syntax, it works great in Chrome and Firefox/Edge (with a polyfill) but I'd like it to run in IE11 so I need to transpile the class. However running it through babel produces code that no longer works in any browser.
Is there any way to generate backwardly compatible web components with the class syntax or is there a preferred way to write web components for maximum compatibility?
Example code -
class TestElement extends HTMLElement {
connectedCallback(){
this.innerHTML = "<div>Testing</div>"
}
}
customElements.define('test-element', TestElement)
Error message when using transpiled code is -
Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

To compile Custom Element classes with Babel, you can use this plugin from Github.
It will use Reflect.construct() instead of new, which is not permitted with HTMLElement objects.

One solution is to use the native-shim available with this polyfill
https://github.com/webcomponents/custom-elements
It's not perfect though, would like to find a cleaner solution.

Related

Packages to verify the re-rendering in es5 components other than "WhyDidYouRender"

Right now I'm using the WhyDidYourender package to verify the component re-rendering but there are few components in my repo that uses es2015. WhyDidYouRender is not working in es2015 components. Seeing below error:
TypeError: Class constructor MyComponent cannot be invoked without 'new'
So need a way to verify the re-rendering for es5 components. Also, tried Chrome highlights to verify the re-rendering, please don't recommend that.
Any help is appreciated, Thanks!
WhyDidYouRender repo link: https://github.com/welldone-software/why-did-you-render
Support the ES6 or not is rely on your Browser. It's more like you trying to use the class but there is no instance to access.
Transpiled to es5 class is available in PR#8656, the whole react class elements are supported to extend with this library. If you transpile your classes by ES5 or ES6, use below code:
// traspiled to es5
const whyDidYouRender = require('#welldone-software/why-did-you-render);
// traspiled to es6
const whyDidYouRender = require('#welldone-software/why-did-you-render/dist/no-classes-transpile/umd/whyDidYouRender.min.js');

Angular elements - Element.createShadowRoot deprecation

I'm testing Anuglar Elements to create some web components and is working great. Anyways I'm getting this warning in console:
[Deprecation] Element.createShadowRoot is deprecated and will be
removed in M73, around March 2019. Please use Element.attachShadow
instead. See https://www.chromestatus.com/features/4507242028072960
for more details.
Related file is platform-browser.js:1182.
Is something I should be aware of? How can i fix it? Should I search an alternative way to create my web components?
According to MDN Web docs this feature is going to be removed completely. In any case it's not supported by most of the web browsers:
Non-standard
This feature is non-standard and is not on a standards
track. Do not use it on production sites facing the Web: it will not
work for every user. There may also be large incompatibilities between
implementations and the behavior may change in the future.
Deprecated
This feature is no longer recommended. Though some browsers
might still support it, it may have already been removed from the
relevant web standards, may be in the process of being dropped, or may
only be kept for compatibility purposes. Avoid using it, and update
existing code if possible; see the compatibility table at the bottom
of this page to guide your decision. Be aware that this feature may
cease to work at any time.
If you're using Angular i'd suggest using Dynamic Component Loader
As the error states you will have to use
Element.attachShadow instead.
Example:
class SomeElement extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = 'Hello World!';
console.log(this.shadowRoot);
}
}
customElements.define('some-element', SomeElement);
The mode defines if you can access the shadow root through JavaScript.
For {mode: 'closed'} the code in the connectedCallback won't work since this.shaodwRoot returns null.

How does the browser know I'm targeting ES6?

I'm using Typescript and I recently changed the transpilation options to target ES6 instead of ES5.
I was using a certain syntax that had always worked fine under ES5, but after the target change, I started getting this error in the (Firefox) browser console:
Javascript ES6 TypeError: Class constructor Client cannot be invoked without 'new'
I changed the code to a suitable syntax for ES6, and this fixed the issue, but I don't understand how the browser would know to throw this error in the first place, because the exact same code worked before.
Does the javascript parser in browser scan other parts of the code base and see they they're using ES6, and then reject this line because it doesn't match the ES6 code elsewhere?
Javascript doesn't enter any particular "mode".
Likely what really happened is that you were declaring a class Client. That is ES6 syntax, and it comes with the special caveat that you must use new Client to instantiate it. Now, your compiler compiled this into a backwards-compatible function Client() .... Obviously, you can call a function without new. And that's what you were doing somewhere.
So, the compilation from class to function masked the error. But when leaving the class as class (because ES6 target mode does not need to dumb it down to a function), the browser was actually dealing with a class and raised that error.

Why is my Cordova Android app throwing a "reserved word" error when defining an object using a class declaration?

My JavaScript app works well in a web browser, but displays an error when running the app on Android using Cordova:
Uncaught SyntaxError: <unknown message reserved_word>
This error is tied to the first line of my class declaration in Javascript, as follows:
class ABC {
constructor() {
...
}
...
someMethod() {
}
}
Could anyone please offer any suggestions about what might be causing this error?
It looks like I am using the word "Class" the way it is intended to be used in JavaScript, per the following reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
This issue had occurred due to the WebView of the browser been v33.0.0.0 in Kitkat which doesn't support the class keyword natively. You can use a transpiler like Babel to make your code compatible with older browsers.

Using third party library TypeScript

I'm new to TypeScript and I'm trying to use a regular library that was written in vanilla JavaScript but I'm getting an error when trying to execute the code.
index.ts:
import OpenSubtitles from 'opensubtitles-api';
new OpenSubtitles;
when trying to node dist/index.js:
new opensubtitles_api_1.default;
TypeError: opensubtitles_api_1.default is not a constructor
edit:
It has nothing to do with the duplicated thread as this one is related to TypeScript and not ES6 itself, and the other thread is talking about old JavaScript syntax compatibility with ES6 but the library I'm trying to link is written in ES6 (using classes and so on, so that is not a duplicated thread).

Categories

Resources