Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

webpack-dev-server

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

To make developing easy, we're using the --watch flag on Webpack. But, there's another way to make developing with Webpack awesome: the Webpack dev server. This is a totally separate library that works a bit like --watch... but has some magic up its sleeves.

First, install it

yarn add webpack-dev-server@2 --dev

As soon as it finishes, go back to the main tab. Stop Webpack and clear the build directory:

rm -rf web/build/*

Now, instead of running webpack, run webpack-dev-server:

./node_modules/.bin/webpack-dev-server

OooOOOooo. I want you to notice two things. First, it appears to do the same thing as Webpack: it builds our assets. And second, it says that it's running on localhost:8080. Yea, this created a new web server that serves our Webpack assets.

Let me show you: copy that URL. But before we try it, look in web/build. Holy cow! It's empty! When you use webpack-dev-server, it does not physically write any files! Instead, it runs a web server - localhost:8080. And when you navigate to the URL of one of our built files... there it is!

Pointing our App at the dev server

To use this, we need to change all of our assets - all of our script and link tags to point to that host. Yep, instead of /build/layout.js, this script tag needs to be http://localhost:8080/build/layout.js. If you're using Symfony, you're in luck! Doing this is easy.

Open app/config/config.yml. And, under the framework key, then assets, set base_url to http://localhost:8080. Actually, in a real project, you should probably put this in config_dev.yml instead, so that it only affects the dev environment:

... lines 1 - 3
framework:
... lines 5 - 8
assets:
base_url: 'http://localhost:8080'
... lines 11 - 37

Let's try it! Refresh the page! Ha! Even though there are no physical files in web/build, this works! All of our assets now point to http://localhost:8080.

webpack-dev-server Static Assets

But... there's a problem. Look at the network tab. Hmm... there are a few 404's, including for router.js. In the HTML source, hmm, the path looks correct. But remember: router.js is a normal file: it is not processed through Webpack.

Open the URL in a browser. Yep, it's broken! webpack-dev-server correctly serves our Webpack-built assets... but it apparently does not serve normal, static assets.

Here's the confusing thing about the dev server. Go to just http://localhost:8080. Huh, it looks like it can serve static files from our project. Oh... but it's serving files from the root of our project. webpack-dev-server doesn't know that the web/ directory is our document root! Yea! We need to tweak things so that we're able to go to http://localhost:8080/favicon.ico, not /web/favicon.ico. We can do that easily.

So, the confusing part is that URLs like /build/login.js do work... you don't need /web/build/login.js. Basically, Webpack-processed assets already have the correct URL, but static assets don't.

Setting contentBase

How do we fix this? In webpack.config.js, add a new devServer key. The most important option we need is contentBase set to ./web:

122 lines webpack.config.js
... lines 1 - 30
module.exports = {
... lines 32 - 117
devServer: {
contentBase: './web',
}
};

Go restart the dev server:

./node_modules/.bin/webpack-dev-server

Now, files like login.js still work. But go back to http://localhost:8080. Perfect! It's looking at the web/ directory. And that means that the dev server can now serve our static assets.

When we refresh, the router 404 is gone! There are a few other 404's for some font awesome assets - we'll fix that next.

Anyways, compared to using --watch, this is pretty similar. Make a change, like the darken from 2.5 to 10:

$brand-primary: darken(#428bca, 2.5%); // #3885c7
... lines 2 - 82

Hit save and then quickly switch over to your browser. See it reload? I didn't do that! The dev server automatically reloaded for me.

That's cool... but the real reason to use the dev server is for Hot Module Replacement, which is amazing... and our next topic.

Leave a comment!

5
Login or Register to join the conversation
GDIBass Avatar
GDIBass Avatar GDIBass | posted 5 years ago | edited

I'm running this on a vagrant box so I had to do a bit of additional configuration in order to get it to work, using the following flags:

--https
--cert <my ssl cert>
--key <my ssl key>
--host <my vagrant box IP>
--public <the domain I set up>:<theport>
--allowed-hosts <my IP on my virtual network>
--port <theport>

or the following dev server config


    devServer: {
        contentBase: './web',
        port: 8085,
        headers: { 'Access-Control-Allow-Origin': '*' },
        watchOptions: {
            poll: true
        },
        host: '192.168.8.11',
        allowedHosts: [
            '192.168.8.1'
        ],
        hot: true,
        inline: true,
        https: {
            key: fs.readFileSync("/etc/ssl/private/myprivatekey.key"),
            cert: fs.readFileSync("/etc/ssl/certs/myprivatepem.pem")
        },
        public: 'mydomainname.com:8085'
    }

I also had to add new webpack.HotModuleReplacementPlugin() to plugins and require fs up top

1 Reply
Daniel G. Avatar
Daniel G. Avatar Daniel G. | posted 4 years ago | edited

For newest webpack-dev-server@3.4.1 if you have error:

GET http://localhost:8000/sockjs-node/info?t=1559045159391 404 (Not Found)<br />

Use config:

` devServer: {

    contentBase: './web',
    sockPort: 8080
}`

More info:

https://github.com/webpack/webpack-dev-server/pull/1792

Reply

Hey Daniel,

Thank you for sharing your solution with others!

Cheers!

Reply
Default user avatar
Default user avatar jarnstad | posted 5 years ago

Looks like there is a problem with the newest version of dev-server. this project is using webpack 3 and the newest dev-server requires 4. I fixed it by installing dev-server@2

Reply

Hey jarnstad!

Thanks for adding the note! That's indeed very likely - all the Webpack 4 compatible versions are starting to come out :). I'm going to check into this - we may add a note to help others thanks to this.

Cheers!

Reply
Cat in space

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

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
    }
}
userVoice