Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Webpack Encore: Frontend like a Pro!

2:10:39

What you'll be learning

This tutorial works great with Symfony5!
// 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
    }
}

Writing great PHP code but your JavaScript looks a little bit hacky? It's not your fault! Before Webpack, coding "correctly" in JavaScript... sorta wasn't possible!

But setting up Webpack can be a pain. So... hello Webpack Encore! Encore allows you to modern JavaScript starting... immediately! Go, go go!

  • Installing Encore & yarn
  • webpack.config.js & your first Webpack build!
  • Adding script & link tags thanks to WebpackEncoreBundle: encore_entry_script_tags() & encore_entry_link_tags()
  • Modules! require, import and export
  • Installing & using external libraries
  • jQuery plugins & global variables
  • Handling CSS! Including fonts & images
  • Code splitting: free, smart optimization
  • Sass & Overriding Bootstrap Sass Variables
  • Copying static files
  • Multiple "entries": page-specific CSS & JavaScript
  • PostCSS, Bower, browserslist, polyfills & new features in old browsers
  • enableSingleRuntimeChunk()?
  • Async imports!

Your Guides

Ryan Weaver


Join the Conversation?

39
Login or Register to join the conversation
Yangzhi Avatar

if i want add global function or const in app.js.the call them on twig,how write it?

Reply

Hey Yangzhi,

We have a screencast about it in this course. Please, check it out here: https://symfonycasts.com/screencast/webpack-encore/external-libs

I hope this helps!

Cheers!

Reply
Paskuale Avatar
Paskuale Avatar Paskuale | posted 1 year ago

is there any way to import a webpack structure from a third party theme ?

Reply

Hey Paskuale

Could you please add more details? What exactly do you mean? Maybe some example?

Cheers!

Reply
Paskuale Avatar

I mean if I find a nice bs5 template with webpack installation, I can try to load it, to tell the truth I spent the weekend and it seems to work, really great.

Reply

oh... I think I got what do you mean. As I know that can't be done automatically, so it requires some manual work. You should include all stuff you need to your app.js and install all dependencies which are required by this template.

Reply
Paskuale Avatar

You are absolutely right, in fact it was not immediate, I lost 2 days to understand all the sub-functions of the webpack, and a lot of yarn add {packageName} but I was able to take advantage of an excellent theme (which due to the webpack system I could no longer to integrate it with another php framework) :)

Reply

Sounds like that it was a cool challenge that gives an awesome experience! Nice that you was able to achieve it!

Sorry that it took some time to answer your question! If you have more questions do not hesitate to ask!

Cheers!

Reply
Paskuale Avatar

On the contrary, you were very quick in answering me, asking a question before a weekend it is normal that we all rest on Saturday and Sunday, I take this opportunity to thank you for this splendid videocast in a week I will start working with simfony 5.x (I come from almost 20 years of work with my beloved fw that I don't quote here for not doing OT) and thanks to these videocasts I'm learning many interesting things. ;)

Reply

Thank you very much for your feedback! This is the best reward for us.

Stay safe and keep learning Symfony! (with SymfonyCasts <3) ;-)

Cheers!

1 Reply
Peter L. Avatar
Peter L. Avatar Peter L. | posted 1 year ago

Hi all,
If someone is using his own Docker with this tutorial zipped code, is best to use version of PHP 7.2.
I haven't tried 7.1, 7.3, but in 7.4 templates are behaving weird. Like select element is merged with id `<selectid=""></selectid="">`
same for textarea and for top nav bar.
I think there must be some strange difference of processing whitespaces on PHP level.
Unrelated to Symfony but probably same bug: https://github.com/PrestaSh...

I was also required to generate thumbnails with Liip with command line in docker as browser links were not working. For example:
`php bin/console liip:imagine:cache:resolve article_image/asteroid-{hash}.jpeg`

Reply

Hey Peter L.!

Ah, I know that weird with the missing spaces! A certain, older version of Twig had a bug with whitespaces in PHP 7.4 - https://github.com/twigphp/... - it was fixed a long time ago, but this tutorial is also getting a little old. So that explains why PHP 7.4 suddenly acted poorly for you :). But since we advertise that this tutorial supports PHP 7.1-7.4, we'll get that fixed in the code download.

I'm not sure about the 2nd issue with why you would need to generating the thumbnails with the command... but, in case someone else has that issue, thanks for posting.

Cheers!

Reply
Peter L. Avatar

Thanks for letting me know about that bug. With Liip bundle, it may be my folder permissions in Docker.

Reply
Peter L. Avatar

I was just running around my old comments and noticed I resolved this problem while ago. It was not only about permissions. My docker nginx proxy was not passing proper Host header to underlaying nginx-phpfpm server. Liip is/was using this information to generate cached img urls.

Reply

Hey Peter,

Interesting! Thank you for sharing the solution with others!

Cheers!

Reply

Hi,
Thanks again for all thoses skills you share with us and for this amazing bundle.
I would like to know how to work with Tailwind CSS 2.1 with the JIT (Just In Time) compiler.
I manage to Maje or work. But I have to restart webpack to apply m'y changes.
Have a good day

Reply

Hey Moulaye,

Thank you for your interest in SymfonyCasts tutorials! I will add this Tailwind CSS to our idea pool for future screencasts. Unfortunately, I don't have estimations when it might be released if ever. Btw, Symfony should support Tailwind CSS since 5.x version, you can see the related PR been merged: https://github.com/symfony/...

Unfortunately, I personally can't say more about this topic as I know it very little and haven't tried to use yet. We will see if we can cover this topic in future tutorials.

Cheers!

Reply

Thank you,

Looking forward for a tailwind topic :)

Cheers

Reply

Hey!

What's the purpose of the second parameter in encore_entry_link_tags()? It looks like it tries to use packages from assets. If I use multiple webpack configs, and I've configured webpack_encore.builds in webpack_encore.yaml — it's clear, encore_entry_link_tags() reads corresponding entrypoints.json. But it also tries to read wrong manifest.json file specified by default in assets.yaml. It's very complicated. Builds... Packages... I'm lost. When I configure my Encore, I get only builds, and they contain both (entrypoints and manifest) JSON files, and it looks like one thing to me. But why are there two different parameters in encore_entry_link_tags()?

Reply

Hey plashenkov !

Yea, that second parameter is super unuseful. I added it to cover an edge case... but I'm not sure that edge case is even needed. So, to simplify, I would basically ignore that 2nd argument - pass null to it. So basically, you if you've configured multiple builds (it sounds like you have), then you have multiple builds... and that's it :).

That's sort of a non-answer, but it's (honestly) probably not that interesting to get into the real detail of these "packages" things. They are part of symfony/asset and aren't particularly useful when you're processing everything through Encore. It holds the 2nd argument because I coded for that edge-case first... and then later someone added the "multiple builds" feature to Encore.

Cheers!

Reply

Hey Ryan,
Thank you for your answer!
Yes, it looks like I've got it already. If you use Encore, you do not need to think about assets and packages at all. It should not use manifest.json, because it will use entrypoints.json. The problem is encore_entry_link_tags() tries to load default manifest.json specified in Symfony config (and it is specified there by default), and we get an exception. Even if null is passed as the second parameter. And we have to find out what's wrong, find it in config and disable. I've expressed all my first confusion here: https://github.com/symfony/...
Now it looks more or less clear to me, but I still think that something is super complicated with all these parameters. :)

Reply

Hey plashenkov!

Ah, I see that! Yea, the manifest.json file is only needed if you need to refer to built assets from a Twig file - most probably an image that used Encore to copy into the build directory - e.g. <img src={{ asset('images/foo.png') }} - in that case Symfony will look for "images/foo.png" in the manifest.json file (assuming you have this configured in assets.yaml). But it's not really needed otherwise (it WAS used in an earlier version of WebpackEncoreBundle, but it's really not important now). In a perfect world, we maybe shouldn't concern ourselves at all with "asset packages" when we use the encore_entry functions. And as you mentioned in your issue, yes, "asset packages" and "builds" are *completely* different things... and you likely don't need multiple asset packages.

So yea, that 2nd arg about the asset packages is a little "not smooth" ;), but I hope this helps. We could maybe considering removing it in a future version, but that's tough to do without breaking backwards compatibility.

Cheers!

Reply

this seems to be a fun and likeable skill to learn, but what about our old "asset" way of handling simple assets? is it discontinued, or added into the core of symfony? to call images, css, javascripts, etc?

Reply

Hey jlchafardet

Using Webpack Encore is the prefered way of Symfony for handling assets but I believe you can use any other mechanism that fit your needs. Symfony does not obligates your to use Encore :)

Cheers!

1 Reply

I'm fairly clear about that, I just tested using the old asset method and worked fine, for now I'm just playing with some things I wanted to learn to do, so decided to not explore something else new while I finish learning those relations things from doctrine which I want to learn first, once I have mastered that,its very likely ill explore encore.

1 Reply

I highly recommend you to use Encore in your Symfony projects, it just make things a lot easier :)

1 Reply
Paul Z. Avatar
Paul Z. Avatar Paul Z. | posted 2 years ago

I wasn't sure where to ask this question, I didn't want to add it as a encore github issue because it's probably not an issue but just me.

What i'm trying to use is encore, typescript, react, and linting typescript with using the '@typescript-eslint/parser' parser (since tslint is being deprecated). I got it all working, but my question is why do I still need the 'babel-eslint' package if i'm not using the babel eslint parser? Encore complains that I need it if I enable 'enableEslintLoader'. Here is the relevant parts of my webpack.config.js:


.enableTypeScriptLoader()
.enableForkedTypeScriptTypesChecking()
.enableEslintLoader(options => {
options.parser = '@typescript-eslint/parser'
})
.configureLoaderRule('eslint', loader => {
loader.test = /\.(jsx?|tsx?)$/
})
.enableReactPreset()

Here is the relevant parts of my .eslintrc.js file:


parser: "@typescript-eslint/parser",
plugins: [
"@typescript-eslint",
"react"
],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended"
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
}

Oh also the 'fork-ts-checker-webpack-plugin' now supports eslint, however when I enable it with:


.enableForkedTypeScriptTypesChecking(tsConfig => {
tsConfig.eslint = true;
})

it doesn't seem to do anything. So i'm just wondering what I'm missing, or what's the best way to config eslint & typescript parser. Thanks in adance, your videos for react and api-platform has given me a huge head start in building my first headless app!

Reply

Hey Dave,

I don't know the exact reason but probably could give you some tips. First of all, JS dependencies are weird :) Really, when you run "yarn install" tons of tons JS packages are pulled locally. So, some dependencies still might require it. Also, you can give some hints from Yarn on it, try to execute "yarn why babel-eslint" to know why exactly it was installed. Does the output helps? Let me know if it's not. Btw, what exactly error message do you see when you don't have "babel-eslint" package installed?

Btw, I also noticed "babel-eslint" as a dependency in package.json of Webpack Encore, see https://github.com/symfony/... . So, it looks like a required dev dependency of Webpack Encore

Also, probably this issue could answers some questions for you? https://github.com/symfony/... . Otherwise, probably better to ask this question on webpack encore repo, probably someone there could answer this question better than me.

I hope this helps!

P.S. Thank you for your kind feedback about our courses! And congrats on your first headless app, well done!

Cheers!

Reply
Paul Z. Avatar

Hi Victor,


/var/www/api-platform # yarn why babel-eslint
yarn why v1.16.0
[1/4] Why do we have the module "babel-eslint"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "babel-eslint@10.0.3"
info Has been hoisted to "babel-eslint"
info This module exists because it's specified in "devDependencies".
info Disk size without dependencies: "2.4MB"
info Disk size with unique dependencies: "6.18MB"
info Disk size with transitive dependencies: "13.52MB"
info Number of shared dependencies: 27
Done in 0.79s.

so it's only a dependency because I added it. If I don't add it:

Running webpack-dev-server ...

WARNING Be careful when using Encore.configureLoaderRule(), this is a low-level method that can potentially break Encore and Webpack when not used carefully.
Error: Install eslint-loader & babel-eslint to use enableEslintLoader()
yarn add eslint-loader@^2.1.2 babel-eslint@^10.0.1 --dev

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

So it looks like it's a required dependency by webpack as it's the default parser even though it may not be used. I'll post the question on their github wiki. Thanks!

Reply

Hey Dave,

Hm, I see... For me it sounds like "eslint-loader & babel-eslint" are optional dependencies, they are required only when you use configureLoaderRule(). This way Encore does not want to force everyone pulling those packages as some customers might just not needed them. So maybe it's only listed in dev deps in package.json for clarity, or maybe it's used in some tests also.

Anyway, good idea to open an issue I think. Probably someone will be able to explain how it works with babel-eslint behind the scene better than I did.

Cheers!

Reply
Jordan Avatar

How can I configure Foundation ?
I don't understand where is the problem ?

Reply

Hey Xidoc,

Could you explain more what exactly problem do you have? Any error messages that would help to figure out your problem? What exactly you want to configure? Did you follow any installation guide or docs? We would be glad to help you knowing a little more about your problem

Cheers!

Reply
Default user avatar
Default user avatar Shamshid | posted 3 years ago

great tutorial.

You should bring usage of purgecss in Encore which will trim out unwanted css and most importantly we need to learn to make a config to which trims page specific css from dedicated css file. (kinda confusing what I told here)

Reply

Hey Shamshid!

That's an excellent suggestion - I haven't played much with purge, but I've heard of it. I think getting it to work nicely requires (as you guessed) a bit of work... and I'm not sure it's worth it. I know Javier played with it for a bit, but ultimately decided not to use it. Here are some resources: https://github.com/symfony/... and https://github.com/symfony/...

Cheers!

Reply
Tomasz N. Avatar
Tomasz N. Avatar Tomasz N. | posted 3 years ago

Hi Ryan, thanks for another amazing and hyuooOOOooough! huge pack of knowledge.

Reply

"pack" of knowledge 😂- yep, we're friends :D

Reply
Alex Z. Avatar
Alex Z. Avatar Alex Z. | posted 3 years ago

This seems very great!

Something is bothering me.
Why are you using jQuery? I am not saying it's not a good tool. If well configured the library can be awesome. But vanilla JS is powerful enough today to be used alone.

Reply

Hey Alex Z.

First to clarify, this course is not about Jquery, but it's a very accepted library for the community, and there are many tricks you need to know about how to properly integrate it with Encore (and this is even more needed when working with Jquery plugins that are poorly written)

Cheers!

Reply
Alex Z. Avatar
Alex Z. Avatar Alex Z. | MolloKhan | posted 3 years ago | edited

Thanks for your answer MolloKhan
I am waiting the course,

Cheers!

1 Reply
Cat in space

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