x)
- [ ] new
- [ x ] build
- [ x ] serve
- [ x ] test
- [ x ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc
Currently, there is no way to define custom polyfills that are only loaded for ES5 or ES2015+ browsers. While the polyfills for ES5 browsers are added automatically since some minor versions, we cannot influence them. This is, however, important when using web components b/c in this case we need to load polyfills for ES5 browsers and shims for ES2015+. The latter one is required for ES2015+ browsers if we don't use differential loading and downlevel to ES5. This feature request proposes a solution.
While it's not the most known feature, we can already define that scripts go into specific additional bundles. The following extra-polyfills script would be put into a bundle extra.js
"scripts":[
{
"input": "src/extra-polyfills.ts",
"bundleName": "extra"
}
]
This proposal would just add a type property telling the CLI for which browsers the bundle is intented:
"scripts":[
{
"input": "src/extra-polyfill.ts",
"bundleName": "extra",
"type": "module"
}
]
For the time being, we could go with three values: all (all browsers), module (ES2015+ browsers), and nomodule (ES5 browsers).
If we extend the possibilities of differential loading we could use this type property to point to more fine-grained information according to the srcset property.
This approach also solves the problem that specific polyfills have to be loaded in a specific order. E. g. the web component polyfills need to be loaded after the ES5 polyfills (core.js, etc.)
ng new could generate own polyfill files like polyfills-es2015.ts and polyfills-es5.ts and point to it with specific properties in angular.json. However, this is more intrusive, leads to confusion esp. if not needed and is less flexible.
This approach also solves the problem that specific polyfills have to be loaded in a specific order.
Is there a problem that we are not aware of? The order of polyfills should be retained already.
Also potentially, following differential loading, we can make certain polyfills added based on the known browser features and the features that the app needs. Using browserlist and caniuse.
Also, note that at the moment, there is already a polyfills option in angular.json
Regarding the order: If we put the additional polyfills to the end of the es5-polyfills this issue would also be solved. Currently, however, we cannot influence the es5-polyfills from the outside.
The browser list idea is a really nice one. In this case, we need a mapping b/w polyfills and caniuse features. This way, we can answer the question "do we need this polyfill at all"? But it doesn't answer the question "do we have to load this polyfill now". To answer this question, we need to know whether the polyfill is needed for module- or nomodule-browsers. Of course, we could infer this by joining (in the sense of a relational DB) module/nomodule browsers with browsers supporting web components. On the other side, this is more difficult and I'm not sure if it is needed.
When it comes to web component polyfills the rule of tumb "an es5 browser needs the polyfill; an es2015+ browser does not" will be a safe and simple assumption once edge is using chromium.
I was actually thinking of opening a feature request along these same lines. Thank you!
As mentioned above, the story of web component polyfills is getting increasingly easier, but at the time of this writing it's definitely still trickier than the normal es5 vs es2015+ divide.
I like the idea of adding polyfills based on browserslist + app features being used, but (again, thinking of the web components use case) I'd imagine that may constrain developers to use web components via Angular only, unless the feature detection were super robust.
This seems like a no brainer, maybe it would be even more obvious with a polyfills.es5.ts and a regular polyfills.ts file? For the same reason we all love the new differential loading, it now pains me to have to put:
import 'core-js/es/object';
in my polyfills.ts file, just because I use Object.entries() in my app, and also still need to support IE 11, knowing that all the es2015 browsers already support this :(
https://caniuse.com/#feat=object-entries
This is a good idea.
I was very excited about es5BrowserSupport when I first saw it but soon feel it is useless to us bc if you want to support ie11, you often need to load other things for ie11 besides the es2015 polyfills. Why don't just a polyfill file will load only for nomodule browsers and let the developer decide what to be put in the file?
Without polyfills, my app won't run in IE11. I've created an example project here and you can see the relevant code here.
I was excited that maybe the compiler would know which polyfills I'd need automatically somehow but this doesn't seem to be the case. I'm confused what differential loading is even doing if we still need to manually import polyfills?
According to this article,
the CLI will automatically build the necessary JS bundles with the necessary polyfills for your targets.
Is that false?
@adamdport
Is that false?
It's true, but only for native javascript features. So if you have some other polyfills such as css vars, interception observer, then you have no luck.
@crysislinux
It's true, but only for native javascript features.
Not quite. When you set IE11 in the browserslist file, the Array.prototype.includes polyfill won't be added either polyfills-es5 or polyfills-es2015 file.
@destus90 Array.prototype.includes is es7, not es6 or es2015
In the meanwhile, what would be the correct way in Angular 8 to add a polyfill that is not automatically added (and makes IE11 crash if omitted) like import 'core-js/es7/array'; for example?
I guess this doc isn't especially explicit:
https://angular.io/guide/browser-support
But for additional polyfills, you just add them at the end of the polyfills.ts in the "Application Imports" section, like:
/***************************************************************************************************
* APPLICATION IMPORTS
*/
import 'core-js/es7/array';
Is there a way to exclude specific polyfills?
For my case would be to remove core-js/es6/string to avoid conflict with Microsoft Script Resource AXD code which is already included for SharePoint 2013.
The current recommended solution is to inject scripts through the workspace configuration and load the polyfills for both environments.
Separating between module/nomodule scripts is very error prone and we prefer to keep it entirely under CLI control at this point.
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
This seems like a no brainer, maybe it would be even more obvious with a polyfills.es5.ts and a regular polyfills.ts file? For the same reason we all love the new differential loading, it now pains me to have to put:
import 'core-js/es/object';in my polyfills.ts file, just because I use Object.entries() in my app, and also still need to support IE 11, knowing that all the es2015 browsers already support this :(
https://caniuse.com/#feat=object-entries