webpack-dev-server 是一个微型的 Express 服务器, 使用了webpack-dev-middleware 来为webpack bundle提供服务。同时也提供另一种方案,添加一个运行环境通过Socket.IO链接到服务器,服务器会推送关于编译状态的信息到对这些事件作出反应的客户端。你可以选择上述两种方案。取决于你的需要。好了我们来看看例子吧:

  1. var path = require("path");
  2. module.exports = {
  3. entry: {
  4. app: ["./app/main.js"]
  5. },
  6. output: {
  7. path: path.resolve(__dirname, "build"),
  8. publicPath: "/assets/",
  9. filename: "bundle.js"
  10. }
  11. };

webpack 将会把app文件夹下面的main.js打包到bundle.js放在build文件夹里。

内容基础

webpack-dev-server将会以当前的文件目录作为服务目录作为内容基础,除非你自己指定内容基础。

  1. $ webpack-dev-server --content-base build/

这样设置以后webpack-dev-server将build当作服务器的文件目录。它将监听文件的改动并且bundle将重新编译。这个被修改的bundle来自publicPath指定的相对目录下的内存(参看 API)。他将不会写入你配置好的文件输出路径里。(默认)将会写入到内存里面的bundle里,bundle和配置的outputpath拥有相同的url 路径。

有了上面的设置下下面这个就可以访问了。
localhost:8080/assets/bundle.js

为了加载bundle文件, 你需要在build目录下面,创建一个index.html文件
例如:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <script src="bundle.js"></script>
  9. </body>
  10. </html>

By default go to localhost:8080/ to launch your app. For example with the configuration above (with publicPath) go to localhost:8080/assets/.

自动刷新

webpack-dev-server 支持多个模式的自动刷新。

  • Iframe 模式 (页面内嵌到iframe里面,等文件改动时候刷新)
  • 行内模式 (在bundle文件里面添加一个小型webpack-dev-server客户端,当有改动触发刷新)
    每个模式都支持热替换,当有一个改动的时候bundle将被通知,而不是整个页面的刷新。然后热替换执行环境加载更新过的moudle然后注入到运行的app里面。

Iframe 模式

不需要改变配置. 只需要将浏览器打开 http://<host>:<port>/webpack-dev-server/<path>链接就可以. 比如. http://localhost:8080/webpack-dev-server/index.html.

  • 不需要改变配置.
  • 友好信息条展示在app的头部.
  • app的url改变 影响浏览器的地址栏变化.

Inline 模式

使用行内模式,你只需要在命令行加上--inline (不能在配置里面加)。这样webpack的配置里面就会加入webpack-dev-server的入口点。url请求方式没有改变还是http://<host>:<port>/<path>,比如http://localhost:8080/index.html

  • 需要命令行.
  • 在浏览器端会有状态日志.
  • app里面url改变会影响浏览器地址栏的url改变.

node.js API

webpack-dev-server里面没有inline:true标记,因为webpack-dev-server模块不能访问webpack配置。要在node api 里使用,就必须将webpack-dev-server客户端入口文件添加到webpack的配置里面。

想要这么做,只需要在所有的入口文件里面添加webpack-dev-server/client?http://<path>:<port>/就可以了。比如:

  1. var config = require("./webpack.config.js");
  2. config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");
  3. var compiler = webpack(config);
  4. var server = new WebpackDevServer(compiler, {...});
  5. server.listen(8080);

HTML

这同样是一种添加webpack-dev-server的方式:

  1. <script src="http://localhost:8080/webpack-dev-server.js"></script>

热替换

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.

CLI行内模式的热替换

Nothing more is 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:

  1. [HMR] Waiting for update signal from WDS...
  2. [WDS] Hot Module Replacement enabled.

Messages prefixed with [HMR] originate from the webpack/hot/dev-server module. Messages prefixed with [WDS] originate from the webpack-dev-server client.

It’s important to specify a correct output.publicPath otherwise the hot update chunks cannot be loaded.

热替换在node.js API应用

Similar to the inline mode the user must make 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 to the webpack-dev-server configuration to enable HMR on the server.

I. e. with the above configuration:

  1. var config = require("./webpack.config.js");
  2. config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server");
  3. var compiler = webpack(config);
  4. var server = new webpackDevServer(compiler, {
  5. hot: true
  6. ...
  7. });
  8. server.listen(8080);

Working with editors/IDEs supporting “safe write”

Note that many editors support “safe write” feature and have it enabled by default, which makes dev server unable to watch files correctly. “Safe write” means changes are not written directly to original file but to temporary one instead, which is renamed and replaces original file when save operation is completed successfully. This behaviour causes file watcher to lose the track because the original file is removed. In order to prevent this issue, you have to disable “safe write” feature in your editor.

  • VIM - set “:set backupcopy=yes” (see documentation)
  • IntelliJ - Settings -> System Settings -> Synchronization -> disable “safe write” (may differ in various IntelliJ IDEs, but you can still use the search feature)

代理

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.

  1. proxy: {
  2. '/some/path*': {
  3. target: 'https://other-server.example.com',
  4. secure: false
  5. }
  6. }

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.

绕开代理

(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.

  1. proxy: {
  2. '/some/path*': {
  3. target: 'https://other-server.example.com',
  4. secure: false,
  5. bypass: function(req, res, proxyOptions) {
  6. if (req.headers.accept.indexOf('html') !== -1) {
  7. console.log('Skipping proxy for browser request.');
  8. return '/index.html';
  9. }
  10. }
  11. }

重写代理请求url

(Added in v???) The request to the proxy can be optionally rewritten by providing a function. The function can inspect and change the HTTP request.

For example, the configuration below will rewrite the HTTP requests to remove the part /api at the beginning of the URL.

  1. proxy: {
  2. '/api/*': {
  3. target: 'https://other-server.example.com',
  4. rewrite: function(req) {
  5. req.url = req.url.replace(/^\/api/, '');
  6. }
  7. }
  8. }

webpack-dev-server CLI

  1. $ 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 use colors in the output.
  • --compress: use gzip compression.
  • --host <hostname/ip>: hostname or IP. 0.0.0.0 binds to all hosts.
  • --port <number>: port.
  • --inline: embed the webpack-dev-server runtime into the bundle.
  • --hot: adds the HotModuleReplacementPlugin and switch the server to hot mode. Note: make sure you don’t add HotModuleReplacementPlugin twice.
  • --hot --inline also adds the webpack/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.
  • --open: opens the url in default browser (for webpack-dev-server versions > 2.0).
  • --history-api-fallback: enables support for history API fallback.

Additional configuration options

When using the CLI it’s possible to have the webpack-dev-server options in the configuration file under the key devServer. Options passed via CLI arguments override options in configuration file. For options under devServer see next section.

Example

  1. module.exports = {
  2. // ...
  3. devServer: {
  4. hot: true
  5. }
  6. }

API

  1. var WebpackDevServer = require("webpack-dev-server");
  2. var webpack = require("webpack");
  3. var compiler = webpack({
  4. // configuration
  5. });
  6. var server = new WebpackDevServer(compiler, {
  7. // webpack-dev-server options
  8. contentBase: "/path/to/directory",
  9. // or: contentBase: "http://localhost/",
  10. hot: true,
  11. // Enable special support for Hot Module Replacement
  12. // Page is no longer updated, but a "webpackHotUpdate" message is send to the content
  13. // Use "webpack/hot/dev-server" as additional module in your entry point
  14. // Note: this does _not_ add the `HotModuleReplacementPlugin` like the CLI option does.
  15. // Set this as true if you want to access dev server from arbitrary url.
  16. // This is handy if you are using a html5 router.
  17. historyApiFallback: false,
  18. // Set this if you want to enable gzip compression for assets
  19. compress: true,
  20. // Set this if you want webpack-dev-server to delegate a single path to an arbitrary server.
  21. // Use "*" to proxy all paths to the specified server.
  22. // This is useful if you want to get rid of 'http://localhost:8080/' in script[src],
  23. // and has many other use cases (see https://github.com/webpack/webpack-dev-server/pull/127 ).
  24. proxy: {
  25. "*": "http://localhost:9090"
  26. },
  27. // pass [static options](http://expressjs.com/en/4x/api.html#express.static) to inner express server
  28. staticOptions: {
  29. },
  30. // webpack-dev-middleware options
  31. quiet: false,
  32. noInfo: false,
  33. lazy: true,
  34. filename: "bundle.js",
  35. watchOptions: {
  36. aggregateTimeout: 300,
  37. poll: 1000
  38. },
  39. publicPath: "/assets/",
  40. headers: { "X-Custom-Header": "yes" },
  41. stats: { colors: true }
  42. });
  43. server.listen(8080, "localhost", function() {});
  44. // 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.

The historyApiFallback option

If you are using the HTML5 history API you probably need to serve your index.html in place of 404 responses, which can be done by setting historyApiFallback: true. However, if you have modified output.publicPath in your Webpack configuration, you need to specify the URL to redirect to. This is done using the historyApiFallback.index option:

  1. // output.publicPath: '/foo-app/'
  2. historyApiFallback: {
  3. index: '/foo-app/'
  4. }

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

Or use the proxy option…