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.
// 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
}
}