webpack-dev-server
The webpack-dev-server is a little node.js Express server, which uses the [[webpack-dev-middleware]] to serve a webpack bundle. It also has a little runtime which is connected to the server via Socket.IO. The server emits information about the compilation state to the client, which reacts to those events. You can choose between different modes, depending on your needs. So lets say you have the following config file:
var path = require("path");
module.exports = {
entry: {
app: ["./app/main.js"]
},
output: {
path: path.resolve(__dirname, "build"),
publicPath: "/assets/",
filename: "bundle.js"
}
};
You have an app
folder with your initial entry point that webpack will bundle into a bundle.js
file in the build
folder.
Content Base
The webpack-dev-server will serve the files in the current directory, unless you configure a specific content base.
$ webpack-dev-server --content-base public/
Using this config webpack-dev-server will serve the static files in your public
folder. It'll watch your source files for changes and when changes are made the bundle will be recompiled. This modified bundle is served from memory at the relative path specified in publicPath
(see API). It will not be written to your configured output directory. Where a bundle already exists at the same url path the bundle in memory will take precedence (by default).
For example with the configuration above your bundle will be available at localhost:8080/assets/bundle.js
To load your bundled files, you will need to create an index.html
file in the public
folder from which static files are served (--content-base
option). e.g:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
By default go to localhost:8080/
to launch your app. For example with the configuration above (with publicPath) go to localhost:8080/assets/
.
Automatic Refresh
The webpack-dev-server supports multiple modes to automatic refresh the page:
- Iframe mode (page is embedded in an iframe and reloaded on change)
- Inline mode (a small webpack-dev-server client entry is added to the bundle which refresh the page on change)
Each mode also supports Hot Module Replacement in which the bundle is notified that a change happened instead of a full page reload. A Hot Module Replacement runtime could then load the updated modules and inject them into the running app.
Iframe mode
To use the iframe mode no additional configuration is needed. Just navigate the browser to http://<host>:<port>/webpack-dev-server/<path>
. I. e. with the above configuration http://localhost:8080/webpack-dev-server/index.html
.
- No configuration change needed.
- Nice information bar on top of your app.
- Url changes in the app are not reflected in the browsers url bar.
Inline mode
To the use inline mode specify --inline
on the command line (you cannot specify it in the configuration). This adds the webpack-dev-server client entry point to the webpack configuration. There is no change in the url required. Just navigate to http://<host>:<port>/<path>
. I. e. with the above configuration http://localhost:8080/index.html
.
- Command line flag needed.
- Status information in the browser log.
- Url changes in the app are reflected in the browsers url bar.
Inline mode with node.js API
There is no inline: true
flag in the webpack-dev-server configuration, because the webpack-dev-server module has no access to the webpack configuration. Instead the user have to add the webpack-dev-server client entry point to the webpack configuration.
To do this just add webpack-dev-server/client?http://<path>:<port>
to (all) entry point(s). I. e. with the above configuration:
var config = require("./webpack.config.js");
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080");
var compiler = webpack(config);
var server = new webpackDevServer(compiler, {...});
server.listen(8080);
Inline mode in HTML
There is also the option to add a reference to the webpack-dev-server client script to the HTML page:
<script src="http://localhost:8080/webpack-dev-server.js"></script>
Hot Module Replacement
To enable Hot Module Replacement with the webpack-dev-server specify --hot
on the command line. This adds the HotModuleReplacementPlugin
to the webpack configuration.
The easiest way to use Hot Module Replacement with the webpack-dev-server is to use the inline mode.
Hot Module Replacement with Inline mode on CLI
There is nothing more needed. --inline --hot
does all the relevant work automatically. The CLI of the webpack-dev-server automatically adds the special webpack/hot/dev-server
entry point to your configuration.
Just navigate to http://<host>:<port>/<path>
and let the magic happen.
You should see the following messages in the browser log:
[HMR] Waiting for update signal from WDS...
[WDS] Hot Module Replacement enabled.
Messages prefixed with [HMR]
orginate from the webpack/hot/dev-server
module. Messages prefixed with [WDS]
orginate from the webpack-dev-server client.
It's important the specify a correct output.publicPath
elsewise hot update chunks cannot be loaded.
Hot Module Replacement with node.js API
Similar to the inline mode the user have to do changes to the webpack configuration.
Three changes are needed:
- add an entry point to the webpack configuration:
webpack/hot/dev-server
. - add the
new webpack.HotModuleReplacementPlugin()
to the webpack configuration. - add
hot: true
the the webpack-dev-server configuration to enable HMR on the server.
I. e. with the above configuration:
var config = require("./webpack.config.js");
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080", "webpack/hot/dev-server");
var compiler = webpack(config);
var server = new webpackDevServer(compiler, {
hot: true
...
});
server.listen(8080);
Proxy
The Webpack dev server makes use of node-http-proxy to optionally proxy requests to a separate, possibly external, backend server. A sample configuration is below.
{
devServer: {
proxy: {
'/some/path*': {
target: 'https://other-server.example.com',
secure: false,
},
},
},
}
See the node-http-proxy Options documentation for available configuration.
Proxying some URLs can be useful for a variety of configurations. One example is to serve JavaScript files and other static assets from the local development server but still send API requests to an external backend development server. Another example is splitting requests between two separate backend servers such as an authentication backend and a application backend.
Bypass the Proxy
(Added in v1.13.0.) The proxy can be optionally bypassed based on the return from a function. The function can inspect the HTTP request, response, and any given proxy options. It must return either false
or a URL path that will be served instead of continuing to proxy the request.
For example, the configuration below will not proxy HTTP requests that originate from a browser. This is similar to the historyApiFallback
option: browser requests will receive the HTML file as normal but API requests will be proxied to the backend server.
{
devServer: {
proxy: {
'/some/path*': {
target: 'https://other-server.example.com',
secure: false,
bypass: function(req, res, proxyOptions) {
if (req.headers.accept.indexOf('html') !== -1) {
console.log('Skipping proxy for browser request.');
return '/index.html';
}
},
},
},
},
}
webpack-dev-server CLI
$ webpack-dev-server <entry>
All webpack [[CLI|cli]] options are valid for the webpack-dev-server CLI too, but there is no <output>
default argument. For the webpack-dev-server CLI a webpack.config.js
(or the file passed by the --config
option) is accepted as well.
There are some additional options:
--content-base <file/directory/url/port>
: base path for the content.--quiet
: don't output anything to the console.--no-info
: suppress boring information.--colors
: add some colors to the output.--no-colors
: don't used colors in the output.--host <hostname/ip>
: hostname or IP.--port <number>
: port.--inline
: embed the webpack-dev-server runtime into the bundle.--hot
: adds theHotModuleReplacementPlugin
and switch the server to hot mode. Note: make sure you don't addHotModuleReplacementPlugin
twice.--hot --inline
also adds thewebpack/hot/dev-server
entry.--lazy
: no watching, compiles on request (cannot be combined with--hot
).--https
: serves webpack-dev-server over HTTPS Protocol. Includes a self-signed certificate that is used when serving the requests.--cert
,--cacert
,--key
: Paths the certificate files.
Configuration under devServer
in webpack.config.js
are merged with the CLI options. For options under devServer
see next section.
API
var WebpackDevServer = require("webpack-dev-server");
var webpack = require("webpack");
var compiler = webpack({
// configuration
});
var server = new WebpackDevServer(compiler, {
// webpack-dev-server options
contentBase: "/path/to/directory",
// or: contentBase: "http://localhost/",
hot: true,
// Enable special support for Hot Module Replacement
// Page is no longer updated, but a "webpackHotUpdate" message is send to the content
// Use "webpack/hot/dev-server" as additional module in your entry point
// Note: this does _not_ add the `HotModuleReplacementPlugin` like the CLI option does.
// Set this as true if you want to access dev server from arbitrary url.
// This is handy if you are using a html5 router.
historyApiFallback: false,
// Set this if you want webpack-dev-server to delegate a single path to an arbitrary server.
// Use "*" to proxy all paths to the specified server.
// This is useful if you want to get rid of 'http://localhost:8080/' in script[src],
// and has many other use cases (see https://github.com/webpack/webpack-dev-server/pull/127 ).
proxy: {
"*": "http://localhost:9090"
},
// webpack-dev-middleware options
quiet: false,
noInfo: false,
lazy: true,
filename: "bundle.js",
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
publicPath: "/assets/",
headers: { "X-Custom-Header": "yes" },
stats: { colors: true },
});
server.listen(8080, "localhost", function() {});
// server.close();
See [[webpack-dev-middleware]] for documentation on middleware options.
Notice that webpack configuration is not passed to WebpackDevServer
API, thus devServer
option in webpack configuration is not used in this case. Also, there is no inline mode for WebpackDevServer
API. <script src="http://localhost:8080/webpack-dev-server.js"></script>
should be inserted to HTML page manually.
Combining with an existing server
You may want to run a backend server or a mock of it in development. You should not use the webpack-dev-server as a backend. Its only purpose is to serve static (webpacked) assets.
You can run two servers side-by-side: The webpack-dev-server and your backend server.
In this case you need to teach the webpack-generated assets to make requests to the webpack-dev-server even when running on a HTML-page sent by the backend server. On the other side you need to teach your backend server to generate HTML pages that include script
tags that point to assets on the webpack-dev-server. In addition to that you need a connection between the webpack-dev-server and the webpack-dev-server runtime to trigger reloads on recompilation.
To teach webpack to make requests (for chunk loading or HMR) to the webpack-dev-server you need to provide a full URL in the output.publicPath
option.
To make a connection between webpack-dev-server and its runtime best use the inline mode with --inline
. The webpack-dev-server CLI automatically includes an entry point which establishes a WebSocket connection. (You can also use the iframe mode if you point --content-base
of the webpack-dev-server to your backend server. If you need a websocket connection to your backend server, you'll have to use iframe mode.
When you use the inline mode just open the backend server URL in your web browsers. (If you use the iframe mode open the /webpack-dev-server/
prefixed URL of the webpack-dev-server.)
Summary and example:
- webpack-dev-server on port
8080
. - backend server on port
9090
. - generate HTML pages with
<script src="http://localhost:8080/assets/bundle.js">
. - webpack configuration with
output.publicPath = "http://localhost:8080/assets/"
. - when compiling files for production, use
--output-public-path /assets/
. - inline mode:
--inline
.- open
http://localhost:9090
.
- or iframe mode:
- webpack-dev-server
contentBase = "http://localhost:9090/"
(--content-base
). - open
http://localhost:8080/webpack-dev-server/
.
- webpack-dev-server
Or use the proxy option...