babel-loader

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

RepLogApp uses the ES6 class syntax. And, at the end of the last tutorial, we used a tool called Babel to transpile this new ES6 code to older code that will run on older browsers. But... we lost that when we moved to Webpack. Yep, if you look at the dumped rep_log.js file and search for class RepLogApp, there it is! Still using the ES6 class syntax.

Installing babel-loader

It's time to bring Babel back. How? Well, we still have the .babelrc file from the last tutorial, which configures Babel to do the transpiling we want:

4 lines .babelrc
{
"presets": ["env"]
}

So if we could somehow tell Webpack to pass all .js files through Babel... we'd be done!

How do we do this? How can we tell Webpack to filter our code through something external? With a very powerful system in Webpack called loaders. Google for "babel-loader" and find its GitHub page. Let's get this guy installed. Copy the yarn add line, though we already have webpack installed.

Find your terminal and run it with --dev on the end:

yarn add babel-loader@7 babel-core babel-preset-env --dev

Tip

Latest version of babel-loader requires a newer version of Babel - so we’re staying on version 7.

This installs Babel itself and the env preset: both things we installed in the last tutorial. It also installed babel-loader.

About Loaders

Here's how the loader system works. In Webpack, you can say:

Yo, Webpack! When I require this file, I want you to send it through this loader so that it can make whatever changes it wants.

In this case, we want to send RepLogApp through babel-loader. How? Of course, there are two ways.

The Inline Loader Sytnax

The first is a special syntax right when you require the module. Before the name of the module, add babel-loader!:

... line 1
const RepLogApp = require('babel-loader!./Components/RepLogApp');
... lines 3 - 8

Read this from right to left. It says: require this module and then pass it through babel-loader. You can even have multiple loaders, each separated by an exclamation mark, processing from right to left. Each loader can even accept options via query parameters when using this syntax.

Let's try it! Refresh! Yes.... nothing is broken. And in the built rep_log.js file, search for RepLogApp. The class key is gone! Replaced by fancy code that mimics its behavior.

Babel is back!

Using a Loader Globally

This is great! Except that I do not want to have to add this to every require statement! Thankfully, Webpack also has a global way to apply loaders.

Remove the inline loader syntax:

... line 1
const RepLogApp = require('./Components/RepLogApp');
... lines 3 - 8

And open webpack.config.js. Add a new module key set to {} and a sub-key called rules set to an array:

... lines 1 - 3
module.exports = {
... lines 5 - 13
module: {
rules: [
... lines 16 - 21
]
},
... lines 24 - 29
};

Here's the deal: each rule will contain a filename regular expression and a loader that should be applied whenever a file matches that. Add {} for this first loader with a test key. We want to apply the loader to all files that end in .js:

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

That's what this regular expression matches. Below this, add use, with loader: 'babel-loader':

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

That is it! Now, every .js file will go through Babel! Woohoo!

Restart the webpack script:

./node_modules/.bin/webpack --watch

And check out the built rep_log.js file. Try to find RepLogApp again. Yep, the same, beautiful, transpiled code.

Leave a comment!

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
        "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
    }
}