Support any Browser with PostCSS & Babel
Go back to /admin/article
and click to edit one of the articles. View the source and search for .js
. Okay, we have several JavaScript files, because Webpack is splitting them. Click to look at build/admin_article_form.js
, which will probably contain all the non-vendor code from that entry point.
The top of the file contains some Webpack boootstrap stuff, then our code is below, still mixed in with some things that makes Webpack work.
Now, check this out: in the original admin_article_form.js
file, we created a class called ReferenceList
:
// ... lines 1 - 8 | |
$(document).ready(function() { | |
const $autoComplete = $('.js-user-autocomplete'); | |
// ... lines 11 - 44 | |
}); | |
// todo - use Webpack Encore so ES6 syntax is transpiled to ES5 | |
class ReferenceList | |
{ | |
// ... lines 50 - 134 | |
} | |
// ... lines 136 - 161 |
And we also use the const
keyword for const $autoComplete
. Back in the compiled file, search for $autoComplete
. Woh! It's not const $autoComplete
, it's var $autoComplete
! And if you search for ReferenceList
... and get down to the class... there's no class syntax! It's wrapped in some sort of a "pure" function thingy.
Surprise! Something is rewriting our code! But, who? And, why?
Hello Babel
The who is Babel: an amazing library that has the superpower of reading your JavaScript and rewriting it to older JavaScript that's compatible with older browsers. And this is seriously important! Because if JavaScript comes out with a new feature, we do not want to wait 10 years for all of the browsers to support it! Babel solves this: you can use brand new language features and it compiles it to boring, traditional code.
But... wait. How is Babel deciding which browsers our site needs to support? Different sites need to support different browsers... and so, in theory, Babel should be able to rewrite the code differently for different sites. For example, if you need to support super old browsers, you probably need to rewrite const
to var
. But if all of your users are awesome... like our SymfonyCasts users... and all use new browsers, then you don't need to rewrite this. In general, converting new code to old code makes your JavaScript larger, so avoiding unnecessary changes is a good thing.
Rewriting CSS for Older Browsers?
Let's answer the question of "how" we can control Babel by talking about something completely different: CSS. Babel does not rewrite CSS. But, if you think about it, it would sorta make sense.
For example, if you're using a border-radius
and need to support older browsers, you need to add some vendor prefixes, like -webkit-border-radius
. You can see one we added manually down here: we have box-shadow
, but we also have -webkit-box-shadow
to make it work in some older browsers... which we might not even need, depending on what browsers we decide we need to support:
// ... lines 1 - 13 | |
div.user-menu-container { | |
// ... lines 15 - 20 | |
-webkit-box-shadow: 0 1px 6px rgba(0, 0, 0, 0.175); | |
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.175); | |
} | |
// ... lines 24 - 90 |
Anyways, forgetting about Webpack and Babel for a minute, in the CSS world, you do not need to add these vendor prefixes by hand. Nope! There's a wonderful library that can do it for you called autoprefixer
. You write code correctly - like using box-shadow
- tell it which browsers you need to support, and it adds the vendor prefixes for you.
Enabling PostCSS
Because that sounds amazing... let's add it! In webpack.config.js
, anywhere, but how about below .enableSassLoader()
, add .enablePostCssLoader()
:
// ... lines 1 - 2 | |
Encore | |
// ... lines 4 - 56 | |
.enablePostCssLoader() | |
// ... lines 58 - 76 | |
; | |
// ... lines 78 - 79 |
PostCSS is a library that allows you to run things at the "end" of your CSS being processed. And it's the easiest way to integrate autoprefixer
.
Next, because we just changed our webpack.config.js
file, go restart Encore:
yarn watch
Hey! This is familiar! Just like when we enabled Sass, this requires us to install a few things. Copy the command, go to your open terminal and run that!
yarn add postcss-loader@^3.0.0 --dev
Ok, let's try Encore again:
yarn watch
Hmm, another error! This is kinda cool: to use PostCSS, you need to create a postcss.config.js
file. Encore walks you through that process and sets it up to use autoprefixer
to start. Copy that, go to the root of your project, create the postcss.config.js
file and paste:
module.exports = { | |
plugins: { | |
'autoprefixer': {}, | |
} | |
} |
Ok, hit Control
+ C
and try that again:
yarn watch
Sheesh! One last error. PostCSS is probably the most involved thing to get running. This error isn't as obvious:
loading PostCSS plugin failed: Cannot find module autoprefixer
We know what that word "module" means! It's trying to find that library. We told PostCSS to use autoprefixer
, but that doesn't exist in our project yet. Run:
yarn add autoprefixer --dev
And now try Encore.
Tip
If you get an error like true is not a PostCSS plugin
, either downgrade autoprefixer to version 9
or upgrade PostCSS to version 8. Basically, autoprefixer 10 doesn't play nicely with PostCSS 7 and lower.
yarn watch
No errors! So... it's probably working? Let's see it in action next and learn how we can tell PostCSS and Babel exactly which browsers we need to support.
Hey Guys, I have similar setup as per this tutorial and I have weird issue with vue2-animate library. Everything works under IE11 when my assets are in dev mode, but under production mode (yarn build) it do not animate under IE11 (one particular animation doesn't work). I have tried lots of different configurations (browserslist) including postcss-preset-env (with different stages) but it do not help.
If I will include vue2-animate directly form public without any processing it works fine under IE11.
What can I do to resolve it? I do not want to copy that css to public and include separately, I would prefer to keep it under node modules. Can I somehow add it to post css ignore? Or is there anything else that I could do?