gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
We're on a mission to refactor all the old <script>
and <link>
tags out of our templates. For the base layout, we're half way done! There is only one script tag, which points to the app
entry:
<html lang="en"> | |
... lines 3 - 17 | |
<body> | |
... lines 19 - 90 | |
{% block javascripts %} | |
{{ encore_entry_script_tags('app') }} | |
{% endblock %} | |
</body> | |
</html> |
That's perfect.
Back on top, we do still have multiple link tags, including Bootstrap from a CDN, FontAwesome, which I apparently just committed into my public/css
directory, and some custom CSS in styles.css
:
<html lang="en"> | |
<head> | |
... lines 5 - 8 | |
{% block stylesheets %} | |
{{ encore_entry_link_tags('app') }} | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | |
<link rel="stylesheet" href="{{ asset('css/font-awesome.css') }}"> | |
<link rel="stylesheet" href="{{ asset('css/styles.css') }}"> | |
{% endblock %} | |
</head> | |
... lines 17 - 94 | |
</html> |
First, eliminate Bootstrap! In the same way that we can properly install JavaScript libraries with Yarn, we can also install CSS libraries! Woo!
In app.js
, we're already importing a single app.css
file:
... lines 1 - 7 | |
// any CSS you require will output into a single css file (app.css in this case) | |
import '../css/app.css'; | |
... lines 10 - 25 |
We could add another import right here for the Bootstrap CSS. Instead, I prefer to import just one CSS file per entry. Then, from within that CSS file, we can use the standard @import
CSS syntax to import other CSS files. To Webpack, these two approaches are identical.
Now, you might be thinking:
Don't we need to install the bootstrap CSS library?
And... yes! Well, I mean, no! Um, I mean, we already did it! In node_modules/
, look for bootstrap/
. This directory contains JavaScript but it also contains the Bootstrap CSS.
But... hmm... In JavaScript, we can say import
then simply the name of the package and... it just works! But we can't repeat that same trick for CSS.
Instead, we'll point directly to the path we want, which, in this case is probably dist/css/bootstrap.css
. Here's how: @import
, ~bootstrap
and the path: /dist/css/bootstrap.css
:
@import '~bootstrap/dist/css/bootstrap.css'; |
The ~
part is special to CSS and Webpack. When you want to reference the node_modules/
directory from within a CSS file, you need to start with ~
. That's different than JavaScript where any path that doesn't start with .
is assumed to live in node_modules/
. After the ~
, it's just a normal, boring path.
But yea... that's all we need! Move over and refresh. This looks exactly the same!
And... remember how I said that we can't simply import CSS by referencing only the package name? That was... kind of a lie. Shorten this to just ~bootstrap
:
@import '~bootstrap'; |
Go try it! Refresh and... the same!
This works thanks to a little extra feature we added to Encore... which may become a more standard feature in the future. We already know that when we import a package by its name in JavaScript, Webpack looks in package.json
, finds the main
key.... there it is and uses this to know that it should finally import the dist/js/bootstrap.js
file.
Some libraries also include these style
or sass
keys. And when they do, you only need to @import
~
and the package name. Because we're doing this from inside a CSS file, it knows to look inside package.json
for a style
key.
This is just a shortcut to do the exact same thing we had before.
Bootstrap, check! Let's keep going: the next link tag is for FontAwesome. Get rid of that and celebrate by deleting the public/css/font-awesome.css
file and this entire fonts/
directory. This feels great! We're deleting things that I never should have committed in the first place.
Next, download FontAwesome with:
yarn add font-awesome --dev
When it finishes, go back to node_modules/
and search for font-awesome/
. Got it! Nice! It has directories for css/
, less/
, scss/
whatever format we want. And fortunately, if you look inside package.json
, it also has a style
key.
Easy peasy! In app.css
, add @import '~font-awesome'
:
@import '~bootstrap'; | |
@import '~font-awesome'; |
Done. Find your browser and refresh. Let's see... down here, yes! This is a FontAwesome icon. It still works!
But this is way cooler than it seems! Internally, the FontAwesome CSS file references some font files that the user's browser needs to download: these files here. But... these files aren't in our public
directory... so shouldn't the paths to these be broken?
Close up node_modules/
and check out the public/build/
directory. Whoa! Where did this fonts/
directory come from? When Webpack sees that a CSS file refers to a font file, it copies those fonts into this fonts/
directory and rewrites the code in the final app.css
file so that the font paths point here. Yes, it just handles it.
It also automatically adds a hash to the filename that's based on the file's contents. So if we ever update the font file, that hash would automatically change and the CSS would automatically point to it. That's free browser cache busting.
Ok one more link tag to go:
<html lang="en"> | |
<head> | |
... lines 5 - 8 | |
{% block stylesheets %} | |
... lines 10 - 11 | |
<link rel="stylesheet" href="{{ asset('css/styles.css') }}"> | |
{% endblock %} | |
</head> | |
... lines 15 - 92 | |
</html> |
Remove it! Then, open css/styles.css
, copy all of this, delete that file, and, in app.css
, highlight the blue background and paste!
@import '~bootstrap'; | |
@import '~font-awesome'; | |
body { | |
position: relative; | |
background: #efefee; | |
min-height: 45rem; | |
padding-bottom: 80px; | |
} | |
html {height:100%} | |
/* NAVIGATION */ | |
.navbar-bg { | |
background: url('../images/space-nav.jpg'); | |
background-size: 80%; | |
} | |
.dropdown-menu, .dropdown-menu.show { | |
right: 0; | |
} | |
.space-brand { | |
color: #fff; | |
font-weight: bold; | |
} | |
.nav-profile-img { | |
width: 50px; | |
border: 1px solid #fff; | |
} | |
.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { | |
color: #efefee; | |
} | |
/* ADVERTISEMENT */ | |
.ad-space { | |
background: #fff; | |
border-radius: 5px; | |
border-top: 5px solid green; | |
} | |
.advertisement-img { | |
width: 150px; | |
height: auto; | |
border: 2px solid #efefee; | |
border-radius: 5px; | |
} | |
.advertisement-text { | |
font-weight: bold; | |
} | |
.quote-space { | |
background: #fff; | |
margin-top: 30px; | |
border-radius: 5px; | |
border-top: 5px solid hotpink; | |
} | |
/* ARTICLES */ | |
.main-article { | |
border: 2px solid #efefee; | |
Background: #fff; | |
border-top-left-radius: 6px; | |
border-top-right-radius: 6px; | |
} | |
.main-article img { | |
width: 100%; | |
height: 250px; | |
border-top-right-radius: 5px; | |
border-top-left-radius: 5px; | |
border-top: 5px solid lightblue; | |
} | |
.article-container { | |
border: 1px solid #efefee; | |
border-top-left-radius: 5px; | |
border-bottom-left-radius: 5px; | |
background: #fff; | |
} | |
.main-article-link, .article-container a { | |
text-decoration: none; | |
color: #000; | |
} | |
.main-article-link:hover { | |
text-decoration: none; | |
color: #000; | |
} | |
.article-title { | |
min-width: 300px; | |
} | |
@media (max-width: 440px) { | |
.article-title { | |
min-width: 100px; | |
max-width: 245px; | |
} | |
} | |
.article-img { | |
height: 100px; | |
width: 100px; | |
border-top-left-radius: 5px; | |
border-bottom-left-radius: 5px; | |
} | |
.article-author-img { | |
height: 25px; | |
border: 1px solid darkgray; | |
} | |
.article-details { | |
font-size: .8em; | |
} | |
/* PROFILE */ | |
.profile-img { | |
width: 150px; | |
height: auto; | |
border: 2px solid #fff; | |
} | |
.profile-name { | |
font-size: 1.5em; | |
} | |
.my-article-container { | |
background: #FFBC49; | |
border: solid 1px #efefee; | |
border-radius: 5px; | |
} | |
/* CREATE ARTICLE */ | |
.create-article-container { | |
min-width: 400px; | |
background-color: lightblue; | |
border-radius: 5px; | |
} | |
/* ARTICLE SHOW PAGE */ | |
.show-article-container { | |
width: 100%; | |
background-color: #fff; | |
} | |
.show-article-container.show-article-container-border-green { | |
border-top: 3px solid green; | |
border-radius: 3px; | |
} | |
.show-article-img { | |
width: 250px; | |
height: auto; | |
border-radius: 5px; | |
} | |
.show-article-title { | |
font-size: 2em; | |
} | |
.like-article, .like-article:hover { | |
color: red; | |
text-decoration: none; | |
} | |
@media (max-width: 991px) { | |
.show-article-title { | |
font-size: 1.5em; | |
} | |
.show-article-title-container { | |
max-width: 220px; | |
} | |
} | |
.article-text { | |
margin-top: 20px; | |
} | |
.share-icons i { | |
font-size: 1.5em; | |
} | |
.comment-container { | |
max-width: 600px; | |
} | |
.comment-img { | |
width: 50px; | |
height: auto; | |
border: 1px solid darkgray; | |
} | |
.commenter-name { | |
font-weight: bold; | |
} | |
.comment-form { | |
min-width: 500px; | |
} | |
@media (max-width: 767px) { | |
.comment-form { | |
min-width: 260px; | |
} | |
.comment-container { | |
max-width: 280px; | |
} | |
} | |
/* FOOTER */ | |
.footer { | |
position: absolute; | |
bottom: 0; | |
width: 100%; | |
height: 60px; /* Set the fixed height of the footer here */ | |
line-height: 60px; /* Vertically center the text there */ | |
background-color: #fff; | |
margin-top: 10px; | |
} | |
/* Sortable */ | |
.sortable-ghost { | |
background-color: lightblue; | |
} | |
.drag-handle { | |
cursor: grab; | |
} |
That's a simple step so... it should work, right? Nope! Check out the build failure:
Module not found: Can't resolve
../images/space-nav.jpg
in ourassets/css/
directory.
It doesn't show the exact file, but we only have one. Ah, here's the problem:
... lines 1 - 12 | |
/* NAVIGATION */ | |
.navbar-bg { | |
background: url('../images/space-nav.jpg'); | |
... line 17 | |
} | |
... lines 19 - 246 |
PhpStorm is super angry about it too! This background image references ../images/
, which was perfect when the code lived in the public/css/
directory. But when we moved it, we broke that path!
This is awesome! Instead of us silently not realizing we did this, we get a build error. Amazing! We can't break paths without Webpack screaming.
To fix this, let's "cut" the entire images/
directory and move it into the assets/
folder. Yep, it's gone. But Encore doesn't know to re-compile... so make a small change and save. Build successful!
Go check it out. Refresh! It works! And even better, look at the build/
folder. We have an images/
directory with space-nav.jpg
inside. Just like with fonts, Webpack sees our path, realizes that space-nav.jpg
needs to be public, and so moves it into the build/images/
directory and rewrites the background-image
code in the final CSS to point here.
The moral is this: all we need to do is worry about writing our code correctly: using the proper relative paths from source CSS file to source image file. Webpack handles the ugly details.
Now, this did break a few <img>
tags on our site that are referencing some of these files. Now that they're not in the public/
directory... they don't work. We'll handle that soon.
But next, let's get more from our CSS by using Sass.
Hey @cybernet2u!
What's your code look like that gives you this error? Encore automatically adds the CSS loader, so you should never see an error like this.
Cheers!
Any suggestions on how to install and run the latest version of font-awesome 5 with this tutorial? A source referred that we should be using @fortawesome/fontawesome-free as a package download now, not font-awesome. Any suggestions?
Hey Kensley L.!
I just did that yesterday on something :). Quick answer:
yarn add @fortawesome/fontawesome-free --dev
Then, from inside some CSS file somewhere, add:
@import '~@fortawesome/fontawesome-free/css/all.css';
There are variations - like you could only import some of the CSS, or you could import the Sass in that same package, but that's the idea. Let me know if it helps :).
Cheers!
After moving the image files from public/images into the assets folder they are not shown anymore.
Doesn't Webpack need to take care of copying these image files into the public/images folder after this step?
Hey Martin,
No, unfortunately Webpack Encore does not know what exactly files you want to copy to the public/ dir, so you have to specify it in webpack.config.js - Webpack Encore has .copyFiles() method that helps with it. It will be next in this course btw, see https://symfonycasts.com/sc... :)
Cheers!
Hi, After adding @import '~bootstrap'; in app.css
I get the following error in console:
GET http://localhost/build/~bootstrap net::ERR_ABORTED 404 (Not Found)
and bootstrap css not working :(
When i stop yarn watch and rerun it agan the app.css file goes back to the prevues version and delete the new line `@import '~bootstrap'; ` !!!???
Bootstrap.js on app.js works with out any program.
And yarn watch not working for app.css file !!
When I try to rerun the yarn watch command the app.css file removes every change and gets back to the first version when I installed encore using `composer require encore`
I don't understand why , any help please :)
Everything works fine now when I enabled `.enableSassLoader()` in webpack.config.js and changed from .css to .scss :)
Hey @Ali!
Nice job debugging! It's unfortunate that you got such an odd error originally... I actually would have expected it to work fine... but who knows. You've got it working now is all that matters :).
Cheers!
Hello!
I am trying to change the font path used for boostrap variable $font-family-sans-serif. I have upoaded my fonts in /assets/fonts and create a new copyFiles in my webpack to copy the fonts in public folder:
`
.copyFiles({
from: './assets/fonts',
to: 'fonts/[path][name].[hash:8].[ext]'
})`
In my variables.scss, I defined the font path as follow:$font-path: '/public/build/fonts';
The new value for bootstrap font-family:$font-family-sans-serif: 'Numito-Regular'
Example of a font face :<br />@font-face {<br /> font-family: 'Nunito-Bold';<br /> src: url('#{$font-path}/Nunito-Bold.eot');<br /> src: url('#{$font-path}/Nunito-Bold.eot?#iefix') format('embedded-opentype'),<br /> url('#{$font-path}/Nunito-Bold.woff2') format('woff2'),<br /> url('#{$font-path}/Nunito-Bold.woff') format('woff'),<br /> url('#{$font-path}/Nunito-Bold.ttf') format('truetype'),<br /> url('#{$font-path}/Nunito-Bold.svg#Nunito-Bold') format('svg');<br /> font-weight: bold;<br /> font-style: normal;<br />}<br />
Compilation is working well but in my page, I got a 404 for the font. Checking the network tab, I can see it's looking for the font file without the hash.
How can I make it looking for the right font file? Or maybe I should do it differently?
Thx!
Hey be_tnt
IIRC you shouldn't create separate .copyFiles()
for fonts, you should just configure $font-path
relative to your variables.scss
for example $font-path: '../fonts';
and webpack will do all the magic.
Cheers!
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.91.4
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.9.0
"league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
"league/flysystem-cached-adapter": "^1.0", // 1.0.9
"liip/imagine-bundle": "^2.1", // 2.1.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
"oneup/flysystem-bundle": "^3.0", // 3.0.3
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.3.1
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.2.5
"symfony/console": "^4.0", // v4.2.5
"symfony/flex": "^1.9", // v1.17.6
"symfony/form": "^4.0", // v4.2.5
"symfony/framework-bundle": "^4.0", // v4.2.5
"symfony/orm-pack": "^1.0", // v1.0.6
"symfony/security-bundle": "^4.0", // v4.2.5
"symfony/serializer-pack": "^1.0", // v1.0.2
"symfony/twig-bundle": "^4.0", // v4.2.5
"symfony/validator": "^4.0", // v4.2.5
"symfony/web-server-bundle": "^4.0", // v4.2.5
"symfony/webpack-encore-bundle": "^1.4", // v1.5.0
"symfony/yaml": "^4.0", // v4.2.5
"twig/extensions": "^1.5" // v1.5.4
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.2.5
"symfony/dotenv": "^4.0", // v4.2.5
"symfony/maker-bundle": "^1.0", // v1.11.5
"symfony/monolog-bundle": "^3.0", // v3.3.1
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.5
"symfony/profiler-pack": "^1.0", // v1.0.4
"symfony/var-dumper": "^3.3|^4.0" // v4.2.5
}
}
// package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.27.0", // 0.27.0
"autocomplete.js": "^0.36.0",
"autoprefixer": "^9.5.1", // 9.5.1
"bootstrap": "^4.3.1", // 4.3.1
"core-js": "^3.0.0", // 3.0.1
"dropzone": "^5.5.1", // 5.5.1
"font-awesome": "^4.7.0", // 4.7.0
"jquery": "^3.4.0", // 3.4.0
"popper.js": "^1.15.0",
"postcss-loader": "^3.0.0", // 3.0.0
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^7.0.1", // 7.3.1
"sortablejs": "^1.8.4", // 1.8.4
"webpack-notifier": "^1.6.0" // 1.7.0
}
}
now you need a loader for css
`ERROR in ./assets/styles/app.css 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders