Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Installing 3rd Party Code into our JS/CSS

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We now have a nice new JavaScript and CSS system that lives entirely inside of the assets/ directory. Let's move our public styles into this. Open public/styles/app.css, copy all of this, delete the entire directory... and then paste into the new app.css. Thanks to the encore_entry_link_tags() in base.html.twig, the new CSS is being included... and we don't need the old link tag anymore.

Go check it out. Refresh and... it still looks great!

Installing 3rd Party JavaScript/CSS Libraries

Go back to base.html.twig. What about these external link tags for bootstrap and FontAwesome? Well, you can totally keeps these CDN links. But we can also process this stuff through Encore. How? By installing Bootstrap and FontAwesome as vendor libraries and importing them.

Remove all of these link tags... and then refresh. Yikes! It's back to looking like I designed this site. Let's... first re-add bootstrap. Find your terminal. Since the watch command is running, open a new terminal tab and then run:

yarn add bootstrap --dev

Tip

If you're using NPM run:

npm add bootstrap --include=dev

This does three things. First, it adds bootstrap to our package.json file. Second it downloads bootstrap into our node_modules/ directory... you would find it down here. And third, it updated the yarn.lock file with the exact version of bootstrap that it just downloaded.

If we stopped now... this wouldn't make any difference! We downloaded bootstrap - yay - but we're not using it.

To use it, we need to import it. Go into app.css. Just like in JavaScript files, we can import from inside CSS files by saying @import and then the file. We could reference a file in the same directory with ./other-file.css. Or, if you want to import something from the node_modules/ directory in CSS, there's a trick: a ~ and then the package name: bootstrap.

@import '~bootstrap';
... lines 2 - 34

That's it! As soon as we did that, Encore's watch function rebuilt our app.css file... which now includes Bootstrap! Watch: refresh the page and... we're back! So cool!

The two other things we're missing are FontAwesome and a specific Font. To add those, head back to the terminal and run:

yarn add @fontsource/roboto-condensed --dev

Full disclosure: I did some searching before recording so that I knew the names of all the packages we need. You can search for packages at https://npmjs.com.

Let's also add the last one we need:

yarn add @fortawesome/fontawesome-free --dev

Again, this downloaded the two libraries into our project... but doesn't automatically use them yet. Because those libraries both hold CSS files, go back to our app.css file and import them: @import '~' then @fortawesome/fontawesome-free. And @import '~@fontsource/roboto-condensed'.

@import '~bootstrap';
@import '~@fortawesome/fontawesome-free';
@import '~@fontsource/roboto-condensed';
... lines 5 - 34

The first package should fix this icon... and the second should cause the font to change on the whole page. Watch the font when we refresh... it did change! But, uh... the icons are still kind of broken.

Importing Specific Files from node_modules/

To be totally honest, I'm not sure why that doesn't work out-of-the box. But the fix is kind of interesting. Hold command on a Mac - or ctrl otherwise - and click this fontawesome-free string.

When you use this syntax, it goes into your node_modules/ directory, into @fortawesome/fontawesome-free... and then if you don't put any filename after this, there's a mechanism where this library tells Webpack which CSS file it should import. By default, it imports this fontawesome.css file. For some reason... that doesn't work. What we want is this all.css.

And we can import that by adding the path: /css/all.css. We don't need the minified file because Encore handles minifying for us.

@import '~bootstrap';
@import '~@fortawesome/fontawesome-free/css/all.css';
@import '~@fontsource/roboto-condensed';
... lines 5 - 34

And now... we're back!

The main reason I love Webpack Encore and this system is that it allows us to use proper imports. We can even organize our JavaScript into small files - putting classes or functions into each - and then import them when we need them. There's no more need for global variables.

Webpack also allows us to use more serious stuff like React or Vue: you can even see, in webpack.config.js, the methods to activate those.

But usually, I like using a delightful JavaScript library called Stimulus. And I want to tell you about it next.

Leave a comment!

15
Login or Register to join the conversation
DSKZPT Avatar

I knoooow I'm early - But my `~bootstrap` isn't working and throws an error on compiling (not found).
If I use `import "../node_modules/bootstrap"` anything works well.

Do you have any hint to fix this?

1 Reply

Hey DSKZPT!

Ha! That's ok that you're early :). Hmm, that is super odd. You have this inside of assets/styles/app.css?


@import '~bootstrap';

Let me know :).

Cheers!

1 Reply
DSKZPT Avatar

yeah... my fault, i added it to the app.js 🤦🏻‍♂️

The good thing in making mistakes - you learn something!
The more mistakes you make, the smarter you get :D

Thanks for your answer and these great tutorials!

Reply

Hey DSKZPT!

Ah, awesome! Np. Bootstrap is a weird one... since it provides both JavaScript AND CSS. If you put that import in app.js, it knows to import the Bootstrap JavaScript. But then that SAME import in a CSS file tells Webpack to import the CSS. Pretty cool and pretty smart. But also, a bit magical ;).

Cheers and thanks for the nice words!

Reply
Sahetmyrat Avatar
Sahetmyrat Avatar Sahetmyrat | posted 6 months ago

Hello, I've imported Quilljs text styling library: @import "~quill"; But it didn't build.
(16:3) node_modules\quill\dist\quill.js Unclosed bracket

How can I solve that? Or isn't Quill compatible with Symfony? Thanks!

Reply

Hey Sahetmyrat,

I don't know that library, but it has nothing to do with Symfony, although it may not be compatible with NodeJS. Try importing the JS and CSS files from a JS file. In your app.js file (or any other) add this

import 'quill';
import 'quill/dist/{the-css-file}';

Cheers!

Reply
akincer Avatar

Hey folks, has there been a change in recent Symfony/Twig versions that would cause variables passed to a Twig template not to be updated on calling render() after a form submit?

That's what I'm seeing when trying to use CraueFormFlowBundle and the lack of variables sent to Twig updating is breaking things. I've validated using logging and {{ dump() }} that the value being sent on render() SHOULD be updated but isn't.

I'm guessing disabling caching might fix this but surely that isn't the best solution.

Reply
Yactouat Avatar
Yactouat Avatar Yactouat | posted 1 year ago

thanks that was a great course, wishful thinking => can we have the js part in typescript ? :)

Reply
Santosh kalwar Avatar
Santosh kalwar Avatar Santosh kalwar | posted 1 year ago

Hey @weaverryan

Awesome stuff. Can I use this material to teach my students about introducing Symfony 6?

I am looking forward to your answer.

Reply

Hi Santosh kalwar!

Absolutely! This tutorial is totally free and open to anyone. Feel free to use it for your students in any way that you want - that would be great :). If you have any questions, let us know.

Cheers!

Reply
Santosh kalwar Avatar
Santosh kalwar Avatar Santosh kalwar | weaverryan | posted 1 year ago

Thank you!

Reply

Hey there,

I'm not sure why but when using SCSS, if you import vendors in your scss files, vendor styles get compiled into the app.css file instead of in a vendor file. I've been having this problem since the first versions of Encore. The easy fix was to import these vendor scss file from javascript instead but I was wondering if there was a way to do that from the scss files and still get that nice vendor css file?

<br /># app.scss<br />@import '~bootstrap';<br />@import '~@fortawesome/fontawesome-free/scss/fontawesome';<br />@import '~@fontsource/roboto-condensed';<br />

Reply

Hey julien_bonnier!

Oh really, that's very interesting! This is not something I've noticed before. So, to make sure I understand correctly, when you import from app.scss, Webpack does NOT split the vendor CSS into some node_modules~bootstrap~fortawsome...css type of file, but instead of compiles it straight into app.css with your custom JavaScript. Correct? Hmm. If that's the case, that sounds like some weird, deep behavior: something that would be difficult to track down. My guess is that the SCSS system imports all of that vendor stuff BEFORE webpack becomes aware of it. So by the time Webpack sees all of the content, it's all "coming from app.scss", which is incorrect.

So, unfortunately, I don't have an answer. My best advice is to stick with your workaround, but that's unfortunate!

Cheers!

Reply
Kaizoku Avatar
Kaizoku Avatar Kaizoku | posted 1 year ago

Hi Ryan,
I wrote a comment on Stackoverflow about why fontawesome is not working out of the box
it's here : https://stackoverflow.com/a...
And fun fact this is actually you that explained why in one of your video, so all the credit is on you ;)

Reply

Hey Kaizoku!

Haha, OMG, did I really? I have a famously bad memory 😆. I wish FontAwesome would fix that to make things easier! And thanks for posting that answer on Stackoverflow for others - that's very cool of you.

Cheers!

Reply
Cat in space

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

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.0.2",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "symfony/asset": "6.0.*", // v6.0.3
        "symfony/console": "6.0.*", // v6.0.3
        "symfony/dotenv": "6.0.*", // v6.0.3
        "symfony/flex": "^2", // v2.1.5
        "symfony/framework-bundle": "6.0.*", // v6.0.4
        "symfony/monolog-bundle": "^3.0", // v3.7.1
        "symfony/runtime": "6.0.*", // v6.0.3
        "symfony/twig-bundle": "6.0.*", // v6.0.3
        "symfony/ux-turbo": "^2.0", // v2.0.1
        "symfony/webpack-encore-bundle": "^1.13", // v1.13.2
        "symfony/yaml": "6.0.*", // v6.0.3
        "twig/extra-bundle": "^2.12|^3.0", // v3.3.8
        "twig/twig": "^2.12|^3.0" // v3.3.8
    },
    "require-dev": {
        "symfony/debug-bundle": "6.0.*", // v6.0.3
        "symfony/stopwatch": "6.0.*", // v6.0.3
        "symfony/web-profiler-bundle": "6.0.*" // v6.0.3
    }
}
userVoice