Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine


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.

Since we programmers are famously lazy, we don't usually run Webpack with all these cumbersome command-line options. Nope, we put them into a configuration file. At the root of your project, create a new webpack.config.js file. If you make a file with exactly this name, Webpack will automatically find it.

And what does this file look like? Oh, you're going to love this: we use, yep module.exports to export a configuration object!

module.exports = {
... lines 2 - 6


If you're using Webpack 4 or higher, add mode key:

// webpack.config.js

module.exports = {
    mode: 'development',

This will tell Webpack you're building in "development" mode. We'll talk about production builds later.

Inside, that config needs two major things. First, an entry key set to ./web/assets/js/RepLogApp.js:

module.exports = {
entry: './web/assets/js/RepLogApp.js',
... lines 3 - 6

Entry is Webpack's name for your input file: the one file it will load. Second, of course, we need to tell Webpack where to create the output. Set this to a hash with path set to the directory: __dirname plus /web/build:

module.exports = {
entry: './web/assets/js/RepLogApp.js',
output: {
path: __dirname+'/web/build',
... line 5

That __dirname is a special variable available inside of Node that points to the directory of this file. Then, add a filename key set to rep_log.js:

module.exports = {
entry: './web/assets/js/RepLogApp.js',
output: {
path: __dirname+'/web/build',
filename: 'rep_log.js',

Now, running Webpack is truly a lazy experience... we should probably lift our cat a few times for exercise. Just run:


And it works exactly like before.

Using the path module

Before we celebrate too much, head to webpack.js.org. Make sure you're here, and not on webpack.github.io - that's the old website for the old version 1 of Webpack. We're using the hipster version 3... and new versions of Webpack tend to come out fast. If there is already a new version when you're going through this tutorial, don't worry too much: there's a good chance the changes are minimal. And we'll add notes otherwise.

Under the main Concepts page, they talk about this configuration file. But check it out: for the output path, they use some path.resolve() thing.

This is a minor detail in Node that I want you guys to see. In Node, you never see path strings concatenated together like this. Nope, to keep things portable between Unix and Windows, you're supposed to call path.resolve() - or a similar function path.join() - to concatenate the path for you.

No big deal! Add path.resolve() passing it __dirname, then web then build:

module.exports = {
... line 2
output: {
path: path.resolve(__dirname, 'web', 'build'),
... line 5

You can pass as many arguments as you want: the args are built into one big path string.

Simple! But... does it work!? Try it:


Ah! An error!

path is not defined

Listen up! This is important: webpack.config.js is executed by Node... and this code will never run in our browser. So since this is a pure Node script, we can use any of the core libraries that you normally have access to, like the path module.

But to get access to it, you need to require it. At the top, add const path = require('path'):

const path = require('path');
module.exports = {
... lines 4 - 8

Now, everything is happy again!

Requiring Core or Vendor Modules

But notice, this is not ./path! The ./ would tell Node to look for a file relative to this file. But when we just say path, Node looks for either a core module inside the language itself called path - which is what happens in this case - or for a module called path inside node_modules. We'll see that very soon.

Making PhpStorm work with Node

Ok, but my editor isn't very happy: when I hover over path, it looks like there's an error:

Node.js coding assistance is disabled

Ok, that sounds like something we can improve! Open up the PhpStorm Preferences, which is Command+, on a Mac. Then, search for Node.js. Ah, there's a section called "Node.js and NPM". Find that "Enable" box and click it! Then hit Ok to exit.

And in a moment, yep! PhpStorm is happy again. And now, we will have auto-complete on core Node features.

Ok, next, we'll teach Webpack to watch for changes... and start installing and requiring vendor libraries - like jQuery - via Yarn.

Leave a comment!

This tutorial explains the concepts of an old version of Webpack using an old version of Symfony. The most important concepts are still the same, but you should expect significant differences in new versions.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": "^7.2.0",
        "symfony/symfony": "3.3.*", // v3.3.16
        "twig/twig": "2.10.*", // v2.10.0
        "doctrine/orm": "^2.5", // v2.7.0
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.3
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.4.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "^2.0", // v2.1.2
        "doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0" // v3.3.5

What JavaScript libraries does this tutorial use?

// package.json
    "dependencies": [],
    "devDependencies": {
        "babel-core": "^6.25.0", // 6.25.0
        "babel-loader": "^7.1.1", // 7.1.1
        "babel-plugin-syntax-dynamic-import": "^6.18.0", // 6.18.0
        "babel-preset-env": "^1.6.0", // 1.6.0
        "bootstrap-sass": "^3.3.7", // 3.3.7
        "clean-webpack-plugin": "^0.1.16", // 0.1.16
        "copy-webpack-plugin": "^4.0.1", // 4.0.1
        "core-js": "^2.4.1", // 2.4.1
        "css-loader": "^0.28.4", // 0.28.4
        "extract-text-webpack-plugin": "^3.0.0", // 3.0.0
        "file-loader": "^0.11.2", // 0.11.2
        "font-awesome": "^4.7.0", // 4.7.0
        "jquery": "^3.2.1", // 3.2.1
        "lodash": "^4.17.4", // 4.17.4
        "node-sass": "^4.5.3", // 4.5.3
        "resolve-url-loader": "^2.1.0", // 2.1.0
        "sass-loader": "^6.0.6", // 6.0.6
        "style-loader": "^0.18.2", // 0.18.2
        "sweetalert2": "^6.6.6", // 6.6.6
        "webpack": "^3.4.1", // 3.4.1
        "webpack-chunk-hash": "^0.4.0", // 0.4.0
        "webpack-dev-server": "^2.6.1", // 2.6.1
        "webpack-manifest-plugin": "^1.2.1" // 1.2.1