Chapters
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
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'; | |
Show Lines
|
// ... 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'; | |
Show Lines
|
// ... 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'; | |
Show Lines
|
// ... 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.
17 Comments
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!
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?
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!
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!
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!
Hi I'm running yarn add bootstrap --dev
and I get the error below. I'm running this just after running composer require encore:1.14.0
(and yarn watch
, both ran fine). I'm backtracking steps as in the next lecture when I add <div data-controller="hello"></div>
to homepage.html.twig it does not show up on my site.
Error when running yarn add bootstrap --dev
WAIT Compiling... 12:20:11 pm
ERROR Failed to compile with 2 errors 12:20:11 pm
error in ./node_modules/css-loader/dist/runtime/cssWithMappingToString.js 12:20:11 pm
Module build failed: Error: ENOENT: no such file or directory, open 'C:\Users\sbhe0002\mixed_vinyl\node_modules\css-loader\dist\runtime\cssWithMappingToString.js'
error in ./assets/styles/app.css 12:20:11 pm
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed: Error: ENOENT: no such file or directory, open 'C:\Users\sbhe0002\mixed_vinyl\node_modules\css-loader\dist\runtime\cssWithMappingToString.js'
at processResult (C:\Users\sbhe0002\mixed_vinyl\node_modules\webpack\lib\NormalModule.js:764:19)
at C:\Users\sbhe0002\mixed_vinyl\node_modules\webpack\lib\NormalModule.js:866:5
at C:\Users\sbhe0002\mixed_vinyl\node_modules\loader-runner\lib\LoaderRunner.js:400:11
at C:\Users\sbhe0002\mixed_vinyl\node_modules\loader-runner\lib\LoaderRunner.js:221:19
at C:\Users\sbhe0002\mixed_vinyl\node_modules\webpack\lib\NormalModule.js:836:24
at Array.eval (eval at create (C:\Users\sbhe0002\mixed_vinyl\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:9:1)
at runCallbacks (C:\Users\sbhe0002\mixed_vinyl\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:43:15)
at ReadFileContext.<anonymous> (C:\Users\sbhe0002\mixed_vinyl\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:249:5)
at ReadFileContext.callback (C:\Users\sbhe0002\mixed_vinyl\node_modules\graceful-fs\graceful-fs.js:123:16)
at FSReqCallback.readFileAfterOpen [as oncomplete] (node:fs:327:13)
Entrypoint app [big] 697 KiB = runtime.js 14.6 KiB vendors-node_modules_symfony_stimulus-bridge_dist_index_js-node_modules_core-js_modules_es_da-03e5c3.js 644 KiB app.js 38.8 KiB
webpack compiled with 2 errors
Hey @CindySymf!
Well that is not a fun error! Honestly, it looks like something failed to download - it's super odd. One of the node vendor packages you downloaded is referring to another vendor file... which doesn't appear to be there! That just... shouldn't happen - I can't think of how this could be something that your code is causing.
Try these 2 things:
1) Remove the node_modules/
directory by hand. Then run yarn install
again. Then try it again.
2) If that doesn't work, then try yarn upgrade
to upgrade the dependencies. It's possible things are just out-of-date enough that it's causing some weird issue.
And let me know how it goes :)
Cheers!
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!
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!
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.
thanks that was a great course, wishful thinking => can we have the js part in typescript ? :)
Hey @weaverryan
Awesome stuff. Can I use this material to teach my students about introducing Symfony 6?
I am looking forward to your answer.
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!
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 />
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!
"Houston: no signs of life"
Start the conversation!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.1",
"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.4.5
"symfony/framework-bundle": "6.0.*", // v6.0.4
"symfony/monolog-bundle": "^3.0", // v3.7.1
"symfony/runtime": "6.4.3", // v6.4.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
}
}
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 ;)