Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add polyfills on demand section to shimming page #1528

Merged
merged 6 commits into from
Aug 25, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/content/guides/shimming.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ contributors:
- pksjce
- jhnns
- simon04
- jeremenichelli
related:
- title: Reward modern browser users script
url: https://hackernoon.com/10-things-i-learned-making-the-fastest-site-in-the-world-18a0e1cdf4a7#c665
- title: useBuiltIns in babel-preset-env
url: https://github.com/babel/babel-preset-env#usebuiltins
---

`webpack` as a module bundler can understand modules written as ES2015 modules, CommonJS or AMD. But many times, while using third party libraries, we see that they expect dependencies which are global, AKA `$` for `jquery`. They might also be creating global variables which need to be exported. Here we will see different ways to help webpack understand these __broken modules__.
Expand Down Expand Up @@ -158,3 +164,82 @@ module.exports = {
## Node Built-Ins

Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples.


## Loading polyfills on demand

It's common in web projects to include polyfills in the main bundle. This is not recommended because we are penalizing modern browsers users by making them download a bigger file with unneeded scripts.

The simplest way to mitigate this is by adding a separate entry point in your webpack config file including the polyfills your project needs.

```javascript
// webpack.config.js
module.exports = {
entry: {
polyfills: [
'babel-polyfill',
'whatwg-fetch'
],
main: './src/index.js'
}
// ... rest of your webpack config
};
```

An alternative is to create a new entry file and manually import these packages.

```javascript
// src/polyfills.js
import 'babel-polyfill';
import 'whatwg-fetch';
```

```javascript
// webpack.config.js
module.exports = {
entry: {
polyfills: './src/polyfills.js',
main: './src/index.js'
}
// rest of your webpack config
};
```

In your html file you need to conditionally load the `polyfills.js` file before your bundle. How you make this decision depends on the technologies and browsers you need to support.

```html
<script>
var modernBrowser = (
'fetch' in window &&
'assign' in Object
);

var scripts = [ '/main.js' ];

if (!modernBrowser) {
scripts.unshift('/polyfills.js');
}

scripts.map(function(src) {
var scriptElement = document.createElement('script');
scriptElement.async = false;
scriptElement.src = src;
document.head.appendChild(scriptElement);
});
</script>
```

T> Any script added dynamically like in the example above will run as soon as it's parsed, but we need our polyfill to run before our bundle. This is why we are setting `async` to `false` for each script.


### Smaller babel polyfill

`babel-preset-env` uses [browserslist](https://github.com/ai/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the `useBuiltIns` option _(false by default)_ which converts your global `babel-polyfill` import to a more granular feature by feature import pattern like:

```javascript
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
import "core-js/modules/web.timers";
import "core-js/modules/web.immediate";
import "core-js/modules/web.dom.iterable";
```