Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

babel-loader Options & Polyfill

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Now, you may or may not have noticed it, but that build took a bit longer than normal: it took almost five seconds. That makes sense... our code is now going through Babel:

... lines 1 - 3
module.exports = {
... lines 5 - 13
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader'
}
}
]
},
... lines 24 - 29
};

But actually, most of that time is because every file is being processed through Babel... including third-party files like jQuery and Bootstrap! That's overkill.

Skipping node_modules Files

Most of the time, we expect third-party modules to already be compiled into older JavaScript. So, we don't need to re-transpile them. That may not always be the case, so just be cautious.

How can we skip third-party files? Add an exclude for /node_modules/:

... lines 1 - 3
module.exports = {
... lines 5 - 13
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
... lines 19 - 24
}
]
},
... lines 28 - 33
};

And just by making this small change, when we re-run Webpack, it's way faster:

./node_modules/.bin/webpack --watch

Instead of four and a half seconds, we're back under two seconds.

Passing babel-loader Options

But we can do better! Every loader can be passed options. If you look at the documentation for babel-loader and scroll down, eventually, you'll see those options.

For babel-loader, there's one really cool option. Under use, add an options object with cacheDirectory set to true:

... lines 1 - 3
module.exports = {
... lines 5 - 13
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
... line 20
options: {
cacheDirectory: true
}
}
}
]
},
... lines 28 - 33
};

This tells Babel to cache its results so that it doesn't need to re-transpile the same source code twice. Try running webpack:

./node_modules/.bin/webpack --watch

The first run is about the same. But try it a second time:

./node_modules/.bin/webpack --watch

Woh! 700 ms - way faster!

And, if you're curious - which I know you are - the cache files live in node_module/.cache. Kind of cool, right?

babel-polyfill

While we're talking about Babel, open your base layout: app/Resources/views/base.html.twig. We have a script tag to a Promise polyfill:

... lines 1 - 98
{% block javascripts %}
... lines 100 - 101
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.0.5/es6-promise.auto.min.js"></script>
... line 103
{% endblock %}
... lines 105 - 108

Why? Because some of our code is using the ES6 Promise object... and some older browsers don't support that. By including the polyfill, we're guaranteed to have that.

Even with Babel, this is still needed. Babel transpiles our new JavaScript syntax into old JavaScript... but it doesn't add missing features, like the Promise object.

So yes... we still need something to fill in the missing Promise object... but I do not want to keep using these global script tags!!! Delete it!

And, in your terminal, install a new library called babel-polyfill:

yarn add babel-polyfill --dev

This library will give us the Promise polyfill and actually, all Polyfills. Use it inside of layout.js - so that we get the polyfill on every page: require babel-polyfill. I'll add a little comment above this:

... lines 1 - 4
// make sure the polyfill library is loaded in this main entry
require('babel-polyfill');
... lines 7 - 11

And of course, when we refresh, everything is happy! And it would even be happy if I were using an older browser. Of course, I would be less happy using an older browser... but that's unrelated.

Anyways, let's move on to something amazing: requiring CSS from JavaScript!

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial explains the concepts of an old version of Webpack using an old version of Symfony. The most important concepts are still the same, but you should expect significant differences in new versions.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.2.0",
        "symfony/symfony": "3.3.*", // v3.3.16
        "twig/twig": "2.10.*", // v2.10.0
        "doctrine/orm": "^2.5", // v2.7.0
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.3
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.4.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "^2.0", // v2.1.2
        "doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0" // v3.3.5
    }
}

What JavaScript libraries does this tutorial use?

// package.json
{
    "dependencies": [],
    "devDependencies": {
        "babel-core": "^6.25.0", // 6.25.0
        "babel-loader": "^7.1.1", // 7.1.1
        "babel-plugin-syntax-dynamic-import": "^6.18.0", // 6.18.0
        "babel-preset-env": "^1.6.0", // 1.6.0
        "bootstrap-sass": "^3.3.7", // 3.3.7
        "clean-webpack-plugin": "^0.1.16", // 0.1.16
        "copy-webpack-plugin": "^4.0.1", // 4.0.1
        "core-js": "^2.4.1", // 2.4.1
        "css-loader": "^0.28.4", // 0.28.4
        "extract-text-webpack-plugin": "^3.0.0", // 3.0.0
        "file-loader": "^0.11.2", // 0.11.2
        "font-awesome": "^4.7.0", // 4.7.0
        "jquery": "^3.2.1", // 3.2.1
        "lodash": "^4.17.4", // 4.17.4
        "node-sass": "^4.5.3", // 4.5.3
        "resolve-url-loader": "^2.1.0", // 2.1.0
        "sass-loader": "^6.0.6", // 6.0.6
        "style-loader": "^0.18.2", // 0.18.2
        "sweetalert2": "^6.6.6", // 6.6.6
        "webpack": "^3.4.1", // 3.4.1
        "webpack-chunk-hash": "^0.4.0", // 0.4.0
        "webpack-dev-server": "^2.6.1", // 2.6.1
        "webpack-manifest-plugin": "^1.2.1" // 1.2.1
    }
}
userVoice