lit-element: Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'

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 the ng new command.

screen shot 2018-05-11 at 3 33 16 pm

If you want to poke at it, run the following commands…

git clone https://github.com/rjsteinert/angular-with-lit-element.git
cd angular-with-list-element
npm install
npm start

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 16
  • Comments: 55 (20 by maintainers)

Commits related to this issue

Most upvoted comments

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/
  ]
}

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

What is the real resolution to this? So much confusion across the issues.

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"]
}

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

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.

@n-devr if you create an example repository, I could take a look.

However, please keep in mind the following problems:

  1. IE11 does not work well with web components because of ShadyDOM performance issues:
  1. Also, ShadyDOM breaks DevTools in IE11 (the issue is closed but not fixed):
  1. Finally, by transpiling to ES5 you also send more code to evergreen browsers.

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.

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 ?

@sslotsky do you need to support IE11? If not, change target: 'es5' in the Rollup config.

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 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.

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",

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.

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

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 ! 🤘 🤘 🤘

@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