npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@telia/vue-web-component-wrapper-ie11

v1.7.3

Published

wrap a vue component as a web component, for IE 11 too.

Downloads

361

Readme

@telia/vue-web-component-wrapper-ie11

Wrap and register a Vue component as a custom element (with Shadow DOM), in IE 11 and beyond.

Features

From the original project: @vue/web-component-wrapper:

  • Automatically emits Custom Events from this.$emit() calls
  • Supports passing in slots
  • Isolated styles, thanks to Shadow DOM (has limitations with leaking styles in IE 11, see this section)
  • Very simple to use.

From this fork

  • Best-effort IE 11 support thanks to ES5 transpilation, a work-around to fix a bug in ShadyDOM regarding Mutation Observers, and a few other fixes specifically written for IE 11 support. Just make sure to include the polyfill described in the next section.
  • If enabled, offers auto-injection of global styles. Can be configured to be selective, too.
  • If enabled, exposes "-json" suffixed props based on your source component props, that automatically map JSON to Objects/Arrays back to your source props.
  • Better support for Vue's scoped style tags without FOUC's.

Usage

import '@webcomponents/webcomponentsjs'

import Vue from 'vue'
import wrap from '@telia/vue-web-component-wrapper-ie11'
import VueComponent from './VueComponent.vue'

const CustomElement = wrap(Vue, VueComponent, {
  // globalStyles: true,
  // jsonMapping: true,
})

window.customElements.define('vue-component', CustomElement)

Now you can just add <vue-component> anywhere in the page, and the component will appear fully loaded, like it was made by the browser itself. This seamless step is arguably the best part of utilizing Web Components.

It works with async components as well - you can pass an async component factory function that returns a Promise, and the function will only be called when an instance of the custom element is created on the page:

const CustomElement = wrap(Vue, () => import(`VueComponent.vue`))

window.customElements.define('my-element', CustomElement)

You can also import or just have a <script> tag point to @telia/vue-web-component-wrapper-ie11/dist/vue-wc-wrapper.global.js, which will expose wrap as wrapVueWebComponent globally on the window object.

How do I use this instead of the standard library shipped with Vue-CLI?

  • Change from --target wc to --target lib (or anything else really) in the Vue-CLI run options (probably in package.json)
    • Add --inline-vue if you want to make sure Vue is included in your web component.
  • Make sure you have a main.js file.
  • Import and use the wrap() method as shown above
  • You can also export the bare Vue component also via ES6 exports, should you need to.

Note that with the above approach, you'll be putting all web components in a single bundle. This section does not document how to make a bundle per web component.

Polyfilling for IE 11

Easiest is to do:

import '@webcomponents/webcomponentsjs'

The polyfill bundle with check if the browser supports web components and will apply polyfills as needed. If you want to reduce bundle size even further, that is possible, just consult the @webcomponents/webcomponentsjs documentation on using their loader.

Whatever you do, do not import the custom elements and other polyfills directly, as it will overwrite native browser functionality for browsers like Chrome, that already support Web Components.

IE11 Warning: Note on CSS Encapsulation When Using the Shady DOM polyfill

The styles will leak through to your web components in IE 11 in several cases, like when passing slots to the web component. Make sure you use a way to encapsulate your styles like BEM, Scoped styles (has drawbacks of its own), or CSS Modules. Choose the one that fits you.

API

wrap(VueInstance, sourceComponent, wrapOptions?)

Returns a Custom Element, that can be used in the browser-provided window.customElements.define call.

VueInstance

Type: object

Your Vue instance.

sourceComponent

Type: object

Your source component (can also just be a simple javascript object {}, not a separate vue file).

wrapOptions?

Type: object

supportScopedCss?

Type: boolean
Default: true

Setting this to false will skip a 0ms setTimeout() call, but will also break Vue's scoped attribute support in the form of FOUC's.

globalStyles?

Type: boolean | object
Default: false

If you want auto-injection of the global styles, set it to true.

You can specify more granular rules for global style injection, refer to this part of the source code for details. The defaults should be reasonable for most developers.

jsonMapping?

Type: boolean
Default: false

If you want automatic deserialization of javascript objects and arrays.

Then just pass "my-array-json" like :my-array-json="JSON.stringify({ a: 1 })" to your web component, it will parse it to the prop called "myArray" in the vue file as a regular js object again. If the json is invalid it will become "INVALID_JSON". This works for props defined with type Array and Object

Interface Proxying Details

Props

  • All props declared in the Vue component are exposed on the custom element as its properties. Kebab-case props are converted to camelCase properties, similar to how they are converted in Vue.

  • Setting properties on the custom element updates the props passed to the inner Vue component.

  • Setting attributes on the custom element updates corresponding declared props. Attributes are mapped to kebab-case. For example, a prop named someProp will have a corresponding attribute named some-prop.

  • Attributes that map to props declared with type: Boolean are auto-casted into boolean values in the following rules:

    • "" or same value as attribute name: -> true

    • "true" -> true

    • "false" -> false

  • Attributes that map to props declared with type: Number are auto-casted into numbers if the value is a parsable number.

Events

Custom events emitted on the inner Vue component are dispatched on the custom element as a CustomEvent. Additional arguments passed to $emit will be exposed as an Array as event.detail.

Slots

Slots work the same way as expected, including named slots. They also update when changed (using MutationObserver).

Scoped slots however, are not supported as they are a Vue specific concept.

Lifecycle

When the custom element is removed from the document, the Vue component behaves just as if it's inside a <keep-alive> and its deactivated hook will be called. When it's inserted again, the activated hook will be called.

If you wish to destroy the inner component, you'd have to do that explicitly:

myElement.vueComponent.$destroy()

Acknowledgments

Special thanks to the prior work by @karol-f in vue-custom-element.

License

MIT