如何在webpack / babel构建中使用CustomElement v1 polyfill?

时间:2017-04-05 17:12:51

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

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

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

所以相关的webpack dev config看起来像这样:

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'),
        ],
      },
    ],
  },
...

关键带走: *我需要在<module that uses CustomElements>之前加载CustomElement poly *我需要在我的应用程序源之前加载<module that uses CustomElements> * <module that uses CustomElements>是ES6,因此我们正在对其进行转换(因此包含在babel-loader中)。

以上在现代ES6浏览器(IE桌面Chrome)中的预期效果如此,但

它在旧浏览器中不起作用。我在旧版浏览器中遇到以下错误,例如iOS 8:

SyntaxError: Unexpected token ')'

指向native-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(并且需要转换)。

  • 将原生填充符映射到es5不起作用
  • 在捆绑入口点顶部使用原生填充功能不适用于iOS 8,但适用于Chrome
  • 不包括native-shim打破Chrome和iOS

此时我对网络组件非常沮丧。我只想使用恰好使用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"
      ]
    }
  }
}

1 个答案:

答案 0 :(得分: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"
  ]
}