gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Cuando instalamos Webpack Encore, su receta nos dio este nuevo directorio assets/
. Mira el archivo app.js
. Es interesante. Observa cómo importa este archivo bootstrap
. En realidad es bootstrap.js
: este archivo de aquí. La extensión .js
es opcional.
Esta es una de las cosas más importantes que nos da Webpack: la capacidad de importar un archivo JavaScript de otro. Podemos importar funciones, objetos... realmente cualquier cosa desde otro archivo. Vamos a hablar más sobre este archivobootstrap.js
dentro de un rato.
Esto también importa un archivo CSS? Si no has visto esto antes, puede parecer... raro: ¿JavaScript importando CSS?
Para ver cómo funciona todo esto, en app.js
, añade un console.log()
.
... lines 1 - 12 | |
console.log('Hi! My name is app.js!'); |
Y app.css
ya tiene un fondo de cuerpo... pero añade un !important
para que podamos ver definitivamente si se está cargando.
body { | |
background-color: lightgray ; | |
} |
Vale... ¿entonces quién lee estos archivos? Porque... no viven en el directorio public/
... así que no podemos crear etiquetas script
o link
que apunten directamente a ellos.
Para responder a esto, abre webpack.config.js
. Webpack Encore es un binario ejecutable: vamos a ejecutarlo en un minuto. Cuando lo hagamos, cargará este archivo para obtener su configuración.
Y aunque hay un montón de funciones dentro de Webpack, lo único en lo que tenemos que centrarnos ahora es en esta: addEntry()
. Este app
puede ser cualquier cosa... como dinosaur
, no importa. Te mostraré cómo se utiliza en un minuto. Lo importante es que apunta al archivo assets/app.js
. Por ello,app.js
será el primer y único archivo que Webpack analizará.
Esto es bastante bueno: Webpack leerá el archivo app.js
y luego seguirá todas las declaraciones deimport
recursivamente hasta que finalmente tenga una colección gigante de todo el JavaScript y el CSS que nuestra aplicación necesita. Entonces, lo escribirá en el directorio public/
.
Vamos a verlo en acción. Busca tu terminal y ejecuta:
yarn watch
Esto es, como dice, un atajo para ejecutar encore dev --watch
. Si miras tu archivo package.json
, viene con una sección script
con algunos atajos.
En cualquier caso, yarn watch
hace dos cosas. En primer lugar, crea un nuevo directorio public/build/
y, dentro, los archivos app.css
y app.js
Pero no dejes que los nombres te engañen: app.js
contiene mucho más que lo que hay dentro de assets/app.js
: contiene todo el JavaScript de todas las importaciones que encuentra. app.css
contiene todo el CSS de todas las importaciones.
La razón por la que estos archivos se llaman app.css
y app.js
es por el nombre de la entrada.
Así que la conclusión es que, gracias a Encore, de repente tenemos nuevos archivos en el directoriopublic/build/
que contienen todo el JavaScript y el CSS que necesita nuestra aplicación
Y si te diriges a tu página de inicio y la actualizas... ¡woh! Ha funcionado al instante!? El fondo ha cambiado... y en mi inspector... ¡está el registro de la consola! ¿Cómo diablos ha ocurrido eso?
Abre tu diseño base: templates/base.html.twig
. El secreto está en las funcionesencore_entry_link_tags()
y encore_entry_script_tags()
. Apuesto a que puedes adivinar lo que hacen: añadir la etiqueta link
a build/app.css
y la etiqueta script
a build/app.js
.
Puedes ver esto en tu navegador. Mira la fuente de la página y... ¡sí! La etiqueta link para /build/app.css
... y la etiqueta script
para /build/app.js
. Ah, pero también ha renderizado otras dos etiquetas script
. Eso es porque Webpack es muy inteligente. Por motivos de rendimiento, en lugar de volcar un gigantesco archivo app.js
, a veces Webpack lo divide en varios archivos más pequeños. Afortunadamente, estas funciones Twig de Encore son lo suficientemente inteligentes como para manejar eso: incluirá todas las etiquetas de enlace o de script necesarias.
Lo más importante es que el código que tenemos en nuestro archivo assets/app.js
-incluyendo todo lo que importa- ¡ahora funciona y aparece en nuestra página!
Ah, y como hemos ejecutado yarn watch
, Encore sigue funcionando en segundo plano en busca de cambios. Compruébalo: entra en app.css
... y cambia el color de fondo. Guarda, pasa y actualiza
body { | |
background-color: maroon ; | |
} |
¡Se actualiza instantáneamente! Eso es porque Encore se ha dado cuenta del cambio y ha recompilado el archivo construido muy rápidamente.
A continuación: vamos a trasladar nuestro CSS existente al nuevo sistema y a aprender cómo podemos instalar e importar bibliotecas de terceros -mira Bootstrap o FontAwesome- directamente en nuestra configuración de Encore.
Hey @Arnaud-G,
Yeah you are totally right, however to follow course we recommend to install symfony/webpack-encore-bundle:1.14
with version constraint.
anyway thanks for the tip ;)
Cheers!
Is there an option to embed the app.js
(or {entry}.js
for that matter) on the HTML head?
Reasoning:
In the enterprise context I would like to maintain sensitive data protected by password instead of hosting is as static. I don't care to expose the pkgs used thou. An example of exposing too much is when you use React Admin. Even if you protects your API documentation it will expose it in the build. Although embedding RA entirely might be a bad idea it illustrates the concern with exposing sensitive enterprise data models.
Hey Cesar-S,
Actually, it's the best practice to include your JS / CSS files in HTML's head
tag now but also use the defer
attribute on it, and Webpack can add that tag automatically for you.
Cheers!
Thanks VictorTest,
That is the best practice for public sites and for performance indeed. But in our enterprise reality we can't expose sensitive data contained in the source unless logged in. There are some infra alternatives like VPN, but it would be nice if we could solve the problem in the app. Would make the infra much simpler for us and the UX much simpler since using a VPN is mostly a pain for the user.
To be clear we would no care to expose simple stuff like "there is a button that when clicked calls x" but rather the fact the that url returns data that is hydrated in a model named X containing the fields Y, Z, etc.. X, Y and Z cannot be exposed, and even in minifyed and transpiled code some info will transpire or in general we don't want to be proofing the transpiled code.
Hey Cesar-S,
Hm, I understand in general your problem, but not sure what are you looking for fairly speaking. In the first message, you asked for:
Is there an option to embed the app.js (or {entry}.js for that matter) on the HTML head?
Unless I misunderstand what you're trying to do, you can embed JS files in your HTML head. The defer tag will help you with it in case those tags were in the body before.
You probably may conditionally require those JS files, i.e. require them only if the user is authorized. But if you don't want to pass them through the compiling process - probably you should stop using Webpack then. Or at least stop using it for your sensitive files maybe.
Unfortunately, I have never tried something similar before, so it's difficult to give you any advice on it.
Cheers!
Hi,
I've Been watching quite a few of your tutorials now and in the past and think they are great. Even more important they surely helped me update my knowledge on using Symfony to build an app.
I'm not a frequent "user" anymore and I'm a bit rusty (comes with the age). I used to work in IT for more than 35 years now and the last time I have been really using Symfony (it was Symfony2 I think) dates back to 2013.
When I retired from IT and stepped into business at my own home (bookkeeping and accountancy) together with my wife, I wanted to start improve our own IT and make a few of our own apps in an "online" environment running locally on a self-hosted internal webserver from home. I decided to use Symfony and started to refresh my skills. I watched the videos, typed along all of the code and almost all worked fine for me. Up untill...and the same thing happens now...Encore Webpack and Node JS and/or Yarn becomes the topic.
Not so much the Symfony-part of Encore but the Node and/or Yarn part of the story which really sents me into the woods (so to speak).
Now I learned Yarn is part of NPM and because of that it could be used both (syntax differs I understand) but I can't get it to work.
Especially in this tutorial you mention you use Yarn (watch) instead of NPM. You follow along using Yarn and skip the alternative when using NPM. Also in the script of the videos nor in the conversations I could find a resolution.
To me it feels the NPM and/or Yarn stuff is quite a jungle (with version maintained and abadoned and you using a version that is not the latest version).
I'm sorry for this lengthy story behind my "problem", As experienced as I think I am in IT related problems, I'm lost.
Can you please help me in the right direction for getting this "watch-thing" up and working?
How can I get something simple (as it seems) as "yarn watch" to work without using Yarn, since Yarn is part of NPM?
Kind Regards,
Wim.
Hey @Wim-T
Welcome back to Symfony! It has changed a lot since then but in a good way. I get what you say. It can be challenging to set up NodeJs with everything it needs. I'd recommend using Yarn instead of NPM, but if you don't want to invest time in learning Yarn, you can replicate the yarn watch
functionality by using node-watch
. I found this guide you can follow to set it up https://medium.com/this-code/the-easy-way-to-watch-npm-builds-without-reloading-every-damn-time-cd1fd14393cb
I hope it helps. Cheers!
Hi @MolloKhan,
Thanks for pointing me in the direction of using nodejs's npm.
I read the article you linked and after reading it, I decided to stick to yarn. This because yarn seems to be running out-of-the-box without having to add any code to existing scripts. Writing my own code also means maintaining my own code and if I can prevent that I'd rather prefer that and that's exactly what using yarn looks like (so far).
Many thanks never the less for your quick answer and helping me out.
Kind Regards,
Wim
I'm not sure what version you are using, but in mine (Symfony 6.3
/ @symfony/webpack-encore 4.3.0
), watch
is just a npm script ("watch": "encore dev --watch"
).
So I can simply use npm run watch
to run it.
Kind regards!
hi,if i add function or const on assets/app.js
:
const demo='ok'
function test(){
alert('this is test')
}
yarn run build
then i want call the test()
function on Twig:
<button onclick='test()'>Test</button>
i got error, how to use it?
Hey Yangzhi,
It's difficult to say because we don't see the actual error. Could you share with us what exactly error you see?
Cheers!
hi, the error is:
test if not defined
if i change test function like this:
window.test=()=>{alert('ok')}
then all work fine. but i want kown is this is only and best way or has other best way?
Hey Yangzhi,
Ah, I see. Yeah, that's on purpose. Probably you found the best workaround for this with setting that function on global window
object. The idea behind webpack encore is different, it makes all the code you're writing in JS files encapsulated (not global) - and that's awesome actually! No more mess in your JS code :)
So, you need to change the way you write your JS code. I'd recommend you to find the element (tag) in your JS code and register a listener for "click" event on that element instead of trying to call the method directly with onclick
attribute - that's a legacy way of doing things now. Or, you can take a look into direction of Stimulus, we have a tutorial about it here: https://symfonycasts.com/screencast/stimulus - it has similar (but much cooler) way of declaring actions for special events like click on an element, etc.
Cheers!
Using Symfony 6.1.6 and yarn 1.22.19.
running yarn Watch I get
getting. Error: Cannot find module 'webpack/bin/webpack'
I also received "Error: Cannot find module '@babel/core" but for that I could do yarn add @babel/core
How do I solve this ?
{
"devDependencies": {
"@hotwired/stimulus": "^3.0.0",
"@popperjs/core": "^2.10.2",
"@symfony/stimulus-bridge": "^3.0.0",
"@symfony/webpack-encore": "^4.1.1",
"axios": "^0.24.0",
"bootstrap": "^5.0.0",
"core-js": "^3.0.0",
"jquery": "^3.6.0",
"regenerator-runtime": "^0.13.2",
"webpack-notifier": "^1.6.0"
},
"license": "UNLICENSED",
"private": true,
"scripts": {
"dev-server": "encore dev-server",
"dev": "encore dev",
"watch": "encore dev --watch",
"build": "encore production --progress"
}
}
Hm ok, let's think differently. Is your code related to this chapter? I'm asking because I see some packages which should be added later in this tutorial.
Also I'd like you to test one thing, can you tweak your package.json
modify webpack-encore
version to
"@symfony/webpack-encore": "^1.7.0",
then try again yarn install
and then yarn watch
Cheers!
Hi,
my usecase is the following:
I have 3rd-party page template and organized the js-files in a separate folder in /assets. I imported them in a separate template.js. All compiles flawlessly. I use the entry_tags in my twig template. All good.
But when I load the page it tries to load some of the imported .js-files directly with https://localhost:port1234/path/like/in/assets/folder Obviously that path doesn't exist on the local dev server as the compiled files are in /build so it fails and the respective js-plugins don't work.
I have no clue were the GET to the files on that path is coming from and why it tries to load them like that at all. Can anyone help?
Hey @Eric!
Apologies for the slow reply - we're just getting back from Symfony conference week!
This sounds like very strange behavior. A few questions:
A) You said:
But when I load the page it tries to load some of the imported .js-files directly with...
When you look at the HTML source, do you see the physical <script
tags with the wrong src=""
attribute? Or do all the script
paths look ok... but then something inside of those script files is then trying to download those strange paths?
B) When you look in the public/build/
directory, what do you see? Does anything look strange in there?
C) Do you have any special config in webpack.config.js
?
D) You mentioned:
I have 3rd-party page template and organized the js-files in a separate folder in /assets. I imported them in a separate template.js.
Can you share some of that code? What does that template.js
look like and what imports that file?
Cheers!
Hi Everyone
I've come to this part of the tutorial for some help, hopefully. I've recently update a webapp to Symfony v6.1 and all appeared well until I ran yarn watch. Everything was fine in v6.0
I got this error in terminal
Error: Cannot find module '@babel/core'
I ran yarn add @babel/core
Sorted.
Running yarn watch now gives me:
Error: Cannot find module 'webpack/bin/webpack'
Require stack:
And now I'm stuck. Is this related in anyway to you guys now using Stimulus or is it something else i'm missing? I've not got as far as using Stimulus yet.
I've tried removing and re-adding Webpack encore (this did initially remove my package.json file too, not sure if that's a problem)
Thank you
Steve
and by coming back to this tutorial, in particular the previous video I've found the answer...
I removed webpack encore and installed as instructed encore, copied everything over from the previous package.json, this file is removed regardless of how it was added automatically, and then updated the webpack config file. All is super great again...few.
One question why does the main Symfony site say to use: composer require symfony/webpack-encore-bundle? What's the big difference?
Cheers
Steve
Howdy Steve,
symfony/webpack-encore
is the JavaScript library for Symfony Webpack Encore. Whereas symfony/webpack-encore-bundle
is the PHP library, in the form of a Symfony Bundle, that configures a Symfony Application to use Webpack Encore - including using Symfony's Flex recipes to configure and add symfony/webpack-encore
to the projects JavaScript packages.
Basically webpack-encore
goes in the package.json
file. webpack-encore-bundle
is for composer.json
if that makes sense.
Hey Jesse
That makes perfect sense, thank you for answering and clearing up my confusion.
Have a great day
Steve
Just a short question about the javascript embedding. Should it embed at the end oft the html instead of the head areas?
Hey Rufnex,
Good question! For many years it was recommended to include your JS at the end of your body tag so that them do not block the page rendering and page loads faster. But lately things changed, and now it's recommended to include all your JS/CSS in the head of the page again... but adding the defer attribute to it. Check a few screencasts to learn more about it:
As you can see, Webpack Encore already knows how to handle it, you just need to configure it.
Cheers!
Hello, i have JS error in console,
Uncaught (in promise) TypeError: Cannot destructure property 'eligibleURLPatterns' of 'Jt' as it is undefined companion-bubble.js:1436
at companion-bubble.js:1436:11909
at Generator.next (<anonymous>)
at tn (companion-bubble.js:1436:11431)
Uncaught TypeError: Cannot read properties of null (reading 'style') (index):212
at renderAjaxRequests ((index):212:10065)
at finishAjaxRequest ((index):212:15943)
at (index):212:21834
at xhr.onreadystatechange ((index):212:7896)
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'style') (index):212
at renderAjaxRequests ((index):212:10065)
at finishAjaxRequest ((index):212:15943)
at (index):212:18218
Hello, I feel like there's something I'm doing wrong, but I simply cannot figure out what it is; the background color of the page won't change regardless of what I do, it always stays "lightgrey" and keeps overwriting the custom app.css that I copied earlier from the tutorial folder.
The issue I'm facing specifically is that even when I update assets/styles/app.css to a different color (let's say "maroon"), it stay lightgrey, even though the "maroon" is stated in app.css in the /build directory. According to the developer tools, the file that overwrites the color of <body> stems from webpack///assets/styles/app.css. I also noticed that the console log specified in app.js will never go through either, the console stays empty.
Everything else works as intended, yarn apparently works, but I've had this default lightgrey color there from the very beginning of the whole course and I can't figure out how to rewrite it.
Hi Petr L.!
Apologies for the slow reply! This is super weird... it's as if your code is "stuck" with the original code. That's especially true since you said the console.log in app.js also doesn't seem to work.
First:
> According to the developer tools, the file that overwrites the color of <body> stems from webpack///assets/styles/app.css.
Encore publishes a sourcemap, which helps map the styles to the "source" filename. So in case you were wondering why it doesn't say "build/app.css", that's why. It's loading it from build/app.css... but then the sourcemap tells it that the true source is assets/styles/app.css. But this doesn't answer what's wrong at all - just mentioning this.
Ok, so let's do some debugging! You mentioned that:
> even though the "maroon" is stated in app.css in the /build directory
That's a good detail to check into. To be absolutely sure, stop Encore, completely empty the public/build directory, then re-run Encore. NOW look inside there again. Does the public/build/app.css file have maroon inside of it or lightgrey?
What happens if you make a JavaScript syntax error in assets/app.js? You should get an error in your console from Encore. Do you? Or not?
Finally, triple check that you browser isn't loading out-of-date content by doing a force refresh (or opening the site in incognito mode).
Let me know what you find out - something is definitely wrong, but I bet it's a minor thing (the minor things are the hard ones to track down!).
Cheers!
Hello , got the same issue with the app.js. cleaned my browser cache and finaly got the console.log :)
// 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
}
}
Wanted to let you know :
Stimulus (Bootstrap.js) was removed around version 2.0 of symfony/webpack-encore-bundle.
From the changelog, it look like it was moved to symfony/stimulus-bundle.
Looked into the recipe for symfony/stimulus-bundle and installing it add the files that would be missing if we now only installed Webpack Encore .