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

@webcomponents/webcomponentsjs

v2.8.0

Published

Web Components Polyfills

Downloads

793,214

Readme

Build Status

webcomponents.js (v1 spec polyfills)

Note. For polyfills that work with the older Custom Elements and Shadow DOM v0 specs, see the v0 branch.

Note. For polyfills that include HTML Imports, see the v1 branch.

A suite of polyfills supporting the Web Components specs:

For browsers that need it, there are also some minor polyfills included:

How to use

Install polyfills

npm install @webcomponents/webcomponentsjs

You can also load the code from a CDN such as unpkg: https://unpkg.com/@webcomponents/webcomponentsjs@^2/

Using webcomponents-bundle.js

The webcomponents-bundle.js contains all of the web components polyfills and is suitable for use on any supported browser. All of the polyfill code will be loaded but each polyfill will only be used based on feature detection. The bundle includes Custom Elements, Shady DOM/CSS and generic platform polyfills (such as ES6 Promise, Constructable events, etc.) (needed by Internet Explorer 11), and Template (needed by IE 11 and Edge).

The webcomponents-bundle.js is very simple to use but it does load code that is not needed on most modern browsers, slowing page load. For best performance, use the webcomponents-loader.js.

Here's an example:

<!-- load webcomponents bundle, which includes all the necessary polyfills -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>

<!-- load the element -->
<script type="module" src="my-element.js"></script>

<!-- use the element -->
<my-element></my-element>

Using webcomponents-loader.js

The webcomponents-loader.js is a client-side loader that dynamically loads the minimum polyfill bundle, using feature detection.

webcomponents-loader.js can be loaded synchronously, or asynchronously depending on your needs.

Inlining

If you have inlined the source of webcomponent-loader.js, then you should specify window.WebComponents.root as the root from which to load the polyfills. For example:

<script>
  window.WebComponents = window.WebComponents || {};
  window.WebComponents.root = 'node_modules/@webcomponents/webcomponentsjs/';
</script>

This property is used to build the URL to the selected bundle, so you should only set it to values that are unable to be influenced by user-controlled data. If trusted types are enforced, this property should be a TrustedScriptURL.

Synchronous

When loaded synchronously, webcomponents-loader.js behaves similarly to webcomponents-bundle.js.

The appropriate bundle will be loaded with document.write() to ensure that WebComponent polyfills are available for subsequent scripts and modules.

Here's an example:

<!-- load the webcomponents loader, which injects the necessary polyfill bundle -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>

<!-- load the element -->
<script type="module" src="my-element.js"></script>

<!-- use the element -->
<my-element></my-element>

Asynchronous

When loaded asychronously with the defer attribute, polyfill bundles will be loaded asynchronously, which means that scripts and modules that depend on webcomponents APIs must be loaded using WebComponents.waitFor function.

The WebComponents.waitFor function takes a callback function as an argument, and will evaluate that callback after the polyfill bundle has been loaded.

The callback function should load scripts that need the polyfills (typically via import('my-script.js')) and should return a promise that resolves when all scripts have loaded.

Here's an example:

<!-- Load polyfills; note that "loader" will load these async -->
<script
  src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
  defer
></script>

<!-- Load a custom element definitions in `waitFor` and return a promise -->
<script type="module">
  WebComponents.waitFor(() => {
    // At this point we are guaranteed that all required polyfills have
    // loaded, and can use web components API's.
    // The standard pattern is to load element definitions that call
    // `customElements.define` here.
    // Note: returning the import's promise causes the custom elements
    // polyfill to wait until all definitions are loaded and then upgrade
    // the document in one batch, for better performance.
    return import('my-element.js');
  });
</script>

<!-- Use the custom element -->
<my-element></my-element>

The WebComponents.waitFor function may be called multiple times, and the callback functions will be processed in order.

Here's a more complicated example:

<!-- Load polyfills; note that "loader" will load these async -->
<script
  src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
  defer
></script>

<script type="module">
  WebComponents.waitFor(async () => {
    if (!window.fetch) {
      await import('node_modules/fetch-polyfill/fetch.js');
    }
    return import('my-element.js');
  });
</script>

<script type="module"></script>

Trusted Types

If you're using the loader on a page that enforces the trusted-types Content Security Policy, you'll need to allow the webcomponents-loader policy name so that the loader can dynamically create and insert a <script> for the polyfill bundle it selects based on feature detection. If you set WebComponents.root (which is rare), it should be set to a TrustedScriptURL for Trusted Types compatibility.

WebComponentsReady event

The WebComponentsReady event is fired when polyfills and user scripts have loaded and custom elements have been upgraded. This event is generally not needed; however, it may be useful in some cases like testing. If imperative code should wait until a specific custom element definition has loaded, it can use the platform customElements.whenDefined API.

custom-elements-es5-adapter.js

According to the spec, only ES6 classes (https://html.spec.whatwg.org/multipage/scripting.html#custom-element-conformance) may be passed to the native customElements.define API. For best performance, ES6 should be served to browsers that support it, and ES5 code should be serve to those that don't. Since this may not always be possible, it may make sense to compile and serve ES5 to all browsers. However, if you do so, ES5-style custom element classes will now not work on browsers with native Custom Elements because ES5-style classes cannot properly extend ES6 classes, like HTMLElement.

As a workaround, if your project has been compiled to ES5, load custom-elements-es5-adapter.js before defining Custom Elements. This adapter will automatically wrap ES5.

The adapter must NOT be compiled.

Browser Support

The polyfills are intended to work in the latest versions of evergreen browsers. See below for our complete browser support matrix:

| Polyfill | Edge | IE11+ | Chrome* | Firefox* | Safari 9+* | Chrome Android* | Mobile Safari* | | --------------- | :--: | :---: | :------: | :-------: | :---------: | :--------------: | :-------------: | | Custom Elements | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Shady CSS/DOM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

*Indicates the current version of the browser

The polyfills may work in older browsers, however require additional polyfills (such as classList, or other platform polyfills) to be used. We cannot guarantee support for browsers outside of our compatibility matrix.

Known Issues

Style encapsulation (inline styling in components) does not work out of the box.

The ShadowDOM polyfill does not properly support CSS in ShadowDoM out of the box:

  • Any styles inside components have an effect on the whole document (instead of on the component only - the encapsulation is broken).
  • Any shadow-dom specific selectors (like :host) do not work.

You can fix those issues by manually calling the ShadyCSS APIs. See ShadyCSS usage.

Custom element's constructor property is unreliable

See #215 for background.

In Edge and IE, instances of Custom Elements have a constructor property of HTMLUnknownElementConstructor and HTMLUnknownElement, respectively. It's unsafe to rely on this property for checking element types.

It's worth noting that customElement.__proto__.__proto__.constructor is HTMLElementPrototype and that the prototype chain isn't modified by the polyfills(onto ElementPrototype, etc.)

ShadyCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work

ShadyCSS :host() rules can only have (at most) 1-level of nested parentheses in its argument selector under ShadyCSS. For example, :host(.zot) and :host(.zot:not(.bar)) both work, but :host(.zot:not(.bar:nth-child(2))) does not.

Manually Building

If you wish to build the bundles yourself, you'll need node and npm on your system:

  • install node.js using the instructions on their website
  • use npm to install gulp.js: npm install -g gulp
  • make sure you have Java installed per https://www.npmjs.com/package/google-closure-compiler#java-version

Now you are ready to build the polyfills with:

# install dependencies
npm install
# build
npm run build

The builds will be placed into the root directory.

Contribute

See the contributing guide

License

Everything in this repository is BSD style license unless otherwise specified.

Copyright (c) 2015 The Polymer Authors. All rights reserved.

Changes in version 2.x

  • The HTML Imports polyfill has been removed. Given that ES modules have shipped in most browsers, the expectation is that web components code will be loaded via ES modules.
  • When using webcomponents-loader.js with the defer attribute, scripts that rely on the polyfills must be loaded using WebComponents.waitFor(loadCallback).