Closed rjcorwin closed 5 years ago
Is it being compiled to es5 without adding the custom-elements-es5-adapter.js file?
@jsilvermist Good idea! Unfortunately, after adding it the same error persists.
@rjsteinert The import
s you specified are not loaded at all. E.g. the webcomponents-loader
as well as the adapter are never actually executed. You can see this by opening the website in Firefox, it will break.
Now, I tried to add the loader and adapter to index.html
, but your node_modules/
are not in src/
, so I was unable to load them via a script tag. I don't think the loader is compatible with ES modules. It has to be loaded via script tag.
@TimvdLippe I found a ticket relared to ES modules in the webcomponentjs issue queue https://github.com/webcomponents/webcomponentsjs/issues/882
This not working in Firefox is definitely a concern and as you said related to the polyfills not loading. Does Chrome need the polyfills to make this work? I'm assuming not, and if that's the case then I wonder what is up with this error Class constructor LitElement cannot be invoked without 'new'
.
@rjsteinert Chrome does not need the polyfill, but does require the adapter to be loaded. When I ran your project, I did not see the adapter being loaded. Therefore it would break in Chrome, as Chrome requires the adapter to be loaded if you define your custom elements in ES5.
I'm getting the same error with the custom-elements-es5-adapter
script loaded. I am trying to get lit-element working with Elm:
Same behavior with create-react-app
.
index.html:
<head>
<script src="./webcomponents-bundle.js"></script>
</head>
...
App.js:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {LitElement, html} from '@polymer/lit-element';
class MyElement extends LitElement {
static get properties() { return { mood: String }}
_render({mood}) {
return html`<style> .mood { color: green; } </style>
Web Components are <span class="mood">${mood}</span>!`;
}
}
customElements.define('my-element', MyElement);
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<my-element/>
</div>
);
}
}
export default App;
same here,
building a pure vanilla/lit-element project, transpiled with Babel 6 (with preset env
defaults) adding the custom-elements-es5-adapter
before the polyfill results in:
Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'
it seems like the adapter is not... adapting.
I'm also using code-splitting via Webpack but trying to going back to single-bundle-file didn't changed the result.
any clue about this? thanks
Related to Polymer/tools#398
From what I can tell, the issue is years-old in Babel, and is a bug preventing the usage of extended native classes without new
. So not really sure if this is a Polymer problem, so much as Babel.
Hey @rjsteinert,
do you need it to be downtranspiled to ES5? I changed my tsconfig.json
to target ES2015
and then using the polyfill without the adapter works. You can see an example here: https://github.com/dkundel/vote-my-talk/commit/8b7f29a2993076b05582914b594b9500d67d919b
Cheeers, Dominik
I experienced the same error when transpiling using webpack and babel-preset-env. And after a few hours of trying, using es2017 works for me.
npm install --save-dev babel-preset-es2017
then change the option in your webpack configuration to es2017
options: {
presets: ['es2017']
}
or in .babelrc
{
"presets": ["es2017"]
}
Fixed with babel/babel#8501 and included in Babel 7 release, so the issue can be closed. See https://github.com/web-padawan/polymer3-webpack-starter for proper config.
@dkundel Changing Agnular's tsconfig.json
target property to es2015
did the trick for Chrome, however Firefox has a strange error white screen of death now. Perhaps the babel fix that @web-padawan mentioned will make it into an angular-cli release sometime soon and all our problems will be solved? I was trying this on a fresh angular-cli install/fresh project.
What is the real resolution to this? So much confusion across the issues.
I’m assuming the new Babel update will fix this.
Waiting on support Babel 7 in Parcel, haha. Until then, I guess you could use Webpack?
I am already on Webpack actually :/
The 7.0.0 stable release of Babel works properly as I mentioned above. You can also find a config example here: https://github.com/web-padawan/lit-components
Thanks @web-padawan, that was helpful. I wasn't willing to let go of "preset-env" just yet.
In summary, the issue is... ES6 classes must only be called with new
on instantiation. Transpiling to ES5 will not solve this issue. So one must also include custom-elements-es5-adapter.js
somewhere to resolve that.
A suggested strategy is to have separate babel builds:
1) Targets modern browsers with ES6 class support (e.g. { targets: { chrome: 60 }}
)
2) Targets IE11 with ES5 support + custom-elements-es5-adapter.js
Then in production server needs to figure out whether to serve 1 or 2, which is admittedly more complexity. (Or just tell your customers to download Chrome)
For now I'll go with 1 and configure 2 later.
@ernsheong if you’re interested in a world that combines 1 and 2 while making sure that users on each side get the best code for them, you might be interested in something like https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ It’s looking really good for the applications I’m working on, which use polymer build
to output multiple builds, but the webpack approach in the blog post looks useful if you’re into it and should be portable in some way to Rollup, etc as needed, not that I know that from experience.
@Westbrook thanks for sharing the article, definitely looks promising (and more doable)! I like this other article from the same author too: https://philipwalton.com/articles/loading-polyfills-only-when-needed/ (from which I got the idea of punishing older browsers rather than newer ones)
Hi, I'm trying to display LitElement components using storybook.
counter-element
component that exists in the pwa-starter-kit:
import { storiesOf } from '@storybook/html';
import './counter-element';
storiesOf('CounterElement', module)
.add('default', () => <counter-element clicks="3" 1alue="1"></counter-element>
);
But then I got the error `Class constructor LitElement cannot be invoked without 'new'` when trying to display the component.
I have read the discussion above, but I don't know I still got that issue.
Does someone know what is missing ?
(I haven't load the polyfills since I'm testing on Chrome 69)
@tonai I'm using LitElement & Storybook with @storybook/polymer
and it's going fine, had some issue with LitElement and @storybook/html
.
@moebiusmania What version of @storybook/polymer
do you use ?
I just switch my above story using @storybook/polymer
(v4.0.7) and still have the same issue.
My storybook config file .storybook/config.js
looks like this:
import { configure } from '@storybook/polymer';
const req = require.context('../src', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach((filename) => req(filename))
}
configure(loadStories, module);
I also tried to initialize the storybook using the cli npx -p @storybook/cli sb init
but still the same error...
@tonai 4.0.2, you can check it out here https://github.com/bitrockteam/amber-components , hope it helps.
Ok thanks to @moebiusmania it finally works.
I works whenI use components with typescript and the following tscongif.json
file (the same as the one in the @moebiusmania repository):
{
"compilerOptions": {
"target": "esnext",
"allowJs": true,
"allowSyntheticDefaultImports": true,
"module": "es6",
"experimentalDecorators": true,
"moduleResolution": "node"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
Is there a special webpack config to use, or something, to make it works with js files ?
@tonai here is the example of the proper babel-loader
config.
In case you don't use Polymer legacy (especially custom-style
), you can leave it like this:
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules\/(?!(lit-html|@polymer)\/).*/,
options: {
cacheDirectory: true
}
}
Ok it's fixed ! Thanks @web-padawan your comment sent me in the right direction.
Storybook comes with its own webpack configuration and at the beginning I was not seeing what was wrong in it. It finaly appear that the important part is the exclude section.
So I have added this rule in the storybook configuration by adding a .storybook/webpack.config.js
file in my project with:
module.exports = (baseConfig, env, config) => {
config.module.rules[0].exclude = /node_modules\/(?!(lit-html|@polymer)\/).*/;
return config;
};
And it finally worked !... for the counter-element
but not for my other components.
In my other components I am using the connect
helper for Redux.
So I updated the RegExp to: /node_modules\/(?!(lit-html|@polymer|pwa-helpers)\/).*/
And now it's completly operationnal ! :metal: :metal: :metal:
@web-padawan in the polymer3-webpack-starter and lit-components projects, the RegExp seems to be more complete : /node_modules\/(?!(@webcomponents\/shadycss|lit-html|@polymer|@vaadin|@lit)\/).*/
Do you think the @webcomponents\/shadycss
, @vaadin
and @lit
parts may be needed in my case ?
(I intend to create an issue on the storybook project to add this exclude
part, but I wonder if I'm not forgetting something.)
Thanks
@tonai @webcomponents\/shadycss
can only be needed because of the import of these lines:
https://github.com/Polymer/polymer/blob/655a64640bfacfa25480d950d1c8092c3fcf9571/lib/elements/custom-style.js#L10
So, if you don't use <custom-style>
element, or the Polymer legacy code, you can remove it.
Regarding @vaadin
, in case you depend on some of Vaadin components, you should keep it. Otherwise, it is not needed. Same applies to e.g. @material
for Material Web Components.
Thank you @web-padawan for the clarification.
I get this error when targeting es5 in a typescript project. I created a simple typescript project to demonstrate the issue.
git clone https://github.com/daniel-nagy/lit-element-test.git && cd lit-element-test
npm install
npm run start
Once Webpack is done you can visit http://localhost:5000 and you will see this error in the browser's console.
If you change the target to es2015 and restart the Webpack server the error will go away.
{
"compilerOptions": {
"experimentalDecorators": true,
"lib": ["dom", "es2017"],
"moduleResolution": "node",
"sourceMap": true,
"strict": true,
- "target": "es5"
+ "target": "es2015"
}
}
Browsers tested
Chrome: 71.0.3578.80 Safari: 12.0.1 Firefox: 62.0.2, 63.0.3
Closing as the issues here seem to have been addressed.
@sorvell how has this been addressed? Are you saying lit-element is limited to browsers that support es2015?
Interestingly enough, I got Uncaught TypeError: Class constructor cannot be invoked without 'new'
when I ran npm install
for a local Vaadin component, which symlinks the directory.
webpack.config.js
required resolve.symlinks: false
and things started working.
To anyone else that ends up here, lit-element is distributed as es2015 so you must transpile it to es5 as part of your build process. If you're using Webpack add the following to your JavaScript rule:
{
include: [
// These packages are distributed as es2015 modules, therefore they need
// to be transpiled to es5.
/node_modules(?:\/|\\)lit-element|lit-html/
]
}
To anyone else that ends up here, lit-element is distributed as es2015 so you must transpile it to es5 as part of your build process.
Note, this is only true if you're targeting older browsers like IE11. All modern browsers support classes. Most modern JS, and definitely LitElement & lit-html, will run faster if you send ES6+ to browsers.
If you are seeing this error, you are likely in need of two important babel plugins. Additionally if you have ES6 code inside node_modules you MUST include them in your babel loader. LitElement library itself is ES6.
I was having this issue with Gatsby. Gatsby 2 by default includes code from all node_modules so all I had to do was
Install these modules and add this to my .babelrc, the order is important.
"plugins": [
["@babel/plugin-proposal-class-properties", { "loose": true }],
["@babel/plugin-transform-classes", {"loose": true}]
]
For Gatsby, I did this by following the instructions at https://www.gatsbyjs.org/docs/babel/#how-to-use-a-custom-babelrc-file
To anyone else that ends up here, lit-element is distributed as es2015 so you must transpile it to es5 as part of your build process. If you're using Webpack add the following to your JavaScript rule:
{ include: [ // These packages are distributed as es2015 modules, therefore they need // to be transpiled to es5. /node_modules(?:\/|\\)lit-element|lit-html/ ] }
It solves the problem for me, but for some reason it prevents arrow functions from being transpiled. In other words, arrow syntax is not replaced neither in lit-element
package nor in my app code.
Here's a snippet from package.json
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"babel-loader": "^8.0.5",
If you are seeing this error, you are likely in need of two important babel plugins. Additionally if you have ES6 code inside node_modules you MUST include them in your babel loader. LitElement library itself is ES6.
I was having this issue with Gatsby. Gatsby 2 by default includes code from all node_modules so all I had to do was
Install these modules and add this to my .babelrc, the order is important.
"plugins": [ ["@babel/plugin-proposal-class-properties", { "loose": true }], ["@babel/plugin-transform-classes", {"loose": true}] ]
For Gatsby, I did this by following the instructions at https://www.gatsbyjs.org/docs/babel/#how-to-use-a-custom-babelrc-file
THIS works, and the problem happens even on Chrome 75. So I don't see why this isn't included by default.
@mihaisavezi Included where by default?
Has anyone solved this issue yet?
I have tried everything in this thread and I'm still seeing this error in Chrome if I transpile my LitElements down to ES5 even when the custom-elements-es5-adapter.js
is loaded.
I tried @Manidos 's Webpack config:
{
include: [
// These packages are distributed as es2015 modules, therefore they need
// to be transpiled to es5.
/node_modules(?:\/|\\)lit-element|lit-html/
]
}
and the error goes away in Chrome. But upon further inspection I believe that's because the include
statement means the only things that will be transpiled are lit-element and lit-html within node_modules. This means that none of the actual LitElement component definitions within my application are transpiled, thus they work just fine in Chrome.
If you rewrite the config to the following:
exclude: /node_modules\/(?!(lit-element|lit-html)\/).*/
it will exclude all node modules except lit-element and lit-html. In this case, the LitElement component definitions in the app are still transpiled, and the error persists.
I have tried including the es5-adapter
in JavaScript as an import in my webpack entry file as well as in my HTML as a script tag but it doesn't seem like the adapter works at all. I know the adapter is being loaded because when I inspect the HTMLElement property of window I see that it has been modified:
@web-padawan do you think this is a Babel issue again?
I am using the following config:
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/preset-env": "^7.6.3",
"babel-loader": "^8.0.6",
"webpack": "^4.41.1",
"webpack-cli": "^3.3.9"
}
and my .babelrc is as follows:
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"debug": true
}
]
]
}
Any guidance would be greatly appreciated. I have enjoyed my experience with LitElement so far and would really like to adopt it into some of my projects. I am currently just excluding the LitElements from my babel-loader in order to continue building, but I would love to put this issue to bed because at some point I will need to properly support IE11.
@n-devr consider using webpack-babel-multi-target-plugin which outputs ES module bundle + ES5 "nomodule" bundle for legacy browsers. We are using it and it works nice.
Thanks for your reply @web-padawan - I did see that solution referenced in other issues and even found the open-wc compatibility docs as well. The concept sounds great and I like the idea of reducing the bundle size for modern browsers, but with the useBuiltIns
option of babel working for me I am not adding much weight to my bundle size by transpiling down to ES5 and I'd much prefer to keep my Webpack config on the simpler side. Is there no way to use the es5-adapter
to accomplish this without having to produce multiple bundles?
I'm happy to create a new repo to isolate the problem and make a new issue for it if that would help. It might also save people some time to know that it's not a viable option.
@n-devr you only need ES5 adapter if you transpile to ES5. Otherwise, you should not include it.
Also, you can set esmodules
target for @babel/preset-env
:
https://babeljs.io/docs/en/babel-preset-env#targetsesmodules
Regarding useBuiltIns
, I haven't tried how it works with corejs
3.
But AFAIK it should not affect custom elements classes when they aren't transpiled.
Thanks for your time and quick reply @web-padawan !
My goal is to have a single bundle transpiled to ES5 that I serve to all browsers. Sorry if the useBuiltIns
piece confused the matter, I was trying to explain that I wouldn't see much benefit in serving separate modern and legacy bundles because the bundle sizes would be almost the same size. I believe I am bundling and transpiling everything correctly, and my LitElements are rendering just fine when I transpile them except when I try to view them in Chrome. I am including the es5-adapter
in that case but I don't think it is working properly. Is that use case simply not supported by LitElement any more?
@n-devr Sir Did you found any solution? with webpack targeting ie 11?
@sdyalor my issue is not the IE11 support in and of itself - if you use the webpack and babel config I referenced above you should be able to generate a bundle that is transpiled down to ES5 and works in IE11. Unfortunately, that same bundle does not work in Chrome, and the custom-elements-es5-adapter.js
script that is supposed to fix this no longer seems to be working. While I haven't found a solution as of yet, @web-padawan has offered a workaround that does work, but it requires you to generate two different bundles. You can combine a plugin like: webpack-babel-multi-target-plugin with this approach: Deploying ES2015+ Code in Production Today. While it does work, I don't think it should be absolutely necessary in order to adopt lit-elements and support IE.
@web-padawan I also want to reiterate my offer to create a public repo with a simple project to demonstrate the issue. It seems like there are a good number of people who are having this issue, and if you think it would help the team to debug and potentially solve the problem I'm happy to help.
@n-devr So, excluding Internet Explorer and knowing that custom-elements-es5-adapter.js
does not work when targeting babel to ie: 11
What the formula to cover wide range of browsers is?
When I target to esmodules: true
, things works well but when this is done, Do I need to load webcomponents polyfill? <script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
with corejs3
@n-devr if you create an example repository, I could take a look.
However, please keep in mind the following problems:
As a result, developer experience with IE11 is horrible and the apps are too slow. This BTW is a reason why Salesforce uses own polyfill for LWC.
Sorry to add to a closed thread but what is the solution to this for TypeScript and Rollup? Most of what I see here is for babel and webpack. I've tried adding this to my tsconfig
"target": "ES2015"
Rollup config looks like this
import typescript from '@rollup/plugin-typescript';
import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'src/client/main.ts',
output: [
{
file: 'src/server/dist/bundle.js',
format: 'iife',
sourcemap: false,
},
{
file: 'src/server/dist/bundle.esm.js',
format: 'esm',
sourcemap: false,
},
],
plugins: [
resolve(),
typescript({
lib: ['es5', 'es6', 'dom'],
target: 'es5',
}),
],
};
What should I change?
I'm trying out Lit Element in a vanilla Angular 6 project and running into
Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'
when trying out the hello world lit element example. This commit shows how I added webcomponentjs / litelement packages, allow custom schema in angular, declare the my-element LitElement example, and then use that element in the app. That commit was made right after running theng new
command.If you want to poke at it, run the following commands...