If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeNow, 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.
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.
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?
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!
"Houston: no signs of life"
Start the conversation!
// 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
}
}
// 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
}
}