programing

HTMLElement 확장: 웹 팩을 사용할 때 생성자가 실패함

itmemos 2023. 6. 16. 21:27
반응형

HTMLElement 확장: 웹 팩을 사용할 때 생성자가 실패함

다음 TypeScript 프로그램을 ES5로 변환했습니다.

파일 1:

class BaseElement extends HTMLElement {
    constructor() {
        super();
    }
}

파일 2:

import {BaseElement} from './BaseElement';

class MyElement extends BaseElement {
    constructor() {
        super();
    }
}

var el = new MyElement();

파일 안에 모든 것을 수동으로 넣고 코드가 정상적으로 작동하며 브라우저에서 실행하면 HTML 요소가 문제 없이 구성됩니다.그러나 웹 팩을 통해 포장하는 즉시 다음 오류 메시지가 표시됩니다.

Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

웹 팩을 사용하지 않으면 다음 JS 코드가 생성됩니다.

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var BaseElement = (function (_super) {
    __extends(BaseElement, _super);
    function BaseElement() {
        _super.call(this);
    }
    return BaseElement;
}(HTMLElement));
var MyElement = (function (_super) {
    __extends(MyElement, _super);
    function MyElement() {
        _super.call(this);
    }
    MyElement.prototype.createdCallback = function () {
        this.innerHTML = "lol";
    };
    return MyElement;
}(BaseElement));
var el = new MyElement();

웹 팩을 사용하여 다음 코드가 구성됩니다.

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }


/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);
    __webpack_require__(2);

/***/ },
/* 1 */
/***/ function(module, exports) {

    "use strict";
    var BaseElement = (function (_super) {
        __extends(BaseElement, _super);
        function BaseElement() {
            _super.call(this);
        }
        return BaseElement;
    }(HTMLElement));
    exports.BaseElement = BaseElement;


/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

    "use strict";
    var BaseElement_1 = __webpack_require__(1);
    var MyElement = (function (_super) {
        __extends(MyElement, _super);
        function MyElement() {
            _super.call(this);
        }
        MyElement.prototype.createdCallback = function () {
            this.innerHTML = "lol";
        };
        return MyElement;
    }(BaseElement_1.BaseElement));
    exports.MyElement = MyElement;
    // TODO: inject
    var p = new MyElement();
/***/ }
/******/ ]);

기본적으로 webpack은 모듈을 함수에 넣고 그들 사이에 내보내기 변수를 유지하지만 HTML 요소의 구성은 실패합니다.웹팩(위 코드) 없이도 정상적으로 작동합니다.

아이디어 있어요?

그것은 문제를 확대하고 있습니다.ES5를 복사하거나 사용하는 경우 네이티브 웹 구성 요소가 지원되는 브라우저용 네이티브 심을 번들로 제공해야 합니다.(https://github.com/webcomponents/custom-elements/blob/master/src/native-shim.js)

가 HTMLElement "의 new.target현재 호출된 생성자에 대한 사용자 지정 요소 정의를 조회합니다. new.target의 경우에만 설정됩니다.new는 호출되고 super() 호출을 통해서만 전파됩니다. super()는 ES5에서 에뮬레이트할 수 없습니다.SuperClass.call(this)`` only works when extending other ES5-style classes, and does not propagatenewnew.target'이(가) .

이슈 토론을 확인하십시오.

ES5 스타일 클래스는 기본 사용자 지정 요소와 함께 작동하지 않습니다.

해결하려면 tsconfig.json 파일의 대상을 es6으로 변경하면 됩니다.

저는 이 문제의 도움으로 이 문제를 해결했습니다 - https://github.com/facebook/create-react-app/issues/3225

기본적으로 나는 npm을 통해 이 두 개의 플러그인을 설치했고 웹팩 구성에서 Babel용으로 이 두 개의 플러그인을 추가했습니다.

use: [
    {
        loader: 'babel-loader',
            options: {
                presets: ['es2015'],
                // https://github.com/facebook/create-react-app/issues/3225
                plugins: ['transform-custom-element-classes', 'transform-es2015-classes']
            },
        }
    ],

웹팩 없이도 작동하는 것이 확실합니까?플레이그라운드를 통해 실행하면 런타임에 설명한 것과 동일한 오류가 발생합니다.

어쨌든, 당신은 그것을 연장하지 말아야 합니다.HTMLElement.
HTMLElement실제로는 유형 스크립트의 인터페이스이므로, 만약 있다면 그렇게 구현해야 합니다.
브라우저에 개체 형식으로 존재하지만 형식 스크립트 클래스로 선언되지 않았으므로 형식 스크립트에서 제대로 확장할 수 없습니다.

이 문제를 해결하는 방법은 다음 답변을 참조하십시오.

웹용 Babel 7 + 웹 팩 4 구성 요소:

꾸러미json:

"devDependencies": {
    "@babel/core": "^7.3.4",
    "@babel/plugin-proposal-class-properties": "^7.3.4",
    "@babel/preset-env": "^7.3.4",
    "babel-loader": "^8.0.5",
    "babel-plugin-transform-custom-element-classes": "^0.1.0",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
}

webpack.config.js:

module: {
  rules: [
    {
      test: /\.js$/,
      use:{
          loader: 'babel-loader',
              options: {
                  presets: ['@babel/preset-env'],
                  plugins: [
                    "transform-custom-element-classes",
                    "@babel/plugin-proposal-class-properties",
                  ]
              },
          },
      exclude: /node_modules/
    }
  ]
}

사용.transform-es2015-classes플러그인은 Babel 7을 사용할 때 빌드 프로세스를 중단합니다.babel-preset-env이미 포함되어 있습니다. @babel/plugin-proposal-class-properties라이프사이클 콜백에 필요합니다.다음과 같은 연간 사전 설정 사용es2015Babel 7에서는 더 이상 사용되지 않습니다.@babel/preset-env대신.

바벨 7.6.0

개인적으로 오류는 다음과 같은 특정 devDependencies에서 제거된 것으로 보입니다.

"devDependencies": {
    "@babel/core": "^7.6.0",
    "@babel/preset-env": "^7.6.0",
    "babel-loader": "^8.0.6",
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.8"
}

다음 webpack.config.js:

var glob = require('glob');
var path = require('path');

module.exports = {
    entry: glob.sync('./app/scripts/**.js').reduce(function(obj, el){
        obj[path.parse(el).name] = el;
        return obj
    },{}),
    output: {
        path: path.resolve(__dirname, './dist/scripts'),
        filename: "[name].js"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [
                    path.resolve(__dirname, 'app/scripts')
                ],
                options: {
                    presets: ['@babel/env']
                }
            }
        ]
    }
};

그래서 기본적으로 저는 웹팩에 제 /app/scripts 폴더에 있는 모든 .js 파일을 transfile하고, babel-loader를 사용하여 /dist/scripts에 저장하라고 말하고 있습니다.@babel/preset-env꾸러미

바벨 6.*.0.

그러나 사용 중인 경우@babel/core 6.*.*https://medium.com/ @allenhwkim/sys-message-custom-syslog-error-e86db5ae3b8c를 확인할 수 있습니다.이것은 매우 간단하며 나는 이미 성공적으로 사용한 후에 모든 바벨 패키지를 업데이트하려고 합니다.

당신이 해야 할 일은npm install babel-plugin-transform-es2015-classes babel-plugin-transform-custom-element-classes --save-dev그런 다음 webpack.config.js에 추가합니다.npm install --save-dev babel-preset-es2015또한):

module: {
    rules: [
        {
            test: /\.js$/,
            loader: 'babel-loader',
            include: [
                path.resolve(__dirname, 'app/scripts')
            ],
            options: {
                presets: ['es2015'],
                plubins: ["transform-custom-element-classes", "transform-es2015-classes"]
            }
        }
    ]
}

언급URL : https://stackoverflow.com/questions/39037489/extending-htmlelement-constructor-fails-when-webpack-was-used

반응형