UNPKG

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