【问题标题】:How to use CustomElement v1 polyfill in a webpack/babel build?如何在 webpack/babel 构建中使用 CustomElement v1 polyfill?
【发布时间】:2017-04-05 17:12:50
【问题描述】:

我在让this WebComponents polyfill + native-shim 在所有设备上正常工作时遇到了一些麻烦,尽管 webpack。

我的设置的一些背景: * Webpack2 + babel-6 * 应用程序是用 ES6 编写的,转译为 ES5 * 导入一个用 ES6 编写的node_module 包,它定义/注册了一个在应用程序中使用的CustomElement

所以相关的 webpack 开发配置看起来像这样:

const config = webpackMerge(baseConfig, {
  entry: [
    'webpack/hot/only-dev-server',
    '@webcomponents/custom-elements/src/native-shim',
    '@webcomponents/custom-elements',
    '<module that uses CustomElements>/dist/src/main',
    './src/client',
  ],
  output: {
    path: path.resolve(__dirname, './../dist/assets/'),
    filename: 'app.js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,
        },
        include: [
          path.join(NODE_MODULES_DIR, '<module that uses CustomElements>'),
          path.join(__dirname, '../src'),
        ],
      },
    ],
  },
...

关键要点: * 我需要在 &lt;module that uses CustomElements&gt; 之前加载 CustomElement poly * 我需要&lt;module that uses CustomElements&gt; 在我的应用程序出现问题之前加载 * &lt;module that uses CustomElements&gt; 是 ES6,所以我们正在编译它(因此包含在 babel-loader 中)。

以上在现代 ES6 浏览器(IE 桌面 Chrome)中按预期工作,但是

它不适用于旧版浏览器。我在旧版浏览器(例如 iOS 8)中收到以下错误:

SyntaxError: Unexpected token ')'

指向本机 shim pollyfill 中打开的匿名函数:

(() => {
  'use strict';

  // Do nothing if `customElements` does not exist.
  if (!window.customElements) return;

  const NativeHTMLElement = window.HTMLElement;
  const nativeDefine = window.customElements.define;
  const nativeGet = window.customElements.get;

所以在我看来,native-shim 需要被转译为 ES5:

        include: [
+         path.join(NODE_MODULES_DIR, '@webcomponents/custom-elements/src/native-shim'),
          path.join(NODE_MODULES_DIR, '<module that uses CustomElements>'),
          path.join(__dirname, '../src'),
        ],

...但是现在这样做会破坏 Chrome 和 iOS 8,并出现以下错误:

app.js:1 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
    at new StandInElement (native-shim.js:122)
    at HTMLDocument.createElement (<anonymous>:1:1545)
    at ReactDOMComponent.mountComponent (ReactDOMComponent.js:504)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at Object.updateChildren (ReactChildReconciler.js:121)
    at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:208)
    at ReactDOMComponent._updateChildren (ReactMultiChild.js:312)

.. 这将我带到本机垫片中的 constructor() 行:

  window.customElements.define = (tagname, elementClass) => {
    const elementProto = elementClass.prototype;
    const StandInElement = class extends NativeHTMLElement {
      constructor() {

呸。所以我很不清楚我们是如何将它实际包含在基于 webpack 的构建中,其中使用 CustomElements 的依赖项是 ES6(并且需要转译)。

  • 将本机 shim 转换为 es5 不起作用
  • 在包入口点的顶部按原样使用 native-shim 不适用于 iOS 8,但适用于 Chrome
  • 不包括 native-shim 会破坏 Chrome 和 iOS

在这一点上,我对 Web 组件感到非常沮丧。我只想使用这个恰好是用 Web 组件构建的依赖项。如何让它在 webpack 构建中正常工作,并在所有设备上工作?我在这里遗漏了什么明显的东西吗?

我的 .babelrc 配置为后代着想(开发配置最相关):

{
  "presets": [
    ["es2015", { "modules": false }],
    "react"
  ],
  "plugins": [
    "transform-custom-element-classes",
    "transform-object-rest-spread",
    "transform-object-assign",
    "transform-exponentiation-operator"
  ],
  "env": {
    "test": {
      "plugins": [
        [ "babel-plugin-webpack-alias", { "config": "./cfg/test.js" } ]
      ]
    },
    "dev": {
      "plugins": [
        "react-hot-loader/babel",
        [ "babel-plugin-webpack-alias", { "config": "./cfg/dev.js" } ]
      ]
    },
    "dist": {
      "plugins": [
        [ "babel-plugin-webpack-alias", { "config": "./cfg/dist.js" } ],
        "transform-react-constant-elements",
        "transform-react-remove-prop-types",
        "minify-dead-code-elimination",
        "minify-constant-folding"
      ]
    },
    "production": {
      "plugins": [
        [ "babel-plugin-webpack-alias", { "config": "./cfg/server.js" } ],
        "transform-react-constant-elements",
        "transform-react-remove-prop-types",
        "minify-dead-code-elimination",
        "minify-constant-folding"
      ]
    }
  }
}

【问题讨论】:

标签: ios webpack babeljs web-component webpack-2


【解决方案1】:

我能够通过下面的.babelrc 插件管道实现类似的效果。看起来唯一的区别是https://babeljs.io/docs/plugins/transform-es2015-classes/https://babeljs.io/docs/plugins/transform-es2015-classes/,但老实说我不记得他们具体解决了什么问题:

{
  "plugins": [
    "transform-runtime",
    ["babel-plugin-transform-builtin-extend", {
      "globals": ["Error", "Array"]
    }],
    "syntax-async-functions",
    "transform-async-to-generator",
    "transform-custom-element-classes",
    "transform-es2015-classes"
  ]
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 2018-12-27
    • 1970-01-01
    相关资源
    最近更新 更多