vuejs/vue-web-component-wrapper

IE Support

ChristianMurphy opened this issue ยท 28 comments

There are now babel plugins and polyfills that can run web components on IE.
https://github.com/github/babel-plugin-transform-custom-element-classes
https://github.com/webcomponents/custom-elements

If an IE compatible version is generated and included in the distribution, it would open the door for Vue CLI to support something like modern mode for target web component.

Hi @ChristianMurphy !! First of all I really appreciate your effort to bring vue web component into IE11. Thanks for that.

Did you success to solve this issue? I have notice that the problem of the IE11 Support is that vue web components requires ES2015 classes and IE11 not supporte it. I also notice that the pollyfills that you listed in this issue solve the custom element problem but not bring ES2015 classes into IE11.

Kind regards.

@pablocattaneo I use babel-plugin-transform-custom-element-classes in https://github.com/karol-f/vue-custom-element and it transform ES2015 classes to ES5 during build so even IE9 can use it (with appropriate polyfill).

So @ChristianMurphy comment is definitely valid

wbern commented

@karol-f @ChristianMurphy Can we get that PR merged soon? We'd love to start using this solution.

@karol-f

IE9 can use it (with appropriate polyfill).

what polyfills are needed to get the web components working on ie9?

not sure where to put this issue, should i create a new issue here?

installed as dev dependencies
babel-plugin-transform-custom-element-classes
transform-custom-element-classes

went to
babel.config.js

added it as such

  presets: [
    '@vue/app',
  ],
  plugins: [
    'transform-custom-element-classes',
    'transform-es2015-classes',
    [
      'import', {
        libraryName: 'iview',
        libraryDirectory: 'src/components',
      },
    ],
  ],
};

went to vue.config.js

added as such

  transpileDependencies: [
    // can be string or regex
    '@vue/web-component-wrapper',
  ],
};

add polyfill to page rendering custom component

<script src="https://cdnjs.cloudflare.com/ajax/libs/document-register-element/1.4.1/document-register-element.js"></script>

not transpiling custom-web-component from es6 to es5

get this error in console

syntax error
const camelize = str => {...}

this is part of the @vue/custom-web-component dependency. javascript is not being transformed from es6 to es5.

any ideas?

@addijhaq the vue web component wrapper is injected in a seperate webpack from the transpiler.
Meaning transpileDependencies has no affect on it.
To work around you need something like: uPortal-Project/uPortal-web-components@37b0f70

Nota Bene: "prebuild": "babel node_modules/@vue/web-component-wrapper/dist/vue-wc-wrapper.js -o node_modules/@vue/web-component-wrapper/dist/vue-wc-wrapper.js" is needed to transpile the dependency before it is injected by webpack.

@ChristianMurphy okay so i'm also getting this problem with vue-style-loader where addStyleShadow.js is not being transpiled either. per your prebuild script i added

babel node_modules/vue-style-loader/lib/addStylesShadow.js -o node_modules/vue-style-loader/lib/addStylesShadow.js

and it fixed the issue, however, this is tedious and will most likely be some kind of issue on a case per case basis dependent upon which vue-* modules are being used to compile the web-component.

any reason why this one script is being ignored too?

Good to know.

any reason why this one script is being ignored too?

Not sure, I haven't run into this.
It would take some more investigation.

@ChristianMurphy what is the order the polyfills should be in the header of the client?

I've been using

<script src="https://unpkg.com/core-js-bundle@3.0.0-beta.3"></script>
<script src="https://unpkg.com/regenerator-runtime/runtime.js"></script>
<script src="https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script src="https://unpkg.com/vue"></script>

Or put more generically

polyfill the language first, polyfill the platform second, add libraries last.

@ChristianMurphy
SCRIPT1003: Expected ':'
vue template in the custom element is being picked up?

name: 'Layout',
  data() {
    return {
      hasSider: false
    };```

@addijhaq you'll need to write code in ES5 or use a transiler (E.G. Babel and Bublรฉ)
Object method shorthand, is supported in ES2015+ only, IE cannot parse the code.

@ChristianMurphy great! added two babel-plugins to my babel.config.js

plugins: [
    'transform-custom-element-classes',
    'transform-es2015-shorthand-properties',
    'transform-es2015-template-literals',
  ],

fixes the es2015 functions and also any template literals using ${whatever.variable}

however pulling script into ie11 throws no errors, but also loads nothing :( ...

i have security to allow loading of local files as i'm not hosting/serving the .js file

i'm using virtualbox to run version of win7 with ie11.... would this be the issue? .. don't have access to a full windows computer. if you do would you mind if i sent you my js to see if it will run?

fyi, i'm working for a large enterprise and we desperately need ie9-11 compatibility... i might have to jump ship on the cli and use @karol-f's... but i'm uncertain how to use his properly with nested components/css.. ie9-11 is such a headache...

also if it makes any difference i will document how to achieve functionality by updating docs to provide clearer approach to tackling this issue. i'm more than 110% willing to give back and share what i find to help others in this similar situation.

however pulling script into ie11 throws no errors, but also loads nothing

I'd drop in some console.logs to see if the scripts are getting called at all.

i'm using virtualbox to run version of win7 with ie11.... would this be the issue? .. don't have access to a full windows computer.

Maybe?
I'm also testing off a VM.
IE11 on Windows 8.1 from https://developer.microsoft.com/en-us/microsoft-edge/tools/vms
It has been working for me, some users running Windows directly have also tested and it has been working.
The only issues that has been seen occasionally is webcomponents/webcomponentsjs#972

but i'm uncertain how to use his properly with nested components/css

That is a bit outside the scope of this issue, that'd be a good question to ask at https://github.com/karol-f/vue-custom-element

Has anyone got this to work?

Has anyone got this to work?

yes, check #32

Closing this out, #32 has been declined.
There is a work around in #31 (comment).
It may be worth opening an issue upstream to see if transpileDependencies can be fixed so it can be applied to any dependency, including vue-web-component-wrapper. #31 (comment)

Rahmo commented

Im still having this issue

@Rahmo I think you can easily assume that this project won't support IE (and I totally understand that). If you want IE support use vue-custom-element

I hope it will help for someone. Build system - webpack without vue cli.
vue-custom-element - is perfect plugin, but I got several issues connected with shadow dom and reusability of components (karol-f/vue-custom-element#191). So I have been had to figure out how to turn on web-component-wrapper for ie. This is my workaround.

list of plugins for transpiling and polyfilling:

"core-js": "^3.4.5",
"@babel/core": "^7.7.4",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-decorators": "^7.7.4",
"@babel/preset-env": "^7.7.4",
"@babel/preset-typescript": "^7.7.4",
"@webcomponents/webcomponentsjs": "2.0.4"  // if using morest new it cause out of stack memory inside IE
"babel-loader": "^8.0.6",

babel.config.js

module.exports = function (api) {
    api.cache(true);

    const presets = [
        ["@babel/env", {
            modules: false,
            targets: '> 1%, ie >= 11',
            useBuiltIns: 'usage',
            corejs: 3,
        }],
        ["@babel/preset-typescript", { allExtensions: true }],
    ];
    const plugins = [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ["@babel/plugin-proposal-class-properties", { "loose" : true }],
    ];
    const sourceType = 'unambiguous';

    return {
        presets,
        plugins,
        sourceType,
    };
};

polifills.ts file should be the first entry point
polifills.ts:

// add webcomponents polyfill
import '@webcomponents/webcomponentsjs/webcomponents-bundle';
/* tslint:enable */

inside webpack js/ts loader exclude all node_modules except web-component-wrapper
webpack.config.js - rules for ts/js:

....
module: {
  rules: [

     ....
            {
                test: /(\.ts$)|(\.js$)/,
                exclude: /node_modules\/(?!(@vue\/web-component-wrapper)\/).*/,
                loader: 'babel-loader',
            }
      ....
  ]
}
....

Kind regards.

wbern commented

Hope this can help others.

There is an issue even if you transpile this repo to es5, with slots and shadyDOM, where slots changes does not trigger a Vue render on the wrapped component.

This fork addresses those issues: https://github.com/TeliaSweden/vue-web-component-wrapper-ie11

This is a fork of @vue/web-component-wrapper which

  • extends support to IE11 through babel transpilation with the babel-plugin-transform-builtin-classes plugin that was created to address the issue of extending HTMLElement in browsers without native support for ES2015 classes.
  • Fixes support for ShadyDOM usage regarding slots where slots are not caught by a Mutation Observer (issue: webcomponents/polyfills#81)

^ See last point above.

@wbern How would I use your fork in combination with vue-cli, can you give me a pointer on the best way how to implement this?

wbern commented

@wbern How would I use your fork in combination with vue-cli, can you give me a pointer on the best way how to implement this?

I will get back to you tomorrow. We identified a bug with it so it needs to be addressed at the same time.

Thanks in advance @wbern :)

wbern commented

@thomasaull

https://gist.github.com/wbern/1a85b42bfee4550fdd0011d5b2902de7

I copied the important files from a playground project we made. We basically omitted the wc option in vue cli, then called the wrap() method ourselves instead. The difference is minimal.

Also need to enable shadowMode in vue.config.js.

@wbern Thanks, Iโ€˜ll give it a try :)

wbern commented

@thomasaull I made some enhancements to it.

If enabled, does continous auto-injection of global styles to inside the shadow dom

const CustomElement = wrap(Vue, () => import(`MyComponent.vue`), {
  globalStyles: true,
})

tell me what you think.