DevServer

webpack-dev-server can be used to quickly develop an application. See the development guide to get started.

This page describes the options that affect the behavior of webpack-dev-server (short: dev-server) version >= 4.0.0. Migration guide from v3 to v4 can be found here.

devServer

object

This set of options is picked up by webpack-dev-server and can be used to change its behavior in various ways. Here's a rudimentary example that gzips and serves everything from our public/ directory in the project root:

webpack.config.js

var path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    compress: true,
    port: 9000,
  },
};

When the server is started, there will be a message prior to the list of resolved modules:

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:9000/
<i> [webpack-dev-server] On Your Network (IPv4): http://197.158.164.104:9000/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::1]:9000/
<i> [webpack-dev-server] Content not from webpack is served from '/path/to/public' directory

that will give some background on where the server is located and what it's serving.

If you're using dev-server through the Node.js API, the options in devServer will be ignored. Pass the options as the first parameter instead: new WebpackDevServer({...}, compiler). See here for an example of how to use webpack-dev-server through the Node.js API.

Usage via CLI

You can invoke webpack-dev-server via CLI by:

npx webpack serve

A list of CLI options for serve is available here

devServer.allowedHosts

'auto' | 'all' [string]

This option allows you to whitelist services that are allowed to access the dev server.

webpack.config.js

module.exports = {
  //...
  devServer: {
    allowedHosts: [
      'host.com',
      'subdomain.host.com',
      'subdomain2.host.com',
      'host2.com',
    ],
  },
};

Mimicking django's ALLOWED_HOSTS, a value beginning with . can be used as a subdomain wildcard. .host.com will match host.com, www.host.com, and any other subdomain of host.com.

webpack.config.js

module.exports = {
  //...
  devServer: {
    // this achieves the same effect as the first example
    // with the bonus of not having to update your config
    // if new subdomains need to access the dev server
    allowedHosts: ['.host.com', 'host2.com'],
  },
};

When set to 'all' this option bypasses host checking. THIS IS NOT RECOMMENDED as apps that do not check the host are vulnerable to DNS rebinding attacks.

webpack.config.js

module.exports = {
  //...
  devServer: {
    allowedHosts: 'all',
  },
};

To use this option with the CLI pass the --allowed-hosts as following:

npx webpack serve --entry ./entry/file --output-path ./output/path --allowed-hosts .host.com --allowed-hosts host2.com

devServer.bonjour

boolean object

This option broadcasts the server via ZeroConf networking on start.

webpack.config.js

module.exports = {
  //...
  devServer: {
    bonjour: true,
  },
};

Usage via the CLI:

npx webpack serve --bonjour

You can also pass custom options to bonjour, for example:

webpack.config.js

module.exports = {
  //...
  devServer: {
    bonjour: {
      type: 'http',
      protocol: 'udp',
    },
  },
};

devServer.client

logging

'log' | 'info' | 'warn' | 'error' | 'none' | 'verbose'

Allows to set log level in the browser, e.g. before reloading, before an error or when Hot Module Replacement is enabled.

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      logging: 'info',
    },
  },
};

Usage via the CLI:

npx webpack serve --client-logging info

overlay

boolean = true object: { errors boolean = true, warnings boolean = true }

Shows a full-screen overlay in the browser when there are compiler errors or warnings.

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      overlay: true,
    },
  },
};

Usage via the CLI:

npx webpack serve --client-overlay

If you want to show only errors:

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      overlay: {
        errors: true,
        warnings: false,
      },
    },
  },
};

Usage via the CLI:

npx webpack serve --client-overlay-errors --no-client-overlay-warnings

progress

Prints compilation progress in percentage in the browser.

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      progress: true,
    },
  },
};

Usage via the CLI:

npx webpack serve --client-progress

webSocketTransport

'ws' | 'sockjs' string

This option allows us either to choose the current devServer transport mode for client individually or to provide custom client implementation. This allows to specify how browser or other client communicates with the devServer.

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketTransport: 'ws',
    },
    webSocketServer: 'ws',
  },
};

Usage via the CLI:

npx webpack serve --client-web-socket-transport ws --web-socket-server ws

To create a custom client implementation, create a class that extends BaseClient.

Using path to CustomClient.js, a custom WebSocket client implementation, along with the compatible 'ws' server:

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketTransport: require.resolve('./CustomClient'),
    },
    webSocketServer: 'ws',
  },
};

Using custom, compatible WebSocket client and server implementations:

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketTransport: require.resolve('./CustomClient'),
    },
    webSocketServer: require.resolve('./CustomServer'),
  },
};

webSocketURL

string object

This option allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketURL: 'ws://0.0.0.0:8080/ws',
    },
  },
};

Usage via the CLI:

npx webpack serve --client-web-socket-url ws://0.0.0.0:8080/ws

You can also specify an object with the following properties:

  • hostname: Tells clients connected to devServer to use the provided hostname.
  • pathname: Tells clients connected to devServer to use the provided path to connect.
  • password: Tells clients connected to devServer to use the provided password to authenticate.
  • port: Tells clients connected to devServer to use the provided port.
  • protocol: Tells clients connected to devServer to use the provided protocol.
  • username: Tells clients connected to devServer to use the provided username to authenticate.

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketURL: {
        hostname: '0.0.0.0',
        pathname: '/ws',
        password: 'dev-server',
        port: 8080,
        protocol: 'ws',
        username: 'webpack',
      },
    },
  },
};

devServer.compress

boolean = true

Enable gzip compression for everything served:

webpack.config.js

module.exports = {
  //...
  devServer: {
    compress: true,
  },
};

Usage via the CLI:

npx webpack serve --compress

devserver.devMiddleware

Provide options to webpack-dev-middleware which handles webpack assets.

webpack.config.js

module.exports = {
  devServer: {
    index: true,
    mimeTypes: { 'text/html': ['phtml'] },
    publicPath: '/publicPathForDevServe',
    serverSideRender: true,
    writeToDisk: true,
  },
};

devServer.http2

boolean

Serve over HTTP/2 using spdy. This option is ignored for Node 15.0.0 and above, as spdy is broken for those versions. The dev server will migrate over to Node's built-in HTTP/2 once Express supports it.

HTTP/2 with a self-signed certificate:

webpack.config.js

module.exports = {
  //...
  devServer: {
    http2: true,
  },
};

Provide your own certificate using the https option:

webpack.config.js

module.exports = {
  //...
  devServer: {
    http2: true,
    https: {
      key: fs.readFileSync('/path/to/server.key'),
      cert: fs.readFileSync('/path/to/server.crt'),
      cacert: fs.readFileSync('/path/to/ca.pem'),
    },
  },
};

Usage via CLI

npx webpack serve --http2

To pass your own certificate via CLI, use the following options

npx webpack serve --http2 --https-key ./path/to/server.key --https-cert ./path/to/server.crt --https-cacert ./path/to/ca.pem

devServer.https

boolean object

By default, dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS:

webpack.config.js

module.exports = {
  //...
  devServer: {
    https: true,
  },
};

With the above setting, a self-signed certificate is used, but you can provide your own:

webpack.config.js

module.exports = {
  devServer: {
    https: {
      cacert: './server.pem',
      pfx: './server.pfx',
      key: './server.key',
      cert: './server.crt',
      passphrase: 'webpack-dev-server',
      requestCert: true,
    },
  },
};

This object is passed straight to Node.js HTTPS module, so see the HTTPS documentation for more information.

Usage via the CLI:

npx webpack serve --https

To pass your own certificate via the CLI use the following options

npx webpack serve --https-key ./path/to/server.key --https--cert ./path/to/server.crt --https-cacert ./path/to/ca.pem

devServer.headers

function object

Adds headers to all responses:

webpack.config.js

module.exports = {
  //...
  devServer: {
    headers: {
      'X-Custom-Foo': 'bar',
    },
  },
};

devServer.historyApiFallback

boolean object

When using the HTML5 History API, the index.html page will likely have to be served in place of any 404 responses. Enable devServer.historyApiFallback by setting it to true:

webpack.config.js

module.exports = {
  //...
  devServer: {
    historyApiFallback: true,
  },
};

By passing an object this behavior can be controlled further using options like rewrites:

webpack.config.js

module.exports = {
  //...
  devServer: {
    historyApiFallback: {
      rewrites: [
        { from: /^\/$/, to: '/views/landing.html' },
        { from: /^\/subpage/, to: '/views/subpage.html' },
        { from: /./, to: '/views/404.html' },
      ],
    },
  },
};

When using dots in your path (common with Angular), you may need to use the disableDotRule:

webpack.config.js

module.exports = {
  //...
  devServer: {
    historyApiFallback: {
      disableDotRule: true,
    },
  },
};

Usage via the CLI:

npx webpack serve --history-api-fallback

For more options and information, see the connect-history-api-fallback documentation.

devServer.host

'local-ip' | 'local-ipv4' | 'local-ipv6' string

Specify a host to use. If you want your server to be accessible externally, specify it like this:

webpack.config.js

module.exports = {
  //...
  devServer: {
    host: '0.0.0.0',
  },
};

Usage via the CLI:

npx webpack serve --host 0.0.0.0

This also works with IPv6:

npx webpack serve --host ::

local-ip

Specifying local-ip as host will try to resolve the host option as your local IPv4 address if available, if IPv4 is not available it will try to resolve your local IPv6 address.

npx webpack serve --host local-ip

local-ipv4

Specifying local-ipv4 as host will try to resolve the host option as your local IPv4 address.

npx webpack serve --host local-ipv4

local-ipv6

Specifying local-ipv6 as host will try to resolve the host option as your local IPv6 address.

npx webpack serve --host local-ipv6

devServer.hot

'only' boolean

Enable webpack's Hot Module Replacement feature:

webpack.config.js

module.exports = {
  //...
  devServer: {
    hot: true,
  },
};

Usage via the CLI:

npx webpack serve --hot

To enable Hot Module Replacement without page refresh as a fallback in case of build failures, use hot: 'only':

webpack.config.js

module.exports = {
  //...
  devServer: {
    hot: 'only',
  },
};

Usage via the CLI:

npx webpack serve --hot only

devServer.ipc

true string

The Unix socket to listen to (instead of a host).

Setting it to true will listen to a socket at /your-os-temp-dir/webpack-dev-server.sock:

webpack.config.js

module.exports = {
  //...
  devServer: {
    ipc: true,
  },
};

Usage via the CLI:

npx webpack serve --ipc

You can also listen to a different socket with:

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    ipc: path.join(__dirname, 'my-socket.sock'),
  },
};

devServer.liveReload

boolean = true

By default, the dev-server will reload/refresh the page when file changes are detected. devServer.hot option must be disabled or devServer.watchFiles option must be enabled in order for liveReload to take effect. Disable devServer.liveReload by setting it to false:

webpack.config.js

module.exports = {
  //...
  devServer: {
    liveReload: false,
  },
};

Usage via the CLI:

npx webpack serve --live-reload

To disable:

npx webpack serve --no-live-reload

devServer.onAfterSetupMiddleware

function (app, server, compiler)

Provides the ability to execute custom middleware after all other middleware internally within the server.

webpack.config.js

module.exports = {
  //...
  devServer: {
    onAfterSetupMiddleware: function (devServer) {
      devServer.app.get('/some/path', function (req, res) {
        res.json({ custom: 'response' });
      });
    },
  },
};

devServer.onBeforeSetupMiddleware

function (app, server, compiler)

Provides the ability to execute custom middleware prior to all other middleware internally within the server. This could be used to define custom handlers, for example:

webpack.config.js

module.exports = {
  //...
  devServer: {
    onBeforeSetupMiddleware: function (app, server, compiler) {
      app.get('/some/path', function (req, res) {
        res.json({ custom: 'response' });
      });
    },
  },
};

devserver.onListening

function (server)

Provides the ability to execute a custom function when webpack-dev-server starts listening for connections on a port.

webpack.config.js

module.exports = {
  //...
  devServer: {
    onListening: function (server) {
      const port = server.address().port;
      console.log('Listening on port:', port);
    },
  },
};

devServer.open

boolean string [string] object [object]

Tells dev-server to open the browser after server had been started. Set it to true to open your default browser.

webpack.config.js

module.exports = {
  //...
  devServer: {
    open: true,
  },
};

Usage via the CLI:

npx webpack serve --open

To open a specified page in browser:

webpack.config.js

module.exports = {
  //...
  devServer: {
    open: ['/my-page'],
  },
};

Usage via the CLI:

npx webpack serve --open /my-page

To open multiple specified pages in browser:

webpack.config.js

module.exports = {
  //...
  devServer: {
    open: ['/my-page', '/another-page'],
  },
};

Usage via the CLI:

npx webpack serve --open /my-page --open /another-page

Provide browser name to use instead of the default one:

webpack.config.js

module.exports = {
  //...
  devServer: {
    open: {
      app: {
        name: 'google-chrome',
      },
    },
  },
};

Usage via the CLI:

npx webpack serve --open-app-name 'google-chrome'

The object accepts all open options:

webpack.config.js

module.exports = {
  //...
  devServer: {
    open: {
      target: ['first.html', 'http://localhost:8080/second.html'],
      app: {
        name: 'google-chrome',
        arguments: ['--incognito', '--new-window'],
      },
    },
  },
};

devServer.port

'auto' string number

Specify a port number to listen for requests on:

webpack.config.js

module.exports = {
  //...
  devServer: {
    port: 8080,
  },
};

Usage via the CLI:

npx webpack serve --port 8080

port option can't be null or empty string, to automatically use a free port please use port: 'auto':

webpack.config.js

module.exports = {
  //...
  devServer: {
    port: 'auto',
  },
};

devServer.proxy

object [object, function]

Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain.

The dev-server makes use of the powerful http-proxy-middleware package. Check out its documentation for more advanced usages. Note that some of http-proxy-middleware's features do not require a target key, e.g. its router feature, but you will still need to include a target key in your configuration here, otherwise webpack-dev-server won't pass it along to http-proxy-middleware).

With a backend on localhost:3000, you can use this to enable proxying:

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': 'http://localhost:3000',
    },
  },
};

A request to /api/users will now proxy the request to http://localhost:3000/api/users.

If you don't want /api to be passed along, we need to rewrite the path:

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: { '^/api': '' },
      },
    },
  },
};

A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your configuration like this:

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'https://other-server.example.com',
        secure: false,
      },
    },
  },
};

Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function.

In the function you get access to the request, response, and proxy options.

  • Return null or undefined to continue processing the request with proxy.
  • Return false to produce a 404 error for the request.
  • Return a path to serve from, instead of continuing to proxy the request.

E.g. for a browser request, you want to serve an HTML page, but for an API request you want to proxy it. You could do something like this:

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        bypass: function (req, res, proxyOptions) {
          if (req.headers.accept.indexOf('html') !== -1) {
            console.log('Skipping proxy for browser request.');
            return '/index.html';
          }
        },
      },
    },
  },
};

If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a context property:

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: [
      {
        context: ['/auth', '/api'],
        target: 'http://localhost:3000',
      },
    ],
  },
};

Note that requests to root won't be proxied by default. To enable root proxying, the devServer.index option should be specified as a falsy value:

webpack.config.js

module.exports = {
  //...
  devServer: {
    index: '', // specify to enable root proxying
    host: '...',
    contentBase: '...',
    proxy: {
      context: () => true,
      target: 'http://localhost:1234',
    },
  },
};

The origin of the host header is kept when proxying by default, you can set changeOrigin to true to override this behaviour. It is useful in some cases like using name-based virtual hosted sites.

webpack.config.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
      },
    },
  },
};

devServer.setupExitSignals

boolean = true

Allows to close dev server and exit the process on SIGINT and SIGTERM signals.

webpack.config.js

module.exports = {
  //...
  devServer: {
    setupExitSignals: true,
  },
};

devServer.static

boolean string [string] object [object]

This options allows to configure options for serving static files from directory (by default 'public' directory). To disable set it to false:

webpack.config.js

module.exports = {
  //...
  devServer: {
    static: false,
  },
};

Usage via CLI:

npx webpack serve --static

To disable:

npx webpack serve --no-static

directory

string = path.join(process.cwd(), 'public')

Tell the server where to serve the content from. This is only necessary if you want to serve static files. static.publicPath will be used to determine where the bundles should be served from, and takes precedence.

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
  },
};

staticOptions

It is possible to configure advanced options for serving static files from static.directory. See the Express documentation for the possible options.

webpack.config.js

module.exports = {
  //...
  devServer: {
    static: {
      staticOptions: {
        redirect: true,
      },
    },
  },
};

publicPath

string = '/' [string]

Tell the server at which URL to serve static.directory content. For example to serve a file assets/manifest.json at /serve-public-path-url/manifest.json, your configurations should be as following:

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'assets'),
      publicPath: '/serve-public-path-url',
    },
  },
};

Provide an array of objects in case you have multiple static folders:

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: [
      {
        directory: path.join(__dirname, 'assets'),
        publicPath: '/serve-public-path-url',
      },
      {
        directory: path.join(__dirname, 'css'),
        publicPath: '/other-serve-public-path-url',
      },
    ],
  },
};

serveIndex

boolean object = { icons: true }

Tell dev-server to use serveIndex middleware when enabled.

serveIndex middleware generates directory listings on viewing directories that don't have an index.html file.

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
      serveIndex: true,
    },
  },
};

Usage via CLI:

npx webpack serve --static-serve-index

To disable:

npx webpack serve --no-static-serve-index

watch

boolean object

Tell dev-server to watch the files served by the static.directory option. It is disabled by default. When enabled, file changes will trigger a full page reload.

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
      watch: true,
    },
  },
};

Usage via CLI:

npx webpack serve --static-watch

To disable:

npx webpack serve --no-static-watch

It is possible to configure advanced options for watching static files from static.directory. See the chokidar documentation for the possible options.

webpack.config.js

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
      watch: {
        ignored: '*.txt',
        usePolling: false,
      },
    },
  },
};

devServer.watchFiles

string [string] object [object]

This option allows you to configure list of globs/directories/files to watch for file changes. For example:

webpack.config.js

module.exports = {
  //...
  devServer: {
    watchFiles: ['src/**/*.php', 'public/**/*'],
  },
};

It is possible to configure advanced options for watching files. See the chokidar documentation for the possible options.

webpack.config.js

module.exports = {
  //...
  devServer: {
    watchFiles: {
      paths: ['src/**/*.php', 'public/**/*'],
      options: {
        usePolling: false,
      },
    },
  },
};

devServer.webSocketServer

false | 'sockjs' | 'ws' string function object

This option allows us either to choose the current web-socket server or to provide custom web-socket server implementation.

The current default mode is 'ws'. This mode uses ws as a server, and native WebSockets on the client.

webpack.config.js

module.exports = {
  //...
  devServer: {
    webSocketServer: 'ws',
  },
};

To create a custom server implementation, create a class that extends BaseServer.

Using path to CustomServer.js, a custom WebSocket server implementation, along with the compatible 'ws' client:

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketTransport: 'ws',
    },
    webSocketServer: require.resolve('./CustomServer'),
  },
};

Using custom, compatible WebSocket client and server implementations:

webpack.config.js

module.exports = {
  //...
  devServer: {
    client: {
      webSocketTransport: require.resolve('./CustomClient'),
    },
    webSocketServer: require.resolve('./CustomServer'),
  },
};