lit / lit-element

LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.
https://lit-element.polymer-project.org
BSD 3-Clause "New" or "Revised" License
4.49k stars 318 forks source link

Uncaught TypeError: Class extends value #<Object> is not a constructor or null #1114

Closed chicken-suop closed 3 years ago

chicken-suop commented 3 years ago

Description

I'm trying to refactor a large legacy application, by componentizing various parts. It was going quite well, until I tried to use the component. The legacy component uses browserify to build a bundle. After importing the component in the legacy app, that browserify step fails with this error:

SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (28:0) while parsing /Volumes/SourceCode/legacy-app/components/my-component/node_modules/lit-element/lib/updating-element.js while parsing file: /Volumes/SourceCode/legacy-app/components/my-component/node_modules/lit-element/lib/updating-element.js

My component:

var UpdatingElement = require('lit-element/lib/updating-element');

class BackboneElement extends UpdatingElement {
  initialize() {
    super.initialize();
    this.renderRoot = this.createRenderRoot();
  }

  createRenderRoot() {
    return this;
  }

  update(changedProperties) {
    super.update(changedProperties);
    const View = this.render();
    const view = new View();
    view.render();
    this.innerHTML = view.$el.html();
  }

  // Needs to return backbone view
  render() {}
}

module.exports = BackboneElement

Now, I tried to solve this issue by adding a babel transform step to browserify:

var b = browserify({
  debug: true,
  entries: inputDir + bundle + '/index.js'
}).transform(hbsfy).transform(babelify, {
  global: true,
  only: [/components\/my-component\/node_modules\/(?:lit-element|lit-html)/],
  presets: [["@babel/preset-env", { targets: { esmodules: true } }]]
})

That solves the above error, and lets me build a bundle successfully. Another issue appears though, when I load the legacy app in the browser:

Uncaught TypeError: Class extends value #<Object> is not a constructor or null
    at Object.614.lit-element/lib/updating-element (backbone-element.js:3)
    at o (_prelude.js:1)
    at _prelude.js:1
    at Object.704.../backbone-element (layouts.js:1)
    at o (_prelude.js:1)
    at _prelude.js:1
    at Object.706../svg-icon (tool-panel.js:8)
    at o (_prelude.js:1)
    at _prelude.js:1
    at initMyComponent (index.js:401)

Package versions

"@babel/core": "^7.12.3", "@babel/preset-env": "^7.12.1", "babelify": "10.0.0", "browserify": "^12.0.1", "lit-element": "^2.3.1",

Acceptance criteria

The component must be useable in the legacy app, without browser or build issues.

chicken-suop commented 3 years ago

Solved by @bathos.

Solution

Change var UpdatingElement = require('lit-element/lib/updating-element'); to import { UpdatingElement } from 'lit-element/lib/updating-element';. Use this babel transform:

.transform(babelify, {
  only: [
    /components\/tool-panel\/node_modules\/(?:lit-element|lit-html)/,
    /components\/tool-panel/
  ],
  global: true,
  presets: [
    ['@babel/preset-env', {
      'targets': {
        esmodules: true,
      },
      'bugfixes': true
    }]
  ],
  plugins: ['@babel/plugin-transform-modules-commonjs']
})

(or use @babel/plugin-transform-runtime)