Hello Webpack Encore

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.

Yo friends! It's Webpack time! Yeeeeeeah! Well, maybe not super "yeeeeeeah!" if you are the person responsible for installing and configuring Webpack... Cause, woh, yea, that can be tough! Unless... you're using Webpack Encore! More about that in a few minutes.

Why all the Webpack Buzz?

But first, I want you to know why you should care about Webpack... like super please-let-me-start-using-webpack-right-now-and-never-stop-using-it kind of care. Sure, technically, Webpack is just a tool to build & compile your JavaScript and CSS files. But, it will revolutionize the way you write JavaScript.

The reason is right on their homepage! In PHP, we organize our code into small files that work together. But then, traditionally, in JavaScript, we just smash all our code into one gigantic file. Or, if we do split them up, it's still a pain because we then need to remember to go add a new script tag to every page that needs it... and those script tags need to be in just the right order. If they're not, kaboom! And even if you do have a build system like Gulp, you still need to manage keeping all of the files listed there and in the right order. How can our code be so nicely organized in PHP, but such a disaster in JavaScript?

Webpack changes this. Suppose we have an index.js file but we want to organize a function into a different, bar.js file. Thanks to Webpack, you can "export" that function as a value from bar.js and then import and use it in index.js. Yes, we can organize our code into small pieces! Webpack's job is to read index.js, parse through all of the import statements it finds, and output one JavaScript file that has everything inside of it. Webpack is a huge over-achiever.

So let's get to it! To import or... Webpack the maximum amount of knowledge from this tutorial, download the course code from this page and code along with me. After you unzip the file, you'll find a start/ directory that has the same code I have here: a Symfony 4 app. Open up the README.md file for all the setup details.

The last step will be to open a terminal, move into the project and start a web server. I'm going to use the Symfony local web server, which you can get from https://symfony.com/download. Run it with:

symfony serve

Then, swing back over to your browser and open up https://localhost:8000 to see... The Space Bar! An app we've been working on throughout our Symfony series. And, we did write some JavaScript and CSS in that series... but we kept it super traditional: the JavaScript is pretty boring, and there are multiple files but each has its own script tag in my templates.

This is not the way I really code. So, let's do this correctly.

Installing WebpackEncoreBundle + Recipe

So even though both Webpack and Encore are Node libraries, if you're using Symfony, you'll install Encore via composer... well... sort of. Open a new terminal tab and run:

composer require encore

This downloads a small bundle called WebpackEncoreBundle. Actually, Encore itself can be used with any framework or any language! But, it works super well with Symfony, and this thin bundle is part of the reason.

This bundle also has a Flex recipe - oooooOOOOooo - which gives us some files to get started! If you want to use Webpack from outside of a Symfony app, you would just need these files in your app.

Back in the editor, check out package.json:

15 lines package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.27.0",
"core-js": "^3.0.0",
"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"
}
}

This is the composer.json file of the Node world. It requires Encore itself plus two optional packages that we'll use:

15 lines package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.27.0",
"core-js": "^3.0.0",
"webpack-notifier": "^1.6.0"
},
... lines 7 - 14
}

Installing Encore via Yarn

To actually download these, go back to your terminal and run:

yarn

Or... yarn install if you're less lazy than me - it's the same thing. Node has two package managers - "Yarn" and "npm" - I know, kinda weird - but you can install and use whichever you want. Anyways, this is downloading our 3 libraries and their dependencies into Node's version of the vendor/ directory: node_modules/.

And... done! Congrats! You now have a gigantic node_modules/ directory... because JavaScript has tons of dependencies. Oh, the recipe also updated our .gitignore file to ignore node_modules/:

31 lines .gitignore
... lines 1 - 22
###> symfony/webpack-encore-bundle ###
/node_modules/
/public/build/
... lines 26 - 27
###
... lines 29 - 31

Just like with Composer, there is no reason to commit this stuff. This also ignores public/build/, which is where Webpack will put our final, built files.

Hello webpack.config.js

In fact, I'll show you why. At the root of your app, the recipe added the most important file of all webpack.config.js:

var Encore = require('@symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// enables @babel/preset-env polyfills
.configureBabel(() => {}, {
useBuiltIns: 'usage',
corejs: 3
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes()
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
// uncomment if you use API Platform Admin (composer req api-admin)
//.enableReactPreset()
//.addEntry('admin', './assets/js/admin.js')
;
module.exports = Encore.getWebpackConfig();

This is the configuration file that Encore reads. Actually, if you use Webpack by itself, you would have this exact same file! Encore is basically a configuration generator: you tell it how you want Webpack to behave and then, all the way at the bottom, say:

Please give me the standard Webpack config that will give me that behavior.

Encore makes things easy, but it's still true Webpack under-the-hood.

Most of the stuff in this file is for configuring some optional features that we'll talk about along the way - so ignore it all for now. The three super important things that we need to talk about are output path, public path and this addEntry() thing:

var Encore = require('@symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
... lines 8 - 10
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
... lines 23 - 65
;
... lines 67 - 68

Let's do that next, build our first Webpack'ed files and include them on the page.

Leave a comment!

  • 2020-06-29 Monia Bensalah

    Cool... Thanks Vladimir Sadicov

  • 2020-06-29 Vladimir Sadicov

    Hey Monia Bensalah

    That's really interesting, I think, I understand why google recommends to use preload. The reason is slow response on this files from server. From my opinion it's better to improve files handling and speedup response from server. But you asked about how to add preload to links, so it's no possible with standard encore_entry_link_tags, But you can do it with encore_entry_css_files. it will return the array of css files. you will need to iterate through them and build your own <link> tags with attributes you need!

    Cheers!

  • 2020-06-25 Monia Bensalah

    Thanks for reply
    https://developers.google.c...
    in the print screen it’s in French
    http://prntscr.com/t6ljz9
    in short it says
    Consider using `<link rel="preload">` to prioritize the recovery of resources currently required for subsequent page loading. Learn more at
    https://web.dev/uses-rel-pr...

  • 2020-06-23 Vladimir Sadicov

    Hey Monia Bensalah

    Interesting question, which issue google found on you project? Honestly I can't remember this recommendation, that's why asking =)

    Cheers!

  • 2020-06-21 Monia Bensalah

    How to preload a font or css file with Webpack Encore ?
    Google PageSpeed Insights recommend me that...

  • 2020-03-16 Anton Bagdatyev

    Nevermind! I was able to solve, running `./node_modules/.bin/encore dev` solved this. Thanks!

  • 2020-03-16 Anton Bagdatyev

    OK, thank you!

  • 2020-03-16 Anton Bagdatyev

    After installing with yarn, and reloading the symfony serve web server, I get the following exception: An exception has been thrown during the rendering of a template ("Asset manifest file "/Users/my-user/code-webpack-encore/start/public/build/manifest.json" does not exists").

  • 2020-03-16 weaverryan

    Hey Anton Bagdatyev!

    Good question. You can safely ignore those :). For the purposes of this tutorial, those packages are not important - zendframework was renamed to laminas, which is what is causing the warnings. So, ignore it and keep going! If this were a real project, I would eventually check into updating those - but for learning, the old ones won't cause any problems.

    Cheers!

  • 2020-03-16 Anton Bagdatyev

    When I install composer require encore, I get the following warning:

    Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
    Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.

    Do I need to do something or can I ignore it?

  • 2019-10-28 Victor Bocharsky

    Hey isTom,

    Hm, it looks like you have a really old Node JS, I'd recommend you to upgrade it, and then upgrade your Yarn as well, otherwise it seems JS dependencies we require in this project are too new your environment and cannot be installed. After you upgrade your Node and Yarn - you should be able to pull the dependencies.

    I hope this helps!

    Cheers!

  • 2019-10-27 isTom

    Sorry it not works at the moment

    $ yarn
    yarn install v1.12.1
    info No lockfile found.
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    error @symfony/webpack-encore@0.28.0: The engine "node" is incompatible with this module. Expected version "8.* || >= 10.*". Got "6.17.1"
    error Found incompatible module
    info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

  • 2019-10-02 weaverryan

    Hey @Paul!

    GREAT question! The short answer is... you should probably not use Encore. Well, it depends... of course :p. You could choose to put some CSS and JS files into your bundle and then make it the responsibility of whatever app is *using* your bundle to import those from their own Encore files. In that case, Encore/Webpack isn't needed in your bundle as you're just creating some "source" files for someone to use and you expect them to process them through Encore.

    But, speaking more broadly, in the "node" world, JS libraries typically write some "source" JavaScript & CSS files, where they use whatever new language features they want. They often then use Webpack to create "distribution" files from those source files. This means that their library ultimately ships with source files and distribution files (where maybe 5 source files have been combined into one and no "new" language features are used, like "import" or let/const, because their Webpack setup has compiled everything into a final version). If you want to do something like this, Encore is *can* be used, but probably isn't the best solution because it's opinionated to make Webpack work for end-user application files, not "library" files. For example, you might choose to use the output.library setting in Webpack for a library (https://webpack.js.org/conf..., but this is not used in Encore (just because packaging files for use in an application versus packaging them for use as a "library" are a bit different cases).

    Let me know if this helps!

    Cheers!

  • 2019-10-02 Paul Requillart-Dole

    Hi !
    How do we manage assets in a Bundle ? Like if i'm writting a Symfony bundle, should I use Webpack Encore to manage my bundle's assets or no ?

  • 2019-09-24 Diego Aguiar

    Hey kensley lewis

    Yes, it's just a shortcut. You can check all composer aliases here: https://flex.symfony.com/

    Cheers!

  • 2019-09-23 kensley lewis

    Are these identical? composer require symfony/webpack-encore-bundle and composer require encore
    If not, should I require both of them through composer?

  • 2019-09-09 Diego Aguiar

    Hey John Christensen

    You are right! It can be a problem if you are not running your local webserver with a SSL certificate (A thing that Symfony CLI enables by default). We will talk about this issue internally and come up with a solution.
    Thanks!

  • 2019-09-09 John Christensen

    I had this same issue (images not loading) after a clean install of course code. The problem is that the image url's are using 'https' protocol.

    To fix, I changed the SITE_BASE_URL var in .env to:

    SITE_BASE_URL=http://localhost:8000

    (from 'https' to 'http')

    Hope that helps someone else! And maybe this change should probably be made in the course code as well?

  • 2019-08-30 Victor Bocharsky

    Hey Miguel,

    Hm, weird. It sounds like a problem with server, i.e. server can't handle this request. Probably it's more question about Docker and how you set it up and run. Because if the file is physically there - it should work. Please, double check your Docker configuration

    Cheers!

  • 2019-08-26 Miguel Barreiro

    Hi there, yes i'm using docker.

    GET https://localhost:8000/uploads/media/cache/squared_thumbnail_small/article_image/asteroid-5d6110774992f.jpeg net::ERR_CONNECTION_REFUSED

    But the file exists at public/uploads/media/cache/squared_thumbnail_small/article_image/asteroid-5d6110774992f.jpeg

    the only images i can't see are the ones in these folders..

    Tks!

  • 2019-08-26 weaverryan

    Hey Miguel Barreiro!

    Are you also using Docker? If the background images aren't showing up, if you copy the URL of the image and open it in your browser, do you see an error?

    Cheers!

  • 2019-08-24 Miguel Barreiro

    I there, same problem here. someone has solved it?

  • 2019-06-10 Victor Bocharsky

    Hey Fabio,

    Yes, you can, just follow the installation guide: https://symfony.com/doc/3.4... . And in case you want to install WebpackEncoreBundle (you probably would like to install it) - here's the installation manual for it: https://github.com/symfony/... - don't forget to register this bundle manually.

    Cheers!

  • 2019-06-07 Fabio Restrepo

    Hi, i can install encore in sf 3.4 without symfony flex?

  • 2019-05-13 Diego Aguiar

    Alright! Anyways, it should work, probably there is something obvious missing (I couldn't find it by looking at your config), I would double check uploads_base_url parameter and the filesystem service

  • 2019-05-11 José Luís Riego Montero

    Really, really no changes.
    I think, this is not important for the course purpose.
    I'll take the course about uploads. 👨‍🎓️
    Thank You!

    liip_imagine:
    # # valid drivers options include "gd" or "gmagick" or "imagick"
    # driver: "gd"
    #

    loaders:
    flysystem_loader:
    flysystem:
    filesystem_service: oneup_flysystem.uploads_filesystem_filesystem

    # default loader to use for all filter sets
    data_loader: flysystem_loader

    resolvers:
    flysystem_resolver:
    flysystem:
    filesystem_service: oneup_flysystem.cached_uploads_filesystem_filesystem
    cache_prefix: media/cache
    root_url: '%uploads_base_url%'

    # default cache resolver for saving thumbnails
    cache: flysystem_resolver

    filter_sets:
    #
    # # an example thumbnail transformation definition
    # # https://symfony.com/doc/cur...
    squared_thumbnail_small:
    filters:
    thumbnail:
    size: [200, 200]
    mode: outbound
    allow_upscale: true

    squared_thumbnail_medium:
    filters:
    thumbnail:
    size: [500, 500]
    mode: outbound
    allow_upscale: true

    #
    # # set your image quality defaults
    # jpeg_quality: 85
    # png_compression_level: 8
    #
    # # setup the filter steps to apply for this transformation
    # filters:
    #
    # # auto rotate the image using EXIF metadata
    # auto_rotate: ~
    #
    # # strip the image of all metadata
    # strip: ~
    #
    # # scale and square the image to the given dimensions
    # thumbnail:
    # size: [253, 253]
    # mode: outbound
    # allow_upscale: true
    #
    # # create border by placing image on larger black background
    # background:
    # size: [256, 256]
    # position: center
    # color: '#fff'

  • 2019-05-10 Diego Aguiar

    Ah ok, can you show me your Liip config?

  • 2019-05-09 José Luís Riego Montero

    thanks Diego!
    Yes, the page show images, the ice cream, the meteor shower etc... but not the article image.
    I suspect there are a problem with the liip bundle configuration.

  • 2019-05-09 Diego Aguiar

    Hey José Luís Riego Montero

    The images are not being displayed on your browser or the actual files are not there? I just double checked and the images are inside "start/public/images/" directory

    Cheers!

  • 2019-05-09 José Luís Riego Montero

    ummm well, god morning...
    I try to rum(Imean run, of course) your(our) course code on docker and the images are missing.
    Not all the images, only the bd images.
    Whats can I do?

  • 2019-05-07 Krzysztof Krakowiak

    Web Components (with VueJS) give me finally proper separation between Templates and JavaScript, I can easy create reusable components without need to dump any JavaScript into script tag.

    They are also a great solution for progressive enhancement strategy, for example what in my symfony forms - if I need to add extra functionality from JavaScript world them I am warping forms in my custom made beautiful-form-component:


    <beautiful-form-component id="my-form">
    <form>
    //here I have all html for form
    </form>
    </beautiful-form-component>

    And then this content between my custom tags is processed as a slot in my VueJS Component, I can easily access it and do with it wherever I want, in this case in example I am adding date-picker to my inputs. Id in above example will be passed as a props to my component. So data can be passed to such component through props or slots.

    here I have repo with really simple example (Encore, vue-custom-element) https://github.com/aniolekx...

    Unfortunately somewhere between encore and babel, there is an issue, which is breaking slots under chrome (I already reported it: https://github.com/karol-f/..., but it works fine under Firefox and IE (IE needs poly-fill, not included in demo)

    I am trying to resolve it too, maybe I will find the root cause of it.

    In my Vue components I am using lots of different libraries (for DataTable, Date Pickers, etc) and all this JS code is wrapped in to Web Components. It is really easier to reuse and maintain such code.

    It is possible to create web components without any extra library like VueJS or React, but I am using Web Components way to mount my VueJS Components.

    Disclaimer: I am absolutely not a pro in a front end world and I have archived all that in past 2 months, but I believe that this is the way :D

  • 2019-05-07 weaverryan

    Hey Krzysztof Krakowiak!

    Hmm, interesting. I'll admit that I don't really have much experience or an opinion yet. What are you using them for? I mean, what problem are they solving for you - or why were you attracted to use them? I'd love to know!

    Cheers!

  • 2019-05-03 Krzysztof Krakowiak

    Ryan, thanks for another great tutorial, but could you add something about Web Components to it? The truth is that I am already using web components with VueJs (through vue-custom-element), but I would like to see some input from your regarding that. Again - Thanks for your hard work!

  • 2019-04-24 Vladimir Sadicov

    hey Vinz Stoned Orgies

    Sometimes it happens, probably you don't have symfony/flex package, or it's outdated in that case you should use full package name symfony/webpack-encore-bundle.

    But stop do you use our course code?

    Cheers!

  • 2019-04-24 Vinz Stoned Orgies

    Hi, my Composer says it can't find any encore package... using "composer require encore".

  • 2019-04-19 weaverryan

    Hey Marcel dos Santos!

    I'm definitely covering the highlights in this video. The biggest one is that we've gone from Webpack 3 to Webpack 4, which is quite a large change. It eliminated the "commons chunk" stuff, and replaced with with the "
    split chunks" (which has a similar name, but is totally different). If you *really* want to see the changes, the last tutorial covered Webpack Encore 0.19. The new tutorial uses 0.27 - you can see the differences in the CHANGELOG: https://github.com/symfony/... - the biggest changes were in 0.21.0.

    Cheers!

  • 2019-04-18 weaverryan

    Hey nibsirahsieu!

    Not *really*. Webpack can be installed globally, but it's not recommended (https://webpack.js.org/guid.... For that reason, if I remember correctly, we actually *don't* support this with Encore. It causes problems with dependency versions between your global node_modules and your local one. So... avoid it ;).

    Cheers!

  • 2019-04-17 nibsirahsieu

    Hi Ryan, is it possible to install webpack encore globally? As you know, nodes dependencies is quite big :)

  • 2019-04-16 Marcel dos Santos

    Nice. Is there a changelog or something like that where I can see the changes, improvements and new features about Symfony Encore since the last course (Webpack Encore: A Party for your Assets)?

  • 2019-04-16 weaverryan

    Hey Marcel dos Santos!

    Great question! You should... thought you will probably speed through a lot of parts ;). There's a quite a lot of new stuff that I want to make sure people are aware of - like the new "split chunks" functionality, browserslist to control browsers you support, super easy async imports(), copyFiles() and Babel polyfill support. If you want, you can skip chapters that you think you know - but definitely check out this other stuff if it's new to you :).

    Cheers!

  • 2019-04-16 Marcel dos Santos

    Hi Ryan, thanks for another great course!

    I already did the course 'Webpack Encore: A Party for your Assets' some weeks ago.
    Should I do this course too? There will be any difference between both courses?

    Bye!