UNPKG

12 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
80This property is used to build the URL to the selected bundle, so you should
81only set it to values that are unable to be influenced by user-controlled data.
82If trusted types are enforced, this property should be a `TrustedScriptURL`.
83
84#### Synchronous
85
86When loaded synchronously, `webcomponents-loader.js` behaves similarly to `webcomponents-bundle.js`.
87
88The appropriate bundle will be loaded with `document.write()` to ensure that WebComponent polyfills are available for subsequent scripts and modules.
89
90Here's an example:
91
92```html
93<!-- load the webcomponents loader, which injects the necessary polyfill bundle -->
94<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
95
96<!-- load the element -->
97<script type="module" src="my-element.js"></script>
98
99<!-- use the element -->
100<my-element></my-element>
101```
102
103#### Asynchronous
104
105When loaded asychronously with the `defer` attribute, polyfill bundles will be loaded asynchronously,
106which means that scripts and modules that depend on webcomponents APIs _must_ be loaded
107using `WebComponents.waitFor` function.
108
109The `WebComponents.waitFor` function takes a callback function as an argument, and will evaluate that callback after the polyfill bundle has been loaded.
110
111The callback function should load scripts that need the polyfills (typically via `import('my-script.js')`) and
112should return a promise that resolves when all scripts have loaded.
113
114Here's an example:
115
116```html
117<!-- Load polyfills; note that "loader" will load these async -->
118<script
119 src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
120 defer
121></script>
122
123<!-- Load a custom element definitions in `waitFor` and return a promise -->
124<script type="module">
125 WebComponents.waitFor(() => {
126 // At this point we are guaranteed that all required polyfills have
127 // loaded, and can use web components API's.
128 // The standard pattern is to load element definitions that call
129 // `customElements.define` here.
130 // Note: returning the import's promise causes the custom elements
131 // polyfill to wait until all definitions are loaded and then upgrade
132 // the document in one batch, for better performance.
133 return import('my-element.js');
134 });
135</script>
136
137<!-- Use the custom element -->
138<my-element></my-element>
139```
140
141The `WebComponents.waitFor` function may be called multiple times, and the callback functions will be processed in order.
142
143Here's a more complicated example:
144
145```html
146<!-- Load polyfills; note that "loader" will load these async -->
147<script
148 src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"
149 defer
150></script>
151
152<script type="module">
153 WebComponents.waitFor(async () => {
154 if (!window.fetch) {
155 await import('node_modules/fetch-polyfill/fetch.js');
156 }
157 return import('my-element.js');
158 });
159</script>
160
161<script type="module"></script>
162```
163
164#### Trusted Types
165
166If you're using the loader on a page that enforces the `trusted-types` Content
167Security Policy, you'll need to allow the `webcomponents-loader` policy name so
168that the loader can dynamically create and insert a `<script>` for the polyfill
169bundle it selects based on feature detection. If you set `WebComponents.root`
170(which is rare), it should be set to a `TrustedScriptURL` for Trusted Types
171compatibility.
172
173### WebComponentsReady event
174
175The `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.
176
177### `custom-elements-es5-adapter.js`
178
179According 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`.
180
181As 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.
182
183**The adapter must NOT be compiled.**
184
185## Browser Support
186
187The polyfills are intended to work in the latest versions of evergreen browsers. See below
188for our complete browser support matrix:
189
190| Polyfill | Edge | IE11+ | Chrome\* | Firefox\* | Safari 9+\* | Chrome Android\* | Mobile Safari\* |
191| --------------- | :--: | :---: | :------: | :-------: | :---------: | :--------------: | :-------------: |
192| Custom Elements | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
193| Shady CSS/DOM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
194
195\*Indicates the current version of the browser
196
197The polyfills may work in older browsers, however require additional polyfills (such as classList, or other [platform](https://github.com/webcomponents/webcomponents-platform)
198polyfills) to be used. We cannot guarantee support for browsers outside of our compatibility matrix.
199
200## Known Issues
201
202- [Style encapsulation (inline styling in components) does not work out of the box](#shadycss)
203- [Custom element's constructor property is unreliable](#constructor)
204- [ShadyCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work](#nestedparens)
205
206### Style encapsulation (inline styling in components) does not work out of the box. <a id="shadycss"></a>
207
208The ShadowDOM polyfill does not properly support CSS in ShadowDoM out of the box:
209
210- Any styles inside components have an effect on the whole document (instead of on the component only - the encapsulation is broken).
211- Any shadow-dom specific selectors (like `:host`) do not work.
212
213You can fix those issues by manually calling the `ShadyCSS` APIs. See [ShadyCSS usage](https://github.com/webcomponents/shadycss#usage).
214
215### Custom element's constructor property is unreliable <a id="constructor"></a>
216
217See [#215](https://github.com/webcomponents/webcomponentsjs/issues/215) for background.
218
219In 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.
220
221It's worth noting that `customElement.__proto__.__proto__.constructor` is `HTMLElementPrototype` and that the prototype chain isn't modified by the polyfills(onto `ElementPrototype`, etc.)
222
223### ShadyCSS: :host(.zot:not(.bar:nth-child(2))) doesn't work <a id="nestedparens"></a>
224
225ShadyCSS `: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.
226
227### Manually Building
228
229If you wish to build the bundles yourself, you'll need `node` and `npm` on your system:
230
231- install [node.js](http://nodejs.org/) using the instructions on their website
232- use `npm` to install [gulp.js](http://gulpjs.com/): `npm install -g gulp`
233- make sure you have Java installed per https://www.npmjs.com/package/google-closure-compiler#java-version
234
235Now you are ready to build the polyfills with:
236
237 # install dependencies
238 npm install
239 # build
240 npm run build
241
242The builds will be placed into the root directory.
243
244## Contribute
245
246See the [contributing guide](CONTRIBUTING.md)
247
248## License
249
250Everything in this repository is BSD style license unless otherwise specified.
251
252Copyright (c) 2015 The Polymer Authors. All rights reserved.
253
254## Changes in version 2.x
255
256- The HTML Imports polyfill has been removed. Given that ES modules have shipped in
257 most browsers, the expectation is that web components code will be loaded via
258 ES modules.
259- When using `webcomponents-loader.js` with the `defer` attribute, scripts that rely on the polyfills _must_ be loaded using `WebComponents.waitFor(loadCallback)`.