Symfony Encore

Install encore via composer, which will create a package.json file with the node dependencies for webpack. Then run npm install which will acquire those packages;

composer require encore
npm i

Refreshing the site now will give an error about missing manifest files. We need to run the encore dev command to generate these and compile our assets. Commands have been added to package.json. Run npm run dev to build our assets.

    "scripts": {
        "dev-server": "encore dev-server",
        "dev": "encore dev",
        "watch": "encore dev --watch",
        "build": "encore production --progress"

Including generated assets

In the html base twig template, use these in the stylesheets and javascripts block

{% block stylesheets %}
    {{ encore_entry_link_tags('app') }}
{% endblock %}

{% block javascripts %}
    {{ encore_entry_script_tags('app') }}
{% endblock %}

This will take the generated entry points in public/build/entrypoints.json and include the files in the template.

Importing third party libraries

Install a third party library

npm i jquery --dev

Because this is a third party library, we don’t need path directories. The main export of a library exists in the library’s “package.json“` in its node_modules directory in the ‘main’ key.

Variables do not permeate across files and are not global. Using the following in our javascript file only makes dollar available within that file.

import $ from 'jquery';

Mainifest.json & Twig Images

Mainifest.json is created when webpack runs. It contains a map of key values of all source and build files. When referencing images in twig templates, use the key in manifest.json to correctly use the image. This will include the build path.


        from: './assets/images',
        to: 'images/[path][name].[hash:8].[ext]'

in webpack.config.js to populate manifest.json with the copied image files.

Fixing jQuery Plugins

use .autoProvidejQuery() which can fix jQuery plugnis which don’t play nice with imports.

Configuring for Production

Encore is set up to do this automatically with hashing of filenames when in production;


Make sure the webserver is set up to serve no-expire headers for a long time in the future for js, and css, and image files.

Demo Files


Webpack – Setting Up


Webpack is installed using NPM. Initialise a new project, which will create a package.json file. Optionally use the flag -y to accept all defaults when initialising the project.

npm init

Now we can install Webpack and Webpack CLI via NPM using the following. The flag -D is for –save-dev, which adds both packages to our devDependencies.

npm install webpack webpack-cli -D

By default, Webpack 4 will use a default configuration file, so one isn’t necessary to get going. The default configuration values can be found here.

By default, Webpack will look in the folder “src” for the file “index.js”, and output to the folder “dist”, with the javascript file “main.js”. A handy Webpack config generator can be found here.

We can now create a file, index.html in the project root and link to the file “dist/main.js”.

<!doctype html>
   <title>Getting Started</title>
    <script src="dist/main.js"></script>

For our example, we’ll install Lodash, which is a utility library

npm install lodash --save

Now let’s create the entry point file in “src/index.js”, we’ll import lodash.

import _ from 'lodash';

console.log(_.join(["This", "is", "using", "Lodash"], " "));

This will import the default export from lodash in our local “_” variable. We could use any name of our choosing for this to use locally, however underscore is a convention when using this package.

To build our javascript into the dist directory, we can run

npx webpack

NPX is a tool for executing node packages. It is typically only used for single use commands, such as react-create-app. We’ll supersede its use later for our builds, but it’s useful to use it for this example. Executables which are available for use with NPX are symlinked to the node_modules/.bin directory. Running “NPX with any of the files in here can perform useful functions, e.g. mkdirp which will make directories recursively:

mkdirp /directory1/directory2

Importing Individual Methods

If we didn’t want to use the entire lodash library, we could import individual methods from it using the following:

import {join as _join} from 'lodash'
console.log(_join(["This", "is", "using", "Lodash"], " "));

However, this will still import the entire Lodash library into our project. Instead, we can use the lodash-es module which defines each method as an ES module:

import {join as _join} from 'lodash-es'

console.log(_join(["This", "is", "using", "Lodash"], " "));

This example cuts our dist/main.js size down from ~70KB to ~1KB.

Building with a separate configuration file

If we need to test something using a separate configuration file, we can use NPX to achieve this. We can create a file called webpack.test.config.js in our project’s root with the following:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'test.js'

Note: config files use require to include, which was introduced with Node.js some time ago, and does not use import

And then execute it with NPX:

npx webpack --config webpack.test.config.js

This will bundle our javascript in dist/test.js instead of dist/main.js.

Note that config files are standalone. So if we had a webpack.config.js in our project’s root, any config file passed to Webpack via NPX will not be merged together.

Adding a Script Shortcut

We can assign shortcut’s via NPM’s script facility. At a very basic level, we can setup a build command so that we do not have to rely on NPX. We can do that in our package.json file:

  "scripts": {
    "build": "webpack"

We can then add a watch command which will automatically re-build our javascript based on changes to the project:

  "scripts": {
    "build": "webpack",
    "watch": "webpack  --watch"

We can also specify other parameters, such as “mode” in our build scripts:

  "scripts": {
    "build": "webpack --mode production",
    "watch": "webpack --mode development  --watch"

Note: When watching for changes, the process will have to be broken and re-started when the config file is changed

Setting publicPath

publicPath is used when resolving things like images included in CSS files. It’s prepended to these files. For this example, we’ll set it to the dist folder.

    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: 'dist/'

Source Maps

To allow easier debugging of code, we can set the devtool parameter of our config to one of the sourceMap options. As Webpack itself only deals with Javascript, this will only affect JS SourceMaps, CSS and other loaders will need to be configured in their own right.

By default, setting the config’s mode to ‘development’ will enable SourceMaps, and ‘production’ will disable them, however there are numerous other options which can be useful for both production and development.

Development SourceMaps

These methods generate sourceMaps inline, in the bundled JS files, adding bloat and should not be used in production.


Fast. Files are separated using the original directory structure, but the code generated by Webpack to load modules is present.


Pretty Fast. Webpack loading code is removed.


Medium Speed (but with fast rebuilds). Uses sourcemaps output by defined loaders.


Slow. Adds column level mappings so inline breakpoints can be set.

Production SourceMaps


No SourceMaps are generated. This is the default in production, but leaves code difficult to debug when receiving user reports.


Source Maps are generated in a separate file. A comment tells dev tools (such as Chrome Dev Tools) where to find them, which are loaded when the dev tools themselves are opened.


Source Maps are generated in a separate file, but the comment to tell the browser where to find it is omitted. These can then be Loaded Manually


The same as source-map, but only gives the file name and line number. The code itself is not visible to the browser.

Cleaning The Output Folder

When changing Webpack settings, it’s often useful to get rid of old files in the output folder which may be left handing around. To do this, we can use a plugin called Clean Webpack Plugin

Install the plugin

npm install -D clean-webpack-plugin

And then add this to the plugins section of our config file:

module.exports = {
    plugins: [
        new CleanWebpackPlugin(['dist'])

The option passed into the first parameter of the plugin is an array of paths to be cleaned. This is required, as it does not use Webpack’s output configuration. Supplying a name like above will completely remove that folder, however we can also provide glob strings, such as dist/., which would remove the files within the folder.

This will, by default leave generated files when we’re watching files, so changes will continually generate new files in our dist folder. To re-generate whilst watching, we can use the following option

module.exports = {
    plugins: [
        new CleanWebpackPlugin(['dist'], {watch: true})