If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeTo 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!
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
.
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.
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
:
... 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.
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:
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
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!
// 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
}
}
// 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
}
}
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
I also had to add new webpack.HotModuleReplacementPlugin() to plugins and require fs up top