Chapters
This course is archived!
While the concepts of this course are still largely applicable, it's built using an older version of Symfony (4) and React (16).
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.2.0
Subscribe to download the code!Compatible PHP versions: ^7.2.0
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Polyfills: fetch & Promise
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
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.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeThe fetch()
function is built into all modern browsers... which is cool because we didn't need to install any outside libraries to make AJAX requests. Yay! Except... what about older browsers? I'm looking at you IE! Google for "caniuse fetch".
The good news is that fetch()
is almost universal... ahem, IE 11. So... you might be ok to do nothing! But, for the rest of us that do have a few users on IE, yea, using fetch()
will be a problem. But, a problem we can fix!
When we use new JavaScript syntaxes - like the arrow function - behind the scenes, Babel transpiles - basically rewrites - that code into old, boring syntax that all browsers support. So, that's already handled. But, when there is a totally new feature, like fetch()
, Babel doesn't handle that. Instead, you need a polyfill: a fancy word for a library that adds a feature if it's missing.
The fetch Polyfill
Google for "fetch polyfill" to find a library from GitHub. Scroll down to find the library name: whatwg-fetch
. Copy that, find your open terminal and:
yarn add whatwg-fetch --dev
To use a JavaScript polyfill, all we need to do is import the file. Internally, it will figure out whether or not the current browser has the feature, like the global fetch()
function. If it does not, it will add it.
Super easy! To make sure fetch()
is available everywhere, we can import it from our entry file: rep_log_react.js
. Then, it will definitely be available in rep_log_api.js
. But... I like to get even crazier! Open layout.js
. Then look inside webpack.config.js
. layout
is configured as my "shared" entry... which is a fancy way of saying that layout.js
is included on every page and so its code will always run. Inside that file, import 'whatwg-fetch'
.
Show Lines
|
// ... lines 1 - 7 |
import 'whatwg-fetch'; | |
Show Lines
|
// ... lines 9 - 13 |
Every part of my app can now safely rely on the fact that the global fetch()
function will be available.
Oh, and because I love digging in to see how things work, let's go check out the polyfill code! Open node_modules
, search for whatwg
, expand its directory and open fetch.js
. This is the file we just imported.
Look all the way at the bottom: it's a self-executing function. It passes this
into the function, which in a browser environment, is the global window
object. Then, on top, that window
object is passed as a self
. And because all global variables & functions are actually properties on the window
object, it's able to ask:
Hey! Does the window variable have the global
fetch()
function on it?
If it does, it just returns. If it does not, the rest of this code works to define and add it. There it is: self.fetch =
. This is a polyfill in action - kinda cool.
The Promise Polyfill
Go back to the fetch
polyfill docs. Ah, it says that we also need to use a Promise
polyfill for older browsers. We can literally see this inside of the fetch
polyfill: it assumes that a Promise
class is available.
Let's polyfill it to be safe: click into the library they recommend. Cool: copy the name, move over, and:
yarn add promise-polyfill --dev
When it finishes, head back to the docs. Interesting: this shows two different import options. You can use the second one to import a Promise
object, but without adding a new global variable. Because we do want to guarantee that a global Promise
variable exists, copy the first one. In layout.js
, paste!
Show Lines
|
// ... lines 1 - 8 |
import 'promise-polyfill/src/polyfill'; | |
Show Lines
|
// ... lines 10 - 14 |
To make sure we didn't break anything, go back to the tab that's running encore and restart it:
yarn run encore dev-server
Perfect! We now support older browsers... ahem, IE.
4 Comments
Hey @danielb
Probably because Ryan wanted to show how things work in a deeper level and to avoid including another dependency into the project, it may overwhelm people :)
Cheers!
Shouldn't the promise pollyfill be imported before the fetch pollyfill ?
Hey Graymath technology
That's a good question. I believe it doesn't matter because no code (app code) is being executed at "import" time, but anyways if you can confirm it, would be great.
Cheers!
"Houston: no signs of life"
Start the conversation!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.2.0",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // v1.8.0
"doctrine/doctrine-bundle": "^1.6", // 1.9.1
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.3
"doctrine/doctrine-fixtures-bundle": "~3.0", // 3.0.2
"doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.1
"doctrine/orm": "^2.5", // v2.7.2
"friendsofsymfony/jsrouting-bundle": "^2.2", // 2.2.0
"friendsofsymfony/user-bundle": "dev-master#4125505ba6eba82ddf944378a3d636081c06da0c", // dev-master
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.0
"sensio/framework-extra-bundle": "^5.1", // v5.2.0
"symfony/asset": "^4.0", // v4.1.4
"symfony/cache": "^3.3|^4.0", // v4.1.4
"symfony/console": "^4.0", // v4.1.4
"symfony/flex": "^1.0", // v1.21.6
"symfony/form": "^4.0", // v4.1.4
"symfony/framework-bundle": "^4.0", // v4.1.4
"symfony/lts": "^4@dev", // dev-master
"symfony/monolog-bundle": "^3.1", // v3.3.0
"symfony/polyfill-apcu": "^1.0", // v1.9.0
"symfony/property-access": "^3.3|^4.0", // v4.1.4
"symfony/property-info": "^3.3|^4.0", // v4.1.4
"symfony/serializer": "^3.3|^4.0", // v4.1.4
"symfony/swiftmailer-bundle": "^3.1", // v3.2.3
"symfony/twig-bundle": "^4.0", // v4.1.4
"symfony/validator": "^4.0", // v4.1.4
"symfony/yaml": "^4.0", // v4.1.4
"twig/twig": "2.10.*" // v2.10.0
},
"require-dev": {
"easycorp/easy-log-handler": "^1.0.7", // v1.0.7
"symfony/debug-bundle": "^3.3|^4.0", // v4.1.4
"symfony/dotenv": "^4.0", // v4.1.4
"symfony/maker-bundle": "^1.5", // v1.5.0
"symfony/phpunit-bridge": "^4.0", // v4.1.4
"symfony/stopwatch": "^3.3|^4.0", // v4.1.4
"symfony/var-dumper": "^3.3|^4.0", // v4.1.4
"symfony/web-profiler-bundle": "^3.3|^4.0", // v4.1.4
"symfony/web-server-bundle": "^4.0" // v4.1.4
}
}
What JavaScript libraries does this tutorial use?
// package.json
{
"dependencies": {
"@babel/plugin-proposal-object-rest-spread": "^7.12.1" // 7.12.1
},
"devDependencies": {
"@babel/preset-react": "^7.0.0", // 7.12.5
"@symfony/webpack-encore": "^0.26.0", // 0.26.0
"babel-plugin-transform-object-rest-spread": "^6.26.0", // 6.26.0
"babel-plugin-transform-react-remove-prop-types": "^0.4.13", // 0.4.13
"bootstrap": "3", // 3.3.7
"copy-webpack-plugin": "^4.4.1", // 4.5.1
"core-js": "2", // 1.2.7
"eslint": "^4.19.1", // 4.19.1
"eslint-plugin-react": "^7.8.2", // 7.8.2
"font-awesome": "4", // 4.7.0
"jquery": "^3.3.1", // 3.3.1
"promise-polyfill": "^8.0.0", // 8.0.0
"prop-types": "^15.6.1", // 15.6.1
"react": "^16.3.2", // 16.4.0
"react-dom": "^16.3.2", // 16.4.0
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^7.0.0", // 7.3.1
"sweetalert2": "^7.11.0", // 7.22.0
"uuid": "^3.2.1", // 3.4.0
"webpack-notifier": "^1.5.1", // 1.6.0
"whatwg-fetch": "^2.0.4" // 2.0.4
}
}
Why not axios?