UNPKG

10.8 kBMarkdownView Raw
1[![Build Status](https://travis-ci.org/webcomponents/webcomponentsjs.svg?branch=master)](https://travis-ci.org/webcomponents/webcomponentsjs)
2
3webcomponents.js (v1 spec polyfills)
4================
5
6> **Note**. For polyfills that work with the older Custom Elements and Shadow DOM v0 specs,
7see the [v0 branch](https://github.com/webcomponents/webcomponentsjs/tree/v0).
8
9> **Note**. For polyfills that include HTML Imports,
10see the [v1 branch](https://github.com/webcomponents/webcomponentsjs/tree/v1).
11
12A suite of polyfills supporting the [Web Components](http://webcomponents.org) specs:
13
14- **Custom Elements v1**: allows authors to define their own custom tags ([spec](https://w3c.github.io/webcomponents/spec/custom/), [tutorial](https://developers.google.com/web/fundamentals/getting-started/primers/customelements), [polyfill](https://github.com/webcomponents/custom-elements)).
15- **Shadow DOM v1**: provides encapsulation by hiding DOM subtrees under shadow roots ([spec](https://w3c.github.io/webcomponents/spec/shadow/), [tutorial](https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom),
16[shadydom polyfill](https://github.com/webcomponents/shadydom), [shadycss polyfill](https://github.com/webcomponents/shadycss)).
17
18For browsers that need it, there are also some minor polyfills included:
19- [`HTMLTemplateElement`](https://github.com/webcomponents/template)
20- [`Promise`](https://github.com/taylorhakes/promise-polyfill)
21- `Event`, `CustomEvent`, `MouseEvent` constructors and `Object.assign`, `Array.from`
22(see [webcomponents-platform](https://github.com/webcomponents/webcomponents-platform))
23- [`URL constructor`](https://github.com/webcomponents/URL)
24
25## How to use
26### Install polyfills
27```bash
28npm install @webcomponents/webcomponentsjs
29```
30
31You can also load the code from a CDN such as unpkg: https://unpkg.com/@webcomponents/webcomponentsjs@^2/
32
33### Using `webcomponents-bundle.js`
34
35The `webcomponents-bundle.js` contains all of the web components polyfills and is
36suitable for use on any supported browser. All of the polyfill code will be loaded
37but each polyfill will only be used based on feature detection.
38The bundle includes Custom Elements, Shady DOM/CSS and generic platform polyfills
39(such as ES6 Promise, Constructable events, etc.) (needed by Internet Explorer 11),
40and Template (needed by IE 11 and Edge).
41
42The `webcomponents-bundle.js` is very simple to use but it does load code
43that is not needed on most modern browsers, slowing page load. For best performance,
44use the `webcomponents-loader.js`.
45
46Here's an example:
47
48```html
49<!-- load webcomponents bundle, which includes all the necessary polyfills -->
50<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
51
52<!-- load the element -->
53<script type="module" src="my-element.js"></script>
54
55<!-- use the element -->
56<my-element></my-element>
57```
58
59### Using `webcomponents-loader.js`
60
61The `webcomponents-loader.js` is a client-side loader that dynamically loads the
62minimum polyfill bundle, using feature detection.
63
64`webcomponents-loader.js` can be loaded synchronously, or asynchronously depending on your needs.
65
66#### Inlining
67
68If 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.
69For example:
70
71```html
72<script>
73 window.WebComponents = window.WebComponents || {};
74 window.WebComponents.root = 'node_modules/@webcomponents/webcomponentsjs/';
75</script>
76```
77
78#### Synchronous
79When loaded synchronously, `webcomponents-loader.js` behaves similarly to `webcomponents-bundle.js`.
80
81The appropriate bundle will be loaded with `document.write()` to ensure that WebComponent polyfills are available for subsequent scripts and modules.
82
83Here's an example:
84
85```html
86<!-- load the webcomponents loader, which injects the necessary polyfill bundle -->
87<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
88
89<!-- load the element -->
90<script type="module" src="my-element.js"></script>
91
92<!-- use the element -->
93<my-element></my-element>
94```
95
96#### Asynchronous
97When loaded asychronously with the `defer` attribute, polyfill bundles will be loaded asynchronously,
98which means that scripts and modules that depend on webcomponents APIs *must* be loaded
99using `WebComponents.waitFor` function.
100
101The `WebComponents.waitFor` function takes a callback function as an argument, and will evaluate that callback after the polyfill bundle has been loaded.
102
103The callback function should load scripts that need the polyfills (typically via `import('my-script.js')`) and
104should return a promise that resolves when all scripts have loaded.
105
106Here's an example:
107
108```html
109<!-- Load polyfills; note that "loader" will load these async -->
110<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" defer></script>
111
112<!-- Load a custom element definitions in `waitFor` and return a promise -->
113<script type="module">
114 WebComponents.waitFor(() => {
115 // At this point we are guaranteed that all required polyfills have
116 // loaded, and can use web components API's.
117 // The standard pattern is to load element definitions that call
118 // `customElements.define` here.
119 // Note: returning the import's promise causes the custom elements
120 // polyfill to wait until all definitions are loaded and then upgrade
121 // the document in one batch, for better performance.
122 return import('my-element.js');
123 });
124</script>
125
126<!-- Use the custom element -->
127<my-element></my-element>
128```
129
130The `WebComponents.waitFor` function may be called multiple times, and the callback functions will be processed in order.
131
132Here's a more complicated example:
133
134```html
135<!-- Load polyfills; note that "loader" will load these async -->
136<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" defer></script>
137
138<script type="module">
139 WebComponents.waitFor(async () => {
140 if (!window.fetch) {
141 await import('node_modules/fetch-polyfill/fetch.js');
142 }
143 return import('my-element.js');
144 })
145</script>
146
147<script type="module">
148</script>
149```
150
151### WebComponentsReady event
152
153The `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.
154
155### `custom-elements-es5-adapter.js`
156According 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 performnace, 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`.
157
158As 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.
159
160**The adapter must NOT be compiled.**
161
162## Browser Support
163
164The polyfills are intended to work in the latest versions of evergreen browsers. See below
165for our complete browser support matrix:
166
167| Polyfill | Edge | IE11+ | Chrome* | Firefox* | Safari 9+* | Chrome Android* | Mobile Safari* |
168| ---------- |:----:|:-----:|:-------:|:--------:|:----------:|:---------------:|:--------------:|
169| Custom Elements | ✓ | ✓ | ✓ | ✓ | ✓ | ✓| ✓ |
170| Shady CSS/DOM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
171
172\*Indicates the current version of the browser
173
174The polyfills may work in older browsers, however require additional polyfills (such as classList, or other [platform](https://github.com/webcomponents/webcomponents-platform)
175polyfills) to be used. We cannot guarantee support for browsers outside of our compatibility matrix.
176
177
178### Manually Building
179
180If you wish to build the bundles yourself, you'll need `node` and `npm` on your system:
181
182 * install [node.js](http://nodejs.org/) using the instructions on their website
183 * use `npm` to install [gulp.js](http://gulpjs.com/): `npm install -g gulp`
184 * make sure you have Java installed per https://www.npmjs.com/package/google-closure-compiler#java-version
185
186Now you are ready to build the polyfills with:
187
188 # install dependencies
189 npm install
190 # build
191 npm run build
192
193The builds will be placed into the root directory.
194
195## Contribute
196
197See the [contributing guide](CONTRIBUTING.md)
198
199## License
200
201Everything in this repository is BSD style license unless otherwise specified.
202
203Copyright (c) 2015 The Polymer Authors. All rights reserved.
204
205## Changes in version 2.x
206
207* The HTML Imports polyfill has been removed. Given that ES modules have shipped in
208most browsers, the expectation is that web components code will be loaded via
209ES modules.
210* When using `webcomponents-loader.js` with the `defer` attribute, scripts that rely on the polyfills *must* be loaded using `WebComponents.waitFor(loadCallback)`.
211
212## Known Issues
213
214 * [ShadowDOM CSS is not encapsulated out of the box](#shadycss)
215 * [Custom element's constructor property is unreliable](#constructor)
216 * [ShadyCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work](#nestedparens)
217
218### ShadowDOM CSS is not encapsulated out of the box <a id="shadycss"></a>
219The ShadowDOM polyfill is not able to encapsulate CSS in ShadowDOM out of the box. You need to use specific code from the ShadyCSS library, included with the polyfill. See [ShadyCSS instructions](https://github.com/webcomponents/shadycss).
220
221### Custom element's constructor property is unreliable <a id="constructor"></a>
222See [#215](https://github.com/webcomponents/webcomponentsjs/issues/215) for background.
223
224In 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.
225
226It's worth noting that `customElement.__proto__.__proto__.constructor` is `HTMLElementPrototype` and that the prototype chain isn't modified by the polyfills(onto `ElementPrototype`, etc.)
227
228### ShadyCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work <a id="nestedparens"></a>
229ShadyCSS `: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.