├── .husky
├── pre-commit
└── commit-msg
├── test
├── fixtures
│ ├── overlay-config
│ │ ├── foo.js
│ │ ├── webpack.config.js
│ │ └── trusted-types.webpack.config.js
│ ├── static-config
│ │ ├── public
│ │ │ ├── foo.wasm
│ │ │ ├── assets
│ │ │ │ ├── example.txt
│ │ │ │ └── other.txt
│ │ │ ├── bar
│ │ │ │ └── index.html
│ │ │ ├── index.html
│ │ │ ├── node_modules
│ │ │ │ └── .gitkeep
│ │ │ └── other.html
│ │ ├── other
│ │ │ └── foo.html
│ │ ├── static
│ │ │ └── index.html
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── client-config
│ │ ├── static
│ │ │ └── foo.txt
│ │ ├── index.html
│ │ ├── bar.js
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── proxy-config
│ │ ├── index.html
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── https-certificate
│ │ ├── ca-symlink.pem
│ │ ├── server-symlink.crt
│ │ ├── server-symlink.key
│ │ ├── server-symlink.pfx
│ │ ├── server.pfx
│ │ └── server.crt
│ ├── mime-types-config
│ │ ├── file.custom
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── multi-public-path-config
│ │ ├── test.html
│ │ ├── bar.js
│ │ ├── baz.js
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── watch-files-config
│ │ ├── other
│ │ │ └── foo.html
│ │ ├── public
│ │ │ ├── assets
│ │ │ │ ├── example.txt
│ │ │ │ └── other.txt
│ │ │ ├── bar
│ │ │ │ └── index.html
│ │ │ └── other.html
│ │ ├── static
│ │ │ └── index.html
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── historyapifallback-2-config
│ │ ├── bar.html
│ │ ├── other.html
│ │ ├── random-file.txt
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── historyapifallback-config
│ │ ├── bar.html
│ │ ├── index.html
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── historyapifallback-3-config
│ │ ├── index.html
│ │ ├── bar.html
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── dev-server
│ │ ├── bar.js
│ │ ├── foo.js
│ │ ├── client-default-path-config.js
│ │ └── client-custom-path-config.js
│ ├── simple-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── static
│ │ ├── foo.js
│ │ ├── webpack.config.js
│ │ └── static
│ │ │ └── index.html
│ ├── cli-multi-entry
│ │ ├── bar.js
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── reload-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-colors-disabled
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-colors-enabled
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-promise-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-single-entry
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-target-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── dev-public-path
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── entry-as-function
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-colors-default-stats
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-entry-as-descriptor
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── lazy-compilation-multiple-entries
│ │ ├── one.js
│ │ └── two.js
│ ├── lazy-compilation-single-entry
│ │ ├── entry.js
│ │ └── webpack.config.js
│ ├── module-federation-config
│ │ ├── entry1.js
│ │ ├── entry2.js
│ │ ├── webpack.config.js
│ │ ├── webpack.multi.config.js
│ │ ├── webpack.object-entry.config.js
│ │ └── webpack.plugin.js
│ ├── multi-compiler-one-configuration
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── multi-compiler-two-configurations
│ │ ├── one.js
│ │ ├── two.js
│ │ └── webpack.config.js
│ ├── custom-client
│ │ ├── CustomClientEntry.js
│ │ ├── CustomClientHotEntry.js
│ │ └── CustomSockJSClient.js
│ ├── cli-universal-compiler-config
│ │ ├── client.js
│ │ ├── server.js
│ │ └── webpack.config.js
│ ├── universal-compiler-config
│ │ ├── browser.js
│ │ ├── server.js
│ │ └── webpack.config.js
│ ├── reload-config-2
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── cli-empty-entry
│ │ └── webpack.config.js
│ ├── worker-config
│ │ ├── worker.js
│ │ ├── index.js
│ │ └── webpack.config.js
│ ├── worker-config-dev-server-false
│ │ ├── worker.js
│ │ ├── index.js
│ │ └── webpack.config.js
│ ├── schema
│ │ └── webpack.config.simple.js
│ ├── simple-config-other
│ │ ├── webpack.config.js
│ │ └── foo.js
│ ├── provide-plugin-custom
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── provide-plugin-sockjs-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── provide-plugin-default
│ │ ├── foo.js
│ │ └── webpack.config.js
│ ├── provide-plugin-ws-config
│ │ ├── foo.js
│ │ └── webpack.config.js
│ └── ssl
│ │ └── localhost-cert.pem
├── helpers
│ ├── custom-http.js
│ ├── session-subscribe.js
│ ├── conditional-test.js
│ ├── ExitOnDonePlugin.js
│ ├── snapshotResolver.js
│ └── normalize-options.js
├── client
│ ├── clients
│ │ └── __snapshots__
│ │ │ ├── SockJSClient.test.js.snap.webpack5
│ │ │ └── WebsocketClient.test.js.snap.webpack5
│ └── utils
│ │ ├── __snapshots__
│ │ ├── sendMessage.test.js.snap.webpack5
│ │ ├── log.test.js.snap.webpack5
│ │ ├── reloadApp.test.js.snap.webpack5
│ │ └── getCurrentScriptSource.test.js.snap.webpack5
│ │ ├── sendMessage.test.js
│ │ └── log.test.js
├── e2e
│ └── __snapshots__
│ │ ├── web-socket-server.test.js.snap.webpack5
│ │ ├── mime-types.test.js.snap.webpack5
│ │ ├── client.test.js.snap.webpack5
│ │ ├── on-listening.test.js.snap.webpack5
│ │ └── setup-exit-signals.test.js.snap.webpack5
└── cli
│ ├── compress-option.test.js
│ ├── liveReload-option.test.js
│ ├── __snapshots__
│ ├── ipc-option.test.js.snap.webpack5
│ ├── port-option.test.js.snap.webpack5
│ └── historyApiFallback-option.test.js.snap.webpack5
│ ├── port-option.test.js
│ ├── ipc-option.test.js
│ ├── historyApiFallback-option.test.js
│ ├── webSocketServer-option.test.js
│ ├── hot-option.test.js
│ └── allowedHosts-option.test.js
├── .gitattributes
├── examples
├── history-api-fallback
│ ├── file.txt
│ └── webpack.config.js
├── watch-static
│ ├── css
│ │ └── styles.css
│ ├── app.js
│ ├── assets
│ │ └── index.html
│ ├── webpack.config.js
│ └── README.md
├── default
│ ├── style.less
│ ├── pixels.png
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── general
│ ├── config-array
│ │ ├── style.less
│ │ ├── pixels.png
│ │ ├── app.js
│ │ ├── README.md
│ │ └── webpack.config.js
│ ├── universal-config
│ │ ├── server.js
│ │ ├── README.md
│ │ ├── webpack.config.js
│ │ └── client.js
│ ├── proxy-advanced
│ │ ├── bypass.html
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── proxy-simple
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── proxy-hot-reload
│ │ ├── app.js
│ │ ├── proxy-config.js
│ │ ├── README.md
│ │ └── webpack.config.js
│ ├── webworker
│ │ ├── worker.js
│ │ ├── web.js
│ │ ├── README.md
│ │ └── webpack.config.js
│ └── config-promise
│ │ ├── app.js
│ │ ├── index.html
│ │ ├── webpack.config.js
│ │ └── README.md
├── .assets
│ ├── favicon.ico
│ ├── geomanist-medium.woff
│ ├── geomanist-medium.woff2
│ ├── icon-square.svg
│ └── layout.html
├── server
│ ├── spdy
│ │ ├── ssl
│ │ │ ├── server.pfx
│ │ │ └── server.crt
│ │ ├── app.js
│ │ └── webpack.config.js
│ ├── https
│ │ ├── ssl
│ │ │ ├── server.pfx
│ │ │ └── server.crt
│ │ ├── app.js
│ │ └── webpack.config.js
│ └── http2
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
├── ipc
│ ├── app.js
│ ├── README.md
│ └── webpack.config.js
├── api
│ ├── start
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── server.js
│ │ └── README.md
│ ├── middleware
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── server.js
│ │ └── README.md
│ ├── start-callback
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── server.js
│ │ └── README.md
│ ├── stop
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── server.js
│ │ └── README.md
│ ├── stop-callback
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── server.js
│ │ └── README.md
│ ├── internal-ip-sync
│ │ ├── app.js
│ │ └── README.md
│ ├── simple
│ │ ├── webpack.config.js
│ │ ├── app.js
│ │ ├── server.js
│ │ └── README.md
│ └── internal-ip
│ │ ├── app.js
│ │ └── README.md
├── app
│ ├── connect
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── hono
│ │ ├── app.js
│ │ ├── README.md
│ │ └── ssl
│ │ └── localhost-cert.pem
├── bonjour
│ ├── boolean
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── object
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
├── node-false
│ ├── app.js
│ ├── README.md
│ └── webpack.config.js
├── client
│ ├── logging
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── progress
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── web-socket-url
│ │ ├── index.html
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── trusted-types-overlay
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ ├── README.md
│ │ └── layout.html
│ ├── reconnect
│ │ ├── false
│ │ │ ├── app.js
│ │ │ ├── webpack.config.js
│ │ │ └── README.md
│ │ ├── number
│ │ │ ├── app.js
│ │ │ ├── webpack.config.js
│ │ │ └── README.md
│ │ └── true
│ │ │ ├── app.js
│ │ │ └── webpack.config.js
│ └── overlay
│ │ ├── create-button.js
│ │ ├── webpack.config.js
│ │ └── app.js
├── compression
│ ├── true
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── false
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
├── dev-middleware
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── headers
│ ├── array
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ ├── function
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── object
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
├── host-and-port
│ ├── app.js
│ └── webpack.config.js
├── on-listening
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── setup-middlewares
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── web-socket-server
│ ├── ws
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── sockjs
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
├── proxy
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── hmr
│ ├── only
│ │ ├── example.js
│ │ ├── app.js
│ │ ├── webpack.config.js
│ │ └── README.md
│ └── boolean
│ │ ├── app.js
│ │ ├── example.js
│ │ └── webpack.config.js
├── multi-compiler
│ ├── app.js
│ ├── webpack.config.js
│ └── README.md
├── open-target
│ ├── app.js
│ └── webpack.config.js
├── open-target-multiple
│ ├── app1.js
│ ├── app2.js
│ ├── README.md
│ └── webpack.config.js
└── README.md
├── client-src
├── modules
│ ├── sockjs-client
│ │ └── index.js
│ └── logger
│ │ ├── index.js
│ │ └── tapable.js
├── utils
│ ├── sendMessage.js
│ └── log.js
├── globals.d.ts
└── clients
│ ├── WebSocketClient.js
│ └── SockJSClient.js
├── .prettierignore
├── scripts
├── setupTest.js
├── prepare-test-for-old-node.js
├── extend-webpack-types.js
└── globalSetupTest.js
├── .versionrc
├── lint-staged.config.js
├── commitlint.config.js
├── .editorconfig
├── types
├── lib
│ ├── getPort.d.ts
│ └── servers
│ │ ├── BaseServer.d.ts
│ │ ├── SockJSServer.d.ts
│ │ └── WebsocketServer.d.ts
└── bin
│ └── webpack-dev-server.d.ts
├── .github
├── dependabot.yml
└── workflows
│ └── dependency-review.yml
├── tsconfig.json
├── CODE_OF_CONDUCT.md
├── lib
└── servers
│ └── BaseServer.js
├── tsconfig.client.json
├── .gitignore
├── babel.config.js
├── eslint.config.mjs
└── LICENSE
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | lint-staged
2 |
--------------------------------------------------------------------------------
/test/fixtures/overlay-config/foo.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | commitlint --edit $1
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/foo.wasm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | bin/* eol=lf
3 |
--------------------------------------------------------------------------------
/examples/history-api-fallback/file.txt:
--------------------------------------------------------------------------------
1 | file
2 |
--------------------------------------------------------------------------------
/test/fixtures/client-config/static/foo.txt:
--------------------------------------------------------------------------------
1 | Text
--------------------------------------------------------------------------------
/test/fixtures/proxy-config/index.html:
--------------------------------------------------------------------------------
1 | Hello
2 |
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/ca-symlink.pem:
--------------------------------------------------------------------------------
1 | ca.pem
--------------------------------------------------------------------------------
/test/fixtures/mime-types-config/file.custom:
--------------------------------------------------------------------------------
1 | test
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/other/foo.html:
--------------------------------------------------------------------------------
1 | Foo!
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/assets/example.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/assets/other.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/multi-public-path-config/test.html:
--------------------------------------------------------------------------------
1 | hello
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/bar/index.html:
--------------------------------------------------------------------------------
1 | Heyo
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/index.html:
--------------------------------------------------------------------------------
1 | Heyo.
2 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/node_modules/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/static/index.html:
--------------------------------------------------------------------------------
1 | Heyo.
2 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/other/foo.html:
--------------------------------------------------------------------------------
1 | Foo!
2 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/public/assets/example.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/public/assets/other.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-2-config/bar.html:
--------------------------------------------------------------------------------
1 | Foobar
2 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-config/bar.html:
--------------------------------------------------------------------------------
1 | Foobar
2 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-config/index.html:
--------------------------------------------------------------------------------
1 | Heyyy
2 |
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/server-symlink.crt:
--------------------------------------------------------------------------------
1 | server.crt
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/server-symlink.key:
--------------------------------------------------------------------------------
1 | server.key
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/server-symlink.pfx:
--------------------------------------------------------------------------------
1 | server.pfx
--------------------------------------------------------------------------------
/test/fixtures/static-config/public/other.html:
--------------------------------------------------------------------------------
1 | Other html
2 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/public/bar/index.html:
--------------------------------------------------------------------------------
1 | Heyo
2 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/static/index.html:
--------------------------------------------------------------------------------
1 | Heyo.
2 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-2-config/other.html:
--------------------------------------------------------------------------------
1 | Other file
2 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-3-config/index.html:
--------------------------------------------------------------------------------
1 | static file
2 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/public/other.html:
--------------------------------------------------------------------------------
1 | Other html
2 |
--------------------------------------------------------------------------------
/examples/watch-static/css/styles.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | color: blue;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-2-config/random-file.txt:
--------------------------------------------------------------------------------
1 | Random file
2 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-3-config/bar.html:
--------------------------------------------------------------------------------
1 | In-memory file
2 |
--------------------------------------------------------------------------------
/test/fixtures/cli/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/client-config/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/examples/default/style.less:
--------------------------------------------------------------------------------
1 | body {
2 | background: url(pixels.png);
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/client-config/bar.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Bar.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/client-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/dev-server/bar.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am bar");
4 |
--------------------------------------------------------------------------------
/test/fixtures/dev-server/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am foo");
4 |
--------------------------------------------------------------------------------
/test/fixtures/proxy-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/simple-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/static/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/client-src/modules/sockjs-client/index.js:
--------------------------------------------------------------------------------
1 | export { default } from "sockjs-client";
2 |
--------------------------------------------------------------------------------
/test/fixtures/cli-multi-entry/bar.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am bar");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-multi-entry/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am foo");
4 |
--------------------------------------------------------------------------------
/test/fixtures/reload-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./main.css");
4 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/examples/general/config-array/style.less:
--------------------------------------------------------------------------------
1 | body {
2 | background: url(pixels.png);
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-disabled/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-enabled/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-promise-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-single-entry/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am foo");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-target-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("I am foo");
4 |
--------------------------------------------------------------------------------
/test/fixtures/dev-public-path/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/entry-as-function/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-public-path-config/bar.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-public-path-config/baz.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-default-stats/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-entry-as-descriptor/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("i am foo!");
4 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-2-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-public-path-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./test.html");
4 |
--------------------------------------------------------------------------------
/test/fixtures/lazy-compilation-multiple-entries/one.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("One.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/lazy-compilation-multiple-entries/two.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Two.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/lazy-compilation-single-entry/entry.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/entry1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = "entry1";
4 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/entry2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = "entry2";
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-compiler-one-configuration/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hey.");
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-compiler-two-configurations/one.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("one");
4 |
--------------------------------------------------------------------------------
/test/fixtures/multi-compiler-two-configurations/two.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("two");
4 |
--------------------------------------------------------------------------------
/examples/general/universal-config/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("webpack-dev-server/server");
4 |
--------------------------------------------------------------------------------
/test/fixtures/custom-client/CustomClientEntry.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("custom client entry");
4 |
--------------------------------------------------------------------------------
/examples/.assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/.assets/favicon.ico
--------------------------------------------------------------------------------
/examples/default/pixels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/default/pixels.png
--------------------------------------------------------------------------------
/test/fixtures/cli-universal-compiler-config/client.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hello from the client");
4 |
--------------------------------------------------------------------------------
/test/fixtures/cli-universal-compiler-config/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hello from the server");
4 |
--------------------------------------------------------------------------------
/test/fixtures/custom-client/CustomClientHotEntry.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("custom client hot entry");
4 |
--------------------------------------------------------------------------------
/test/fixtures/universal-compiler-config/browser.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hello from the browser");
4 |
--------------------------------------------------------------------------------
/test/fixtures/universal-compiler-config/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log("Hello from the server");
4 |
--------------------------------------------------------------------------------
/client-src/modules/logger/index.js:
--------------------------------------------------------------------------------
1 | // @ts-expect-error
2 | export { default } from "webpack/lib/logging/runtime.js";
3 |
--------------------------------------------------------------------------------
/test/fixtures/mime-types-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./file.custom");
4 |
5 | console.log("Hey.");
6 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-3-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./bar.html");
4 |
5 | console.log("Hey.");
6 |
--------------------------------------------------------------------------------
/examples/server/spdy/ssl/server.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/server/spdy/ssl/server.pfx
--------------------------------------------------------------------------------
/test/helpers/custom-http.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const customHTTP = require("node:http");
4 |
5 | module.exports = customHTTP;
6 |
--------------------------------------------------------------------------------
/examples/.assets/geomanist-medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/.assets/geomanist-medium.woff
--------------------------------------------------------------------------------
/examples/server/https/ssl/server.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/server/https/ssl/server.pfx
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /client
2 | !/test/client
3 | coverage
4 | node_modules
5 | CHANGELOG.md
6 | examples/client/trusted-types-overlay/app.js
7 |
--------------------------------------------------------------------------------
/examples/.assets/geomanist-medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/.assets/geomanist-medium.woff2
--------------------------------------------------------------------------------
/examples/general/config-array/pixels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/examples/general/config-array/pixels.png
--------------------------------------------------------------------------------
/test/fixtures/reload-config-2/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // eslint-disable-next-line import/no-unresolved
4 | require("./main.css");
5 |
--------------------------------------------------------------------------------
/scripts/setupTest.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /* global jest */
4 |
5 | process.env.CHOKIDAR_USEPOLLING = true;
6 |
7 | jest.setTimeout(400000);
8 |
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/server.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/webpack-dev-server/main/test/fixtures/https-certificate/server.pfx
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./index.html");
4 | require("./bar.html");
5 |
6 | console.log("Hey.");
7 |
--------------------------------------------------------------------------------
/examples/ipc/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/api/start/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/app/connect/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/app/hono/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/bonjour/boolean/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.innerHTML = "Please check your Zeroconf service.";
6 |
--------------------------------------------------------------------------------
/examples/bonjour/object/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.innerHTML = "Please check your Zeroconf service.";
6 |
--------------------------------------------------------------------------------
/examples/node-false/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/server/spdy/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/.versionrc:
--------------------------------------------------------------------------------
1 | {
2 | "types": [
3 | {"type":"feat","section":"Features"},
4 | {"type":"fix","section":"Bug Fixes"},
5 | {"type":"test", "hidden": true}
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/examples/api/middleware/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/client/logging/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/client/progress/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/compression/true/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/dev-middleware/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/general/proxy-advanced/bypass.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Example: proxy advanced
5 |
6 | Bypassed proxy!
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/headers/array/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/headers/function/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/headers/object/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/host-and-port/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/on-listening/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/server/http2/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/server/https/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/watch-static/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/api/start-callback/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/compression/false/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/general/proxy-simple/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/setup-middlewares/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/web-socket-server/ws/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-default-stats/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | entry: "./foo.js",
7 | };
8 |
--------------------------------------------------------------------------------
/examples/general/proxy-advanced/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/general/proxy-hot-reload/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/examples/web-socket-server/sockjs/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
--------------------------------------------------------------------------------
/test/fixtures/cli/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | stats: "detailed",
6 | context: __dirname,
7 | entry: "./foo.js",
8 | };
9 |
--------------------------------------------------------------------------------
/test/fixtures/cli-empty-entry/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | stats: { orphanModules: true, preset: "detailed" },
6 | entry: {},
7 | };
8 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config/worker.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | postMessage("I'm working before postMessage");
4 |
5 | onmessage = (event) => {
6 | postMessage(`Message sent: ${event.data}`);
7 | };
8 |
--------------------------------------------------------------------------------
/examples/api/stop/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success! Reload the page after 5 seconds.";
7 |
--------------------------------------------------------------------------------
/examples/client/web-socket-url/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/proxy/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success! Now visit /proxy";
7 |
--------------------------------------------------------------------------------
/examples/api/stop-callback/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success! Reload the page after 5 seconds.";
7 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config-dev-server-false/worker.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | postMessage("I'm working before postMessage");
4 |
5 | onmessage = (event) => {
6 | postMessage(`Message sent: ${event.data}`);
7 | };
8 |
--------------------------------------------------------------------------------
/examples/hmr/only/example.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.innerHTML =
6 | "Modify and save /examples/hmr/example.js to update this element without reloading the page.";
7 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | "*": [
5 | "prettier --cache --write --ignore-unknown",
6 | "cspell --cache --no-must-find-files",
7 | ],
8 | "*.js": ["eslint --cache --fix"],
9 | };
10 |
--------------------------------------------------------------------------------
/examples/general/webworker/worker.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /* eslint-env worker */
4 |
5 | globalThis.onmessage = function onMessage(e) {
6 | console.log("[WORKER]", e);
7 | self.postMessage({
8 | hello: 222,
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/examples/hmr/boolean/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./example");
4 |
5 | if (module.hot) {
6 | module.hot.accept((err) => {
7 | if (err) {
8 | console.error("Cannot apply HMR update.", err);
9 | }
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/examples/hmr/boolean/example.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.innerHTML =
6 | "Modify and save /examples/hmr/example.js to update this element without reloading the page.";
7 |
--------------------------------------------------------------------------------
/examples/hmr/only/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./example");
4 |
5 | if (module.hot) {
6 | module.hot.accept((err) => {
7 | if (err) {
8 | console.error("Cannot apply HMR update.", err);
9 | }
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/test/fixtures/cli-entry-as-descriptor/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | entry: {
7 | main: {
8 | import: "./foo.js",
9 | },
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/test/fixtures/cli-single-entry/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { resolve } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | stats: "detailed",
8 | entry: resolve(__dirname, "./foo.js"),
9 | };
10 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const myWorker = new Worker("./worker.js");
4 |
5 | myWorker.onmessage = (event) => {
6 | console.log(`Worker said: ${event.data}`);
7 | };
8 |
9 | myWorker.postMessage("message");
10 |
--------------------------------------------------------------------------------
/examples/client/trusted-types-overlay/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.textContent = "Success!";
7 |
8 | // To display an overlay with an error
9 | (
10 |
--------------------------------------------------------------------------------
/examples/general/config-promise/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // Change the following line and save to see the compilation status
4 |
5 | const target = document.querySelector("#target");
6 |
7 | target.classList.add("pass");
8 | target.innerHTML = "Success!";
9 |
--------------------------------------------------------------------------------
/examples/multi-compiler/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
8 | // This results in an error:
9 | // if(!window) require("test");
10 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | extends: ["@commitlint/config-conventional"],
5 | rules: {
6 | "header-max-length": [0],
7 | "body-max-line-length": [0],
8 | "footer-max-line-length": [0],
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/examples/client/web-socket-url/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.innerHTML =
6 | "Please check the ws request in devtools, it should try to connect to the protocol + server defined in the webSocketURL setting.";
7 |
--------------------------------------------------------------------------------
/test/fixtures/cli-target-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { resolve } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | stats: "detailed",
8 | entry: resolve(__dirname, "./foo.js"),
9 | target: ["web"],
10 | };
11 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config-dev-server-false/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const myWorker = new Worker("./worker-bundle.js");
4 |
5 | myWorker.onmessage = (event) => {
6 | console.log(`Worker said: ${event.data}`);
7 | };
8 |
9 | myWorker.postMessage("message");
10 |
--------------------------------------------------------------------------------
/examples/general/webworker/web.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /* eslint-env browser */
4 |
5 | const worker = new Worker("worker.bundle.js");
6 | worker.onmessage = function onMessage(e) {
7 | console.log("[MAIN]", e);
8 | };
9 | worker.postMessage({
10 | hello: 111,
11 | });
12 |
--------------------------------------------------------------------------------
/test/client/clients/__snapshots__/SockJSClient.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`SockJSClient client should open, receive message, and close 1`] = `
4 | [
5 | "open",
6 | "hello world",
7 | "close",
8 | ]
9 | `;
10 |
--------------------------------------------------------------------------------
/test/fixtures/schema/webpack.config.simple.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | entry: "./foo.js",
7 | output: {
8 | path: "/",
9 | },
10 | infrastructureLogging: {
11 | level: "warn",
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/test/fixtures/static/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | entry: path.resolve(__dirname, "foo.js"),
8 | devServer: {
9 | static: path.resolve(__dirname, "static"),
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | insert_final_newline = false
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-enabled/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | stats: {
6 | colors: true,
7 | },
8 | context: __dirname,
9 | entry: "./foo.js",
10 | infrastructureLogging: {
11 | colors: true,
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/test/fixtures/cli-promise-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { join } = require("path");
4 |
5 | module.exports = () =>
6 | new Promise((resolve) => {
7 | resolve({
8 | mode: "development",
9 | entry: join(__dirname, "foo.js"),
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/test/client/clients/__snapshots__/WebsocketClient.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`WebsocketClient client should open, receive message, and close 1`] = `
4 | [
5 | "open",
6 | "hello world",
7 | "close",
8 | ]
9 | `;
10 |
--------------------------------------------------------------------------------
/test/fixtures/cli-colors-disabled/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | stats: {
6 | colors: false,
7 | },
8 | context: __dirname,
9 | entry: "./foo.js",
10 | infrastructureLogging: {
11 | colors: false,
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/types/lib/getPort.d.ts:
--------------------------------------------------------------------------------
1 | export = getPorts;
2 | /**
3 | * @param {number} basePort base port
4 | * @param {string=} host host
5 | * @returns {Promise} resolved port
6 | */
7 | declare function getPorts(
8 | basePort: number,
9 | host?: string | undefined,
10 | ): Promise;
11 |
--------------------------------------------------------------------------------
/client-src/modules/logger/tapable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @returns {SyncBailHook} mocked sync bail hook
3 | * @constructor
4 | */
5 | function SyncBailHook() {
6 | return {
7 | call() {},
8 | };
9 | }
10 |
11 | /**
12 | * Client stub for tapable SyncBailHook
13 | */
14 | export { SyncBailHook };
15 |
--------------------------------------------------------------------------------
/examples/client/reconnect/false/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML =
7 | "Success!
Now, open the console tab in your browser's devtools. Then, close the server with `Ctrl+C` to disconnect the client.";
8 |
--------------------------------------------------------------------------------
/examples/client/reconnect/number/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML =
7 | "Success!
Now, open the console tab in your browser's devtools. Then, close the server with `Ctrl+C` to disconnect the client.";
8 |
--------------------------------------------------------------------------------
/examples/client/reconnect/true/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML =
7 | "Success!
Now, open the console tab in your browser's devtools. Then, close the server with `Ctrl+C` to disconnect the client.";
8 |
--------------------------------------------------------------------------------
/examples/host-and-port/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | });
11 |
--------------------------------------------------------------------------------
/examples/node-false/README.md:
--------------------------------------------------------------------------------
1 | # Webpack `node` Option
2 |
3 | ```console
4 | npx webpack serve --open
5 | ```
6 |
7 | ## What should happen
8 |
9 | 1. The script should open `http://localhost:8080/` in your default browser.
10 | 2. You should see the text on the page itself change to read `Success!`.
11 |
--------------------------------------------------------------------------------
/test/fixtures/proxy-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | stats: "none",
7 | entry: "./foo.js",
8 | output: {
9 | path: "/",
10 | },
11 | infrastructureLogging: {
12 | level: "warn",
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/examples/general/config-promise/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Promise Config Example
5 |
6 |
7 |
8 | Example: Promise Config
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/client/utils/__snapshots__/sendMessage.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`'sendMessage' function should run self.postMessage 1`] = `
4 | [
5 | {
6 | "data": "bar",
7 | "type": "webpackfoo",
8 | },
9 | "*",
10 | ]
11 | `;
12 |
--------------------------------------------------------------------------------
/test/fixtures/dev-public-path/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { join } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | entry: join(__dirname, "foo.js"),
8 | devServer: {
9 | devMiddleware: {
10 | publicPath: "/foo/bar",
11 | },
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/test/fixtures/static-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | stats: "none",
7 | entry: "./foo.js",
8 | output: {
9 | publicPath: "/",
10 | },
11 | infrastructureLogging: {
12 | level: "warn",
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/examples/node-false/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | node: false,
11 | });
12 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-2-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | stats: "none",
7 | entry: "./foo.js",
8 | output: {
9 | path: "/",
10 | },
11 | infrastructureLogging: {
12 | level: "warn",
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/examples/multi-compiler/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = [
8 | setup({
9 | context: __dirname,
10 | entry: "./app.js",
11 | }),
12 | ];
13 |
--------------------------------------------------------------------------------
/test/helpers/session-subscribe.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = async function sessionSubscribe(session) {
4 | session.on("sessionattached", (attachedSession) => {
5 | sessionSubscribe(attachedSession);
6 | });
7 | session.send("Network.enable");
8 | session.send("Runtime.runIfWaitingForDebugger");
9 | };
10 |
--------------------------------------------------------------------------------
/test/fixtures/simple-config-other/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | stats: "none",
7 | entry: "./foo.js",
8 | output: {
9 | path: "/",
10 | },
11 | node: false,
12 | infrastructureLogging: {
13 | level: "warn",
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/test/e2e/__snapshots__/web-socket-server.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`web socket server should work allow to disable: console messages 1`] = `
4 | [
5 | "Hey.",
6 | ]
7 | `;
8 |
9 | exports[`web socket server should work allow to disable: page errors 1`] = `[]`;
10 |
--------------------------------------------------------------------------------
/test/fixtures/cli-multi-entry/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { resolve } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | stats: "detailed",
8 | context: __dirname,
9 | entry: {
10 | foo: resolve(__dirname, "./foo.js"),
11 | bar: resolve(__dirname, "./bar.js"),
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/test/fixtures/dev-server/client-default-path-config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { resolve } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | stats: "detailed",
8 | entry: resolve(__dirname, "./foo.js"),
9 | devServer: {
10 | webSocketServer: {
11 | type: "ws",
12 | },
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/examples/api/internal-ip-sync/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const WebpackDevServer = require("../../../lib/Server");
4 |
5 | const localIPv4 = WebpackDevServer.internalIPSync("v4");
6 | const localIPv6 = WebpackDevServer.internalIPSync("v6");
7 |
8 | console.log("Local IPv4 address:", localIPv4);
9 | console.log("Local IPv6 address:", localIPv6);
10 |
--------------------------------------------------------------------------------
/examples/hmr/boolean/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | hot: true,
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/hmr/only/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | hot: "only",
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/bonjour/boolean/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | bonjour: true,
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/open-target/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | if (globalThis.location.href.endsWith("example.html#page1")) {
6 | target.classList.add("pass");
7 | target.innerHTML = "Success!";
8 | } else {
9 | target.classList.add("fail");
10 | target.innerHTML = "Houston, we have a problem.";
11 | }
12 |
--------------------------------------------------------------------------------
/examples/watch-static/assets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Static
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/compression/false/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | compress: false,
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/compression/true/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | compress: true,
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/open-target-multiple/app1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | if (globalThis.location.href.endsWith("example1.html")) {
6 | target.classList.add("pass");
7 | target.innerHTML = "Success!";
8 | } else {
9 | target.classList.add("fail");
10 | target.innerHTML = "Houston, we have a problem.";
11 | }
12 |
--------------------------------------------------------------------------------
/examples/open-target-multiple/app2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | if (globalThis.location.href.endsWith("example2.html")) {
6 | target.classList.add("pass");
7 | target.innerHTML = "Success!";
8 | } else {
9 | target.classList.add("fail");
10 | target.innerHTML = "Houston, we have a problem.";
11 | }
12 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-custom/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // 'npm run prepare' must be run for this to work during testing
4 | const CustomClient = require("../../fixtures/custom-client/CustomSockJSClient");
5 |
6 | window.expectedClient = CustomClient;
7 | // eslint-disable-next-line camelcase, no-undef
8 | window.injectedClient = __webpack_dev_server_client__;
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "04:00"
8 | timezone: Europe/Berlin
9 | open-pull-requests-limit: 10
10 | versioning-strategy: lockfile-only
11 | groups:
12 | dependencies:
13 | patterns:
14 | - "*"
15 |
--------------------------------------------------------------------------------
/examples/watch-static/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | static: ["assets", "css"],
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/history-api-fallback/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | historyApiFallback: true,
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/web-socket-server/ws/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | webSocketServer: "ws",
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-sockjs-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // 'npm run prepare' must be run for this to work during testing
4 | const SockJSClient = require("../../../client/clients/SockJSClient").default;
5 |
6 | window.expectedClient = SockJSClient;
7 | // eslint-disable-next-line camelcase, no-undef
8 | window.injectedClient = __webpack_dev_server_client__.default;
9 |
--------------------------------------------------------------------------------
/examples/web-socket-server/sockjs/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | webSocketServer: "sockjs",
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "module": "commonjs",
5 | "lib": ["es2017", "dom"],
6 | "allowJs": true,
7 | "checkJs": true,
8 | "strict": true,
9 | "types": ["node"],
10 | "resolveJsonModule": true,
11 | "allowSyntheticDefaultImports": true
12 | },
13 | "include": ["./bin/**/*", "./lib/**/*"]
14 | }
15 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | name: "Dependency Review"
2 | on: [pull_request]
3 |
4 | permissions:
5 | contents: read
6 |
7 | jobs:
8 | dependency-review:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: "Checkout Repository"
12 | uses: actions/checkout@v4
13 | - name: "Dependency Review"
14 | uses: actions/dependency-review-action@v4
15 |
--------------------------------------------------------------------------------
/examples/client/progress/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | client: {
12 | progress: true,
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | target: "node",
6 | stats: "none",
7 | context: __dirname,
8 | entry: ["./entry1.js", "./entry2.js"],
9 | output: {
10 | path: "/",
11 | libraryTarget: "umd",
12 | },
13 | infrastructureLogging: {
14 | level: "warn",
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-default/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // 'npm run prepare' must be run for this to work during testing
4 | const WebsocketClient =
5 | require("../../../client/clients/WebSocketClient").default;
6 |
7 | window.expectedClient = WebsocketClient;
8 | // eslint-disable-next-line camelcase, no-undef
9 | window.injectedClient = __webpack_dev_server_client__.default;
10 |
--------------------------------------------------------------------------------
/examples/general/config-array/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./style.less");
4 |
5 | const target = document.querySelector("#target");
6 |
7 | target.classList.add("pass");
8 | target.innerHTML = "Success!";
9 |
10 | // This results in a warning:
11 | // if(!window) require("./" + window + "parseable.js");
12 |
13 | // This results in an error:
14 | // if(!window) require("test");
15 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-ws-config/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // 'npm run prepare' must be run for this to work during testing
4 | const WebsocketClient =
5 | require("../../../client/clients/WebSocketClient").default;
6 |
7 | window.expectedClient = WebsocketClient;
8 | // eslint-disable-next-line camelcase, no-undef
9 | window.injectedClient = __webpack_dev_server_client__.default;
10 |
--------------------------------------------------------------------------------
/examples/app/connect/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const connect = require("connect");
6 | const { setup } = require("../../util");
7 |
8 | module.exports = setup({
9 | context: __dirname,
10 | entry: "./app.js",
11 | devServer: {
12 | app: () => connect(),
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/examples/client/reconnect/number/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | client: {
12 | reconnect: 2,
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/examples/client/reconnect/true/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | client: {
12 | reconnect: true,
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/examples/headers/object/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | headers: {
12 | "X-Custom-Header": "yes",
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/examples/api/simple/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/api/start/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/api/stop/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/client/reconnect/false/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | client: {
12 | reconnect: false,
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/test/fixtures/dev-server/client-custom-path-config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { resolve } = require("path");
4 |
5 | module.exports = {
6 | mode: "development",
7 | stats: "detailed",
8 | entry: resolve(__dirname, "./foo.js"),
9 | devServer: {
10 | webSocketServer: {
11 | type: "ws",
12 | options: {
13 | path: "/custom/path",
14 | },
15 | },
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 |
3 | At webpack and webpack/webpack-dev-server repository we follow the [JSFoundation Code of Conduct][1].
4 | Please adhere to the guidelines there and feel free to report any violation of them to the **@webpack/core-team**,
5 | **@webpack/dev-server-team**, or .
6 |
7 | [1]: https://github.com/openjs-foundation/code-and-learn/blob/main/CODE_OF_CONDUCT.md
8 |
--------------------------------------------------------------------------------
/examples/api/middleware/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/client/overlay/create-button.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * @param {string} label
5 | * @param {() => void} onClick
6 | * @returns HTMLButtonElement
7 | */
8 | module.exports = function createButton(label, onClick) {
9 | const button = document.createElement("button");
10 |
11 | button.addEventListener("click", onClick);
12 | button.innerHTML = label;
13 |
14 | return button;
15 | };
16 |
--------------------------------------------------------------------------------
/examples/api/simple/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | target.classList.add("pass");
6 | target.innerHTML = "Success!";
7 |
8 | // This results in a warning:
9 | if (!globalThis) {
10 | // eslint-disable-next-line
11 | require(`./${window}parseable.js`);
12 | }
13 |
14 | // This results in an error:
15 | // if(!window) {
16 | // require("test");
17 | // }
18 |
--------------------------------------------------------------------------------
/examples/api/start-callback/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/api/stop-callback/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | output: {
11 | filename: "bundle.js",
12 | },
13 | stats: {
14 | colors: true,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/general/proxy-hot-reload/proxy-config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**/
4 | module.exports = {
5 | target: "http://jsonplaceholder.typicode.com/",
6 | pathRewrite: {
7 | "^/api": "",
8 | },
9 | };
10 | /**/
11 |
12 | //
13 | // Replace it with following and save the file:
14 | //
15 |
16 | /**
17 | * /
18 | * module.exports = {
19 | * target: 'http://reqres.in/'
20 | * };
21 | * /*
22 | */
23 |
--------------------------------------------------------------------------------
/examples/general/proxy-simple/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | proxy: {
12 | "/api": "http://127.0.0.1:50545",
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/examples/headers/function/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | headers: () => ({ "X-Custom-Header": ["key1=value1", "key2=value2"] }),
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/examples/general/config-promise/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = new Promise((resolve) => {
8 | resolve(
9 | setup({
10 | context: __dirname,
11 | entry: "./app.js",
12 | devServer: {},
13 | }),
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/examples/api/internal-ip/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const WebpackDevServer = require("../../../lib/Server");
4 |
5 | const logInternalIPs = async () => {
6 | const localIPv4 = await WebpackDevServer.internalIP("v4");
7 | const localIPv6 = await WebpackDevServer.internalIP("v6");
8 |
9 | console.log("Local IPv4 address:", localIPv4);
10 | console.log("Local IPv6 address:", localIPv6);
11 | };
12 |
13 | logInternalIPs();
14 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/webpack.multi.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = [
4 | {
5 | mode: "development",
6 | target: "node",
7 | context: __dirname,
8 | stats: "none",
9 | entry: ["./entry1.js", "./entry2.js"],
10 | output: {
11 | path: "/",
12 | libraryTarget: "umd",
13 | },
14 | infrastructureLogging: {
15 | level: "warn",
16 | },
17 | },
18 | ];
19 |
--------------------------------------------------------------------------------
/examples/general/config-promise/README.md:
--------------------------------------------------------------------------------
1 | # General: Promise-Based Webpack Config
2 |
3 | This example demonstrates using `webpack-dev-server` with a `webpack` config that
4 | returns a `Promise`.
5 |
6 | ```console
7 | npx webpack serve --open
8 | ```
9 |
10 | ## What Should Happen
11 |
12 | 1. The script should open `http://localhost:8080/` in your default browser.
13 | 2. You should see the text on the page itself change to read `Success!`.
14 |
--------------------------------------------------------------------------------
/test/fixtures/static/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 | Document
11 |
12 |
13 | Test
14 |
15 |
16 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/webpack.object-entry.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | target: "node",
6 | stats: "none",
7 | context: __dirname,
8 | entry: {
9 | foo: "./entry1.js",
10 | main: ["./entry1.js", "./entry2.js"],
11 | },
12 | output: {
13 | path: "/",
14 | libraryTarget: "umd",
15 | },
16 | infrastructureLogging: {
17 | level: "warn",
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/examples/bonjour/object/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | bonjour: {
12 | name: "webpack-dev-server",
13 | type: "https",
14 | subtype: "webpack",
15 | },
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/examples/dev-middleware/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | devMiddleware: {
12 | index: false,
13 | headers: {
14 | "X-Custom-Header": "yes",
15 | },
16 | },
17 | },
18 | });
19 |
--------------------------------------------------------------------------------
/examples/server/http2/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const connect = require("connect");
6 | const { setup } = require("../../util");
7 |
8 | module.exports = setup({
9 | context: __dirname,
10 | entry: "./app.js",
11 | devServer: {
12 | server: "http2",
13 | // Only `connect` supports `http2`
14 | app: () => connect(),
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/test/fixtures/watch-files-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | devtool: false,
8 | context: __dirname,
9 | stats: "none",
10 | entry: "./foo.js",
11 | output: {
12 | publicPath: "/",
13 | },
14 | infrastructureLogging: {
15 | level: "warn",
16 | },
17 | plugins: [new HTMLGeneratorPlugin()],
18 | };
19 |
--------------------------------------------------------------------------------
/test/helpers/conditional-test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /* global test */
4 |
5 | const isWindows = process.platform === "win32";
6 |
7 | /**
8 | * @param {string} reason reason
9 | * @returns {boolean} true when it is windows, otherwise false
10 | */
11 | function skipTestOnWindows(reason) {
12 | if (isWindows) {
13 | test.skip(reason, () => {});
14 | }
15 |
16 | return isWindows;
17 | }
18 |
19 | module.exports.skipTestOnWindows = skipTestOnWindows;
20 |
--------------------------------------------------------------------------------
/examples/client/web-socket-url/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | host: "0.0.0.0",
12 | client: {
13 | webSocketURL: "ws://localhost:8080",
14 | },
15 | allowedHosts: "all",
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/examples/general/universal-config/README.md:
--------------------------------------------------------------------------------
1 | # General: Webpack Universal Config
2 |
3 | This example demonstrates using a `webpack` config containing a `target: web` config and `target:node` config.
4 |
5 | ```console
6 | npx webpack serve --open
7 | ```
8 |
9 | ## What Should Happen
10 |
11 | 1. The script should open `http://localhost:8080/` in your default browser.
12 | 2. You should see the text on the page itself change to read `[client.js, server.js]: Success!`.
13 |
--------------------------------------------------------------------------------
/test/helpers/ExitOnDonePlugin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = class ExitOnDonePlugin {
4 | apply(compiler) {
5 | compiler.hooks.afterDone.tap("webpack-dev-server", (stats) => {
6 | let exitCode = 0;
7 |
8 | if (stats.hasErrors()) {
9 | exitCode = 1;
10 | }
11 |
12 | setImmediate(() => {
13 | // eslint-disable-next-line n/no-process-exit
14 | process.exit(exitCode);
15 | });
16 | });
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/examples/on-listening/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | onListening: (devServer) => {
12 | const { port } = devServer.server.address();
13 | console.log("Listening on port:", port);
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/examples/api/middleware/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = webpackConfig.devServer;
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | server.startCallback(() => {
12 | console.log("Starting server on http://localhost:8080");
13 | });
14 |
--------------------------------------------------------------------------------
/test/fixtures/overlay-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | infrastructureLogging: {
14 | level: "info",
15 | stream: {
16 | write: () => {},
17 | },
18 | },
19 | plugins: [new HTMLGeneratorPlugin()],
20 | };
21 |
--------------------------------------------------------------------------------
/examples/api/simple/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = { ...webpackConfig.devServer, open: true };
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | server.startCallback(() => {
12 | console.log("Starting server on http://localhost:8080");
13 | });
14 |
--------------------------------------------------------------------------------
/examples/server/http2/README.md:
--------------------------------------------------------------------------------
1 | # HTTP2 server
2 |
3 | **webpack.config.js**
4 |
5 | ```js
6 | const connect = require("connect");
7 |
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | server: {
12 | server: "http2",
13 | app: () => connect(),
14 | },
15 | },
16 | };
17 | ```
18 |
19 | ## What Should Happen
20 |
21 | 1. The script should open `https://localhost:8080/` in your default browser.
22 | 2. You should see the text on the page itself change to read `Success!`.
23 |
--------------------------------------------------------------------------------
/types/lib/servers/BaseServer.d.ts:
--------------------------------------------------------------------------------
1 | export = BaseServer;
2 | declare class BaseServer {
3 | /**
4 | * @param {import("../Server")} server server
5 | */
6 | constructor(server: import("../Server"));
7 | /** @type {import("../Server")} */
8 | server: import("../Server");
9 | /** @type {ClientConnection[]} */
10 | clients: ClientConnection[];
11 | }
12 | declare namespace BaseServer {
13 | export { ClientConnection };
14 | }
15 | type ClientConnection = import("../Server").ClientConnection;
16 |
--------------------------------------------------------------------------------
/types/lib/servers/SockJSServer.d.ts:
--------------------------------------------------------------------------------
1 | export = SockJSServer;
2 | declare class SockJSServer extends BaseServer {
3 | implementation: sockjs.Server;
4 | }
5 | declare namespace SockJSServer {
6 | export { WebSocketServerConfiguration, ClientConnection };
7 | }
8 | import BaseServer = require("./BaseServer");
9 | import sockjs = require("sockjs");
10 | type WebSocketServerConfiguration =
11 | import("../Server").WebSocketServerConfiguration;
12 | type ClientConnection = import("../Server").ClientConnection;
13 |
--------------------------------------------------------------------------------
/test/fixtures/client-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | devtool: false,
7 | mode: "development",
8 | context: __dirname,
9 | stats: "none",
10 | entry: "./foo.js",
11 | output: {
12 | path: "/",
13 | },
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/test/fixtures/simple-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | node: false,
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-custom/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | node: false,
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/types/bin/webpack-dev-server.d.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | export type CliOption = {
3 | /**
4 | * display name
5 | */
6 | name: string;
7 | /**
8 | * npm package name
9 | */
10 | package: string;
11 | /**
12 | * name of the executable file
13 | */
14 | binName: string;
15 | /**
16 | * currently installed?
17 | */
18 | installed: boolean;
19 | /**
20 | * homepage
21 | */
22 | url: string;
23 | /**
24 | * preprocessor
25 | */
26 | preprocess: () => void;
27 | };
28 |
--------------------------------------------------------------------------------
/examples/api/start-callback/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = { ...webpackConfig.devServer, open: true };
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | server.startCallback(() => {
12 | console.log("Successfully started server on http://localhost:8080");
13 | });
14 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-default/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | node: false,
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-ws-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | node: false,
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/examples/headers/array/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | headers: [
12 | {
13 | key: "X-Foo",
14 | value: "value1",
15 | },
16 | {
17 | key: "X-Bar",
18 | value: "value2",
19 | },
20 | ],
21 | },
22 | });
23 |
--------------------------------------------------------------------------------
/test/fixtures/provide-plugin-sockjs-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | node: false,
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/examples/general/config-array/README.md:
--------------------------------------------------------------------------------
1 | # General: Webpack Config Array
2 |
3 | This example demonstrates using a `webpack` config containing an array of configs.
4 |
5 | ```console
6 | npx webpack serve --open
7 | ```
8 |
9 | ## What Should Happen
10 |
11 | 1. The script should open `http://localhost:8080/` in your default browser.
12 | 2. You should see the text on the page itself change to read `Success!`.
13 | 3. Navigate to `http://localhost:8080/bundle2.js`
14 | 4. The browser should display a minified JavaScript bundle.
15 |
--------------------------------------------------------------------------------
/lib/servers/BaseServer.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /** @typedef {import("../Server").ClientConnection} ClientConnection */
4 |
5 | // base class that users should extend if they are making their own
6 | // server implementation
7 | module.exports = class BaseServer {
8 | /**
9 | * @param {import("../Server")} server server
10 | */
11 | constructor(server) {
12 | /** @type {import("../Server")} */
13 | this.server = server;
14 |
15 | /** @type {ClientConnection[]} */
16 | this.clients = [];
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/examples/api/start/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = { ...webpackConfig.devServer, open: true };
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | const runServer = async () => {
12 | console.log("Starting server...");
13 | await server.start();
14 | };
15 |
16 | runServer();
17 |
--------------------------------------------------------------------------------
/examples/default/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | require("./style.less");
4 |
5 | const target = document.querySelector("#target");
6 |
7 | target.classList.add("pass");
8 | target.innerHTML = "Success!";
9 |
10 | const img = document.createElement("img");
11 | img.src = "/svg.svg";
12 | img.style = "width: 200px;";
13 |
14 | document.body.appendChild(img);
15 |
16 | // This results in a warning:
17 | // if(!window) require("./" + window + "parseable.js");
18 |
19 | // This results in an error:
20 | // if(!window) require("test");
21 |
--------------------------------------------------------------------------------
/examples/general/webworker/README.md:
--------------------------------------------------------------------------------
1 | # General: WebWorker
2 |
3 | This example demonstrates using a WebWorker within an app run by `webpack-dev-server`.
4 |
5 | ```console
6 | npx webpack serve
7 | ```
8 |
9 | ## What should happen
10 |
11 | 1. The main thread sends a message to the Worker.
12 | 2. The worker outputs the message in the console.
13 | 3. The worker sends a message back to the main thread.
14 | 4. The main thread posts the message in the console.
15 |
16 | No error, warning or other log traces should be in the console.
17 |
--------------------------------------------------------------------------------
/examples/general/universal-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { setup } = require("../../util");
4 |
5 | module.exports = [
6 | setup({
7 | mode: "development",
8 | entry: "./client.js",
9 | output: {
10 | filename: "client.js",
11 | },
12 | context: __dirname,
13 | }),
14 | {
15 | mode: "development",
16 | target: "node",
17 | entry: "./server.js",
18 | output: {
19 | filename: "server.js",
20 | },
21 | context: __dirname,
22 | node: false,
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/tsconfig.client.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "lib": ["es5", "dom", "webworker", "es2022.error"],
5 | "module": "nodenext",
6 | "moduleResolution": "nodenext",
7 | "allowJs": true,
8 | "checkJs": true,
9 | "noEmit": true,
10 | "strict": true,
11 | "types": ["@types/trusted-types", "webpack/module"],
12 | "skipDefaultLibCheck": true,
13 | "esModuleInterop": true
14 | },
15 | "include": ["./client-src/**/*"],
16 | "exclude": ["./client-src/webpack.config.js"]
17 | }
18 |
--------------------------------------------------------------------------------
/examples/app/hono/README.md:
--------------------------------------------------------------------------------
1 | # `app` Option
2 |
3 | Serve using [`hono`](https://github.com/honojs/hono) as an application.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | const connect = require("connect");
9 |
10 | module.exports = {
11 | // ...
12 | devServer: {
13 | server: {
14 | app: () => connect(),
15 | },
16 | },
17 | };
18 | ```
19 |
20 | ## What Should Happen
21 |
22 | 1. The script should open `https://localhost:8080/` in your default browser.
23 | 2. You should see the text on the page itself change to read `Success!`.
24 |
--------------------------------------------------------------------------------
/examples/open-target/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HtmlWebpackPlugin = require("html-webpack-plugin");
4 | // our setup function adds behind-the-scenes bits to the config that all of our
5 | // examples need
6 | const { setup } = require("../util");
7 |
8 | module.exports = setup({
9 | context: __dirname,
10 | entry: "./app.js",
11 | plugins: [
12 | new HtmlWebpackPlugin({
13 | filename: "example.html",
14 | template: "../.assets/layout.html",
15 | title: "Open Target / Example",
16 | }),
17 | ],
18 | });
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | npm-debug.log
4 |
5 | .idea
6 |
7 | client
8 | !/examples/client
9 | !/test/client
10 | coverage
11 | node_modules
12 | .vscode
13 | yarn.lock
14 | yarn-error.log
15 |
16 | .eslintcache
17 | .cspellcache
18 |
19 | test/fixtures/static-config/public/assets/non-exist.txt
20 | test/fixtures/watch-files-config/public/assets/non-exist.txt
21 | test/fixtures/reload-config/main.css
22 | test/fixtures/reload-config-2/main.css
23 | test/fixtures/worker-config-dev-server-false/public
24 | !/test/fixtures/static-config/public/node_modules
25 |
--------------------------------------------------------------------------------
/examples/general/webworker/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = [
8 | setup({
9 | devtool: "source-map",
10 | target: "web",
11 | entry: "./web.js",
12 | }),
13 | {
14 | devtool: "source-map",
15 | target: "webworker",
16 | entry: "./worker.js",
17 | output: {
18 | filename: "worker.bundle.js",
19 | path: __dirname,
20 | },
21 | },
22 | ];
23 |
--------------------------------------------------------------------------------
/examples/multi-compiler/README.md:
--------------------------------------------------------------------------------
1 | # Multi Compiler
2 |
3 | `webpack-dev-server` should be able to compile multiple webpack configs.
4 |
5 | ```shell
6 | npx webpack serve --open
7 | ```
8 |
9 | ## What Should Happen
10 |
11 | 1. The script should open `http://localhost:8080/` in your default browser.
12 | 2. You should see the text on the page itself change to read `Success!`.
13 | 3. In `app.js` write code containing a syntax error and save the file.
14 | 4. The page should now refresh and show a full screen error overlay, displaying
15 | the syntax error.
16 |
--------------------------------------------------------------------------------
/examples/app/connect/README.md:
--------------------------------------------------------------------------------
1 | # `app` Option
2 |
3 | Serve using [`connect`](https://github.com/senchalabs/connect) as an application.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | const connect = require("connect");
9 |
10 | module.exports = {
11 | // ...
12 | devServer: {
13 | server: {
14 | app: () => connect(),
15 | },
16 | },
17 | };
18 | ```
19 |
20 | ## What Should Happen
21 |
22 | 1. The script should open `https://localhost:8080/` in your default browser.
23 | 2. You should see the text on the page itself change to read `Success!`.
24 |
--------------------------------------------------------------------------------
/examples/bonjour/boolean/README.md:
--------------------------------------------------------------------------------
1 | # Bonjour (ZeroConf)
2 |
3 | The Bonjour capability broadcasts server information via ZeroConf when the Server
4 | is started.
5 |
6 | ## boolean
7 |
8 | **webpack.config.js**
9 |
10 | ```js
11 | module.exports = {
12 | // ...
13 | devServer: {
14 | bonjour: true,
15 | },
16 | };
17 | ```
18 |
19 | Usage via CLI:
20 |
21 | ```console
22 | npx webpack serve --bonjour
23 | ```
24 |
25 | ## What Should Happen
26 |
27 | A Zeroconf broadcast should occur, containing data with a type of `http` and a
28 | subtype of `webpack`.
29 |
--------------------------------------------------------------------------------
/test/fixtures/overlay-config/trusted-types.webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/trusted-types-html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | trustedTypes: { policyName: "webpack" },
13 | },
14 | infrastructureLogging: {
15 | level: "info",
16 | stream: {
17 | write: () => {},
18 | },
19 | },
20 | plugins: [new HTMLGeneratorPlugin()],
21 | };
22 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-3-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const moduleRuleForHTML = {
4 | test: /\.html$/,
5 | type: "asset/resource",
6 | generator: {
7 | filename: "index.html",
8 | },
9 | };
10 |
11 | module.exports = {
12 | mode: "development",
13 | context: __dirname,
14 | stats: "none",
15 | entry: "./foo.js",
16 | output: {
17 | path: "/",
18 | },
19 | module: {
20 | rules: [
21 | {
22 | ...moduleRuleForHTML,
23 | },
24 | ],
25 | },
26 | infrastructureLogging: {
27 | level: "warn",
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/test/fixtures/historyapifallback-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const moduleRuleForHTML = {
4 | test: /\.html$/,
5 | type: "asset/resource",
6 | generator: {
7 | filename: "[name][ext]",
8 | },
9 | };
10 |
11 | module.exports = {
12 | mode: "development",
13 | context: __dirname,
14 | stats: "none",
15 | entry: "./foo.js",
16 | output: {
17 | path: "/",
18 | },
19 | module: {
20 | rules: [
21 | {
22 | ...moduleRuleForHTML,
23 | },
24 | ],
25 | },
26 | infrastructureLogging: {
27 | level: "warn",
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/test/cli/compress-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-compress"];
5 |
6 | describe('"compress" CLI option', () => {
7 | it('should work using "--compress"', async () => {
8 | const { exitCode } = await testBin(["--port", port, "--compress"]);
9 |
10 | expect(exitCode).toBe(0);
11 | });
12 |
13 | it('should work using "--no-compress"', async () => {
14 | const { exitCode } = await testBin(["--port", port, "--no-compress"]);
15 |
16 | expect(exitCode).toBe(0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/test/fixtures/entry-as-function/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | mode: "development",
5 | context: __dirname,
6 | entry: () => "./foo.js",
7 | plugins: [
8 | {
9 | apply(compiler) {
10 | compiler.hooks.done.tap("webpack-dev-server", (stats) => {
11 | let exitCode = 0;
12 | if (stats.hasErrors()) {
13 | exitCode = 1;
14 | }
15 | setTimeout(() => process.exit(exitCode));
16 | });
17 | },
18 | },
19 | ],
20 | infrastructureLogging: {
21 | level: "warn",
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/test/fixtures/multi-compiler-one-configuration/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = [
6 | {
7 | target: "web",
8 | mode: "development",
9 | context: __dirname,
10 | stats: "none",
11 | entry: "./foo.js",
12 | output: {
13 | path: "/",
14 | },
15 | node: false,
16 | infrastructureLogging: {
17 | level: "info",
18 | stream: {
19 | write: () => {},
20 | },
21 | },
22 | plugins: [new HTMLGeneratorPlugin()],
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/client-src/utils/sendMessage.js:
--------------------------------------------------------------------------------
1 | /* global WorkerGlobalScope */
2 |
3 | /** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */
4 |
5 | // Send messages to the outside, so plugins can consume it.
6 | /**
7 | * @param {string} type type
8 | * @param {EXPECTED_ANY=} data data
9 | */
10 | function sendMsg(type, data) {
11 | if (
12 | typeof self !== "undefined" &&
13 | (typeof WorkerGlobalScope === "undefined" ||
14 | !(self instanceof WorkerGlobalScope))
15 | ) {
16 | self.postMessage({ type: `webpack${type}`, data }, "*");
17 | }
18 | }
19 |
20 | export default sendMsg;
21 |
--------------------------------------------------------------------------------
/examples/server/spdy/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | server: {
12 | type: "spdy",
13 | options: {
14 | key: "./ssl/server.key",
15 | pfx: "./ssl/server.pfx",
16 | cert: "./ssl/server.crt",
17 | ca: "./ssl/ca.pem",
18 | passphrase: "webpack-dev-server",
19 | },
20 | },
21 | },
22 | });
23 |
--------------------------------------------------------------------------------
/examples/server/https/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | server: {
12 | type: "https",
13 | options: {
14 | key: "./ssl/server.key",
15 | pfx: "./ssl/server.pfx",
16 | cert: "./ssl/server.crt",
17 | ca: "./ssl/ca.pem",
18 | passphrase: "webpack-dev-server",
19 | },
20 | },
21 | },
22 | });
23 |
--------------------------------------------------------------------------------
/test/client/utils/sendMessage.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @jest-environment jsdom
3 | */
4 |
5 | "use strict";
6 |
7 | const sendMessage = require("../../../client-src/utils/sendMessage").default;
8 |
9 | describe("'sendMessage' function", () => {
10 | afterEach(() => {
11 | jest.resetAllMocks();
12 | });
13 |
14 | it("should run self.postMessage", () => {
15 | jest.spyOn(globalThis, "postMessage").mockImplementation();
16 |
17 | sendMessage("foo", "bar");
18 |
19 | expect(self.postMessage).toHaveBeenCalled();
20 | expect(self.postMessage.mock.calls[0]).toMatchSnapshot();
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/test/fixtures/mime-types-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const moduleRuleForCustom = {
4 | test: /\.custom$/,
5 | type: "asset/resource",
6 | generator: {
7 | filename: "[name][ext]",
8 | },
9 | };
10 |
11 | module.exports = {
12 | mode: "development",
13 | context: __dirname,
14 | stats: "none",
15 | entry: "./foo.js",
16 | output: {
17 | path: "/",
18 | },
19 | node: false,
20 | infrastructureLogging: {
21 | level: "warn",
22 | },
23 | module: {
24 | rules: [
25 | {
26 | ...moduleRuleForCustom,
27 | },
28 | ],
29 | },
30 | };
31 |
--------------------------------------------------------------------------------
/test/cli/liveReload-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-live-reload"];
5 |
6 | describe('"liveReload" CLI option', () => {
7 | it('should work using "--live-reload"', async () => {
8 | const { exitCode } = await testBin(["--port", port, "--live-reload"]);
9 |
10 | expect(exitCode).toBe(0);
11 | });
12 |
13 | it('should work using "--no-live-reload"', async () => {
14 | const { exitCode } = await testBin(["--port", port, "--no-live-reload"]);
15 |
16 | expect(exitCode).toBe(0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/test/client/utils/__snapshots__/log.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`'log' function should set log level via setLogLevel 1`] = `
4 | [
5 | [
6 | {
7 | "level": "none",
8 | },
9 | ],
10 | [
11 | {
12 | "level": "error",
13 | },
14 | ],
15 | [
16 | {
17 | "level": "warn",
18 | },
19 | ],
20 | [
21 | {
22 | "level": "info",
23 | },
24 | ],
25 | [
26 | {
27 | "level": "log",
28 | },
29 | ],
30 | [
31 | {
32 | "level": "verbose",
33 | },
34 | ],
35 | ]
36 | `;
37 |
--------------------------------------------------------------------------------
/test/client/utils/__snapshots__/reloadApp.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`'reloadApp' function should run hot 1`] = `"App hot update..."`;
4 |
5 | exports[`'reloadApp' function should run hot 2`] = `"webpackHotUpdate"`;
6 |
7 | exports[`'reloadApp' function should run hot 3`] = `
8 | [
9 | "webpackHotUpdatehash",
10 | "*",
11 | ]
12 | `;
13 |
14 | exports[`'reloadApp' function should run liveReload when protocol is about: 1`] = `"App updated. Reloading..."`;
15 |
16 | exports[`'reloadApp' function should run liveReload when protocol is http: 1`] = `"App updated. Reloading..."`;
17 |
--------------------------------------------------------------------------------
/types/lib/servers/WebsocketServer.d.ts:
--------------------------------------------------------------------------------
1 | export = WebsocketServer;
2 | declare class WebsocketServer extends BaseServer {
3 | static heartbeatInterval: number;
4 | implementation: WebSocket.Server<
5 | typeof WebSocket,
6 | typeof import("http").IncomingMessage
7 | >;
8 | }
9 | declare namespace WebsocketServer {
10 | export { WebSocketServerConfiguration, ClientConnection };
11 | }
12 | import BaseServer = require("./BaseServer");
13 | import WebSocket = require("ws");
14 | type WebSocketServerConfiguration =
15 | import("../Server").WebSocketServerConfiguration;
16 | type ClientConnection = import("../Server").ClientConnection;
17 |
--------------------------------------------------------------------------------
/test/cli/__snapshots__/ipc-option.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`"ipc" CLI option should work using "--ipc": stderr 1`] = `
4 | " [webpack-dev-server] Project is running at: "/webpack-dev-server.sock"
5 | [webpack-dev-server] Content not from webpack is served from '/public' directory"
6 | `;
7 |
8 | exports[`"ipc" CLI option should work using "--ipc=": stderr 1`] = `
9 | " [webpack-dev-server] Project is running at: "/webpack-dev-server.cli.sock"
10 | [webpack-dev-server] Content not from webpack is served from '/public' directory"
11 | `;
12 |
--------------------------------------------------------------------------------
/test/fixtures/cli-universal-compiler-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = [
4 | {
5 | name: "client",
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./client.js",
10 | output: {
11 | path: "/",
12 | filename: "client.js",
13 | },
14 | },
15 | {
16 | name: "server",
17 | mode: "development",
18 | context: __dirname,
19 | target: "node",
20 | stats: "none",
21 | entry: "./server.js",
22 | output: {
23 | path: "/",
24 | filename: "server.js",
25 | },
26 | dependencies: ["client"],
27 | },
28 | ];
29 |
--------------------------------------------------------------------------------
/client-src/utils/log.js:
--------------------------------------------------------------------------------
1 | import logger from "../modules/logger/index.js";
2 |
3 | const name = "webpack-dev-server";
4 | // default level is set on the client side, so it does not need
5 | // to be set by the CLI or API
6 | const defaultLevel = "info";
7 |
8 | // options new options, merge with old options
9 | /**
10 | * @param {false | true | "none" | "error" | "warn" | "info" | "log" | "verbose"} level level
11 | * @returns {void}
12 | */
13 | function setLogLevel(level) {
14 | logger.configureDefaultLogger({ level });
15 | }
16 |
17 | setLogLevel(defaultLevel);
18 |
19 | const log = logger.getLogger(name);
20 |
21 | export { log, setLogLevel };
22 |
--------------------------------------------------------------------------------
/examples/api/internal-ip-sync/README.md:
--------------------------------------------------------------------------------
1 | # internalIPSync(family: "v4" | "v6")
2 |
3 | Returns the internal IP address synchronously.
4 |
5 | ```js
6 | const WebpackDevServer = require("webpack-dev-server");
7 |
8 | const localIPv4 = WebpackDevServer.internalIPSync("v4");
9 | const localIPv6 = WebpackDevServer.internalIPSync("v6");
10 |
11 | console.log("Local IPv4 address:", localIPv4);
12 | console.log("Local IPv6 address:", localIPv6);
13 | ```
14 |
15 | Use the following command to run this example:
16 |
17 | ```console
18 | node app.js
19 | ```
20 |
21 | ## What Should Happen
22 |
23 | - The script should log your local IPv4 and IPv6 address.
24 |
--------------------------------------------------------------------------------
/test/fixtures/module-federation-config/webpack.plugin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const ModuleFederationPlugin =
4 | require("webpack").container.ModuleFederationPlugin;
5 |
6 | module.exports = {
7 | mode: "development",
8 | target: "node",
9 | stats: "none",
10 | context: __dirname,
11 | entry: ["./entry1.js"],
12 | plugins: [
13 | new ModuleFederationPlugin({
14 | name: "app1",
15 | library: { type: "var", name: "app1" },
16 | filename: "remoteEntry.js",
17 | exposes: {
18 | "./entry1": "./entry1",
19 | },
20 | }),
21 | ],
22 | infrastructureLogging: {
23 | level: "warn",
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/examples/.assets/icon-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/test/fixtures/reload-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | entry: "./foo.js",
9 | stats: "none",
10 | output: {
11 | path: "/",
12 | },
13 | module: {
14 | rules: [
15 | {
16 | test: /\.css$/,
17 | use: [{ loader: "style-loader" }, { loader: "css-loader" }],
18 | },
19 | ],
20 | },
21 | infrastructureLogging: {
22 | level: "info",
23 | stream: {
24 | write: () => {},
25 | },
26 | },
27 | plugins: [new HTMLGeneratorPlugin()],
28 | };
29 |
--------------------------------------------------------------------------------
/examples/web-socket-server/ws/README.md:
--------------------------------------------------------------------------------
1 | # web-socket-server (ws)
2 |
3 | To create a custom server implementation.
4 |
5 | ## ws
6 |
7 | This mode uses [ws](https://github.com/websockets/ws) as a server.
8 |
9 | **webpack.config.js**
10 |
11 | ```js
12 | module.exports = {
13 | // ...
14 | devServer: {
15 | webSocketServer: "ws",
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```console
23 | npx webpack serve --web-socket-server-type ws --open
24 | ```
25 |
26 | ### What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. You should see the text on the page itself change to read `Success!`.
30 |
--------------------------------------------------------------------------------
/examples/api/stop-callback/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = { ...webpackConfig.devServer, open: true };
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | server.startCallback(() => {
12 | console.log("Successfully started server on http://localhost:8080");
13 | });
14 |
15 | const stopServer = () =>
16 | server.stopCallback(() => {
17 | console.log("Server stopped.");
18 | });
19 |
20 | setTimeout(stopServer, 5000);
21 |
--------------------------------------------------------------------------------
/examples/api/middleware/README.md:
--------------------------------------------------------------------------------
1 | # API: Custom Middleware
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also
4 | choose to start a server via the API. This example demonstrates using one of the
5 | few custom middleware options; `before`.
6 |
7 | ```console
8 | node server.js
9 | ```
10 |
11 | ## What Should Happen
12 |
13 | 1. Open `http://localhost:8080/` in your preferred browser.
14 | 2. You should see the text on the page itself change to read `Success!`.
15 | 3. In the console/terminal, you should see the following for each refresh in
16 | the browser:
17 |
18 | ```
19 | Using middleware for /
20 | Using middleware for /bundle.js
21 | ```
22 |
--------------------------------------------------------------------------------
/examples/api/stop/server.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Webpack = require("webpack");
4 | const WebpackDevServer = require("../../../lib/Server");
5 | const webpackConfig = require("./webpack.config");
6 |
7 | const compiler = Webpack(webpackConfig);
8 | const devServerOptions = { ...webpackConfig.devServer, open: true };
9 | const server = new WebpackDevServer(devServerOptions, compiler);
10 |
11 | const runServer = async () => {
12 | console.log("Starting server...");
13 | await server.start();
14 | };
15 |
16 | const stopServer = async () => {
17 | console.log("Stopping server...");
18 | await server.stop();
19 | };
20 |
21 | runServer();
22 |
23 | setTimeout(stopServer, 5000);
24 |
--------------------------------------------------------------------------------
/test/client/utils/__snapshots__/getCurrentScriptSource.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`'getCurrentScriptSource' function should fail when 'document.currentScript' doesn't exist and no 'script' tags 1`] = `[Error: [webpack-dev-server] Failed to get current script source.]`;
4 |
5 | exports[`'getCurrentScriptSource' function should fail when 'document.scripts' doesn't exist and no scripts 1`] = `[Error: [webpack-dev-server] Failed to get current script source.]`;
6 |
7 | exports[`'getCurrentScriptSource' function should fail when no scripts with the 'scr' attribute 1`] = `[Error: [webpack-dev-server] Failed to get current script source.]`;
8 |
--------------------------------------------------------------------------------
/test/fixtures/reload-config-2/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = {
6 | mode: "development",
7 | context: __dirname,
8 | stats: "none",
9 | entry: "./foo.js",
10 | output: {
11 | path: "/",
12 | },
13 | module: {
14 | rules: [
15 | {
16 | test: /\.css$/,
17 | use: [{ loader: "style-loader" }, { loader: "css-loader" }],
18 | },
19 | ],
20 | },
21 | node: false,
22 | infrastructureLogging: {
23 | level: "info",
24 | stream: {
25 | write: () => {},
26 | },
27 | },
28 | plugins: [new HTMLGeneratorPlugin()],
29 | };
30 |
--------------------------------------------------------------------------------
/examples/default/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | const moduleRuleForPNG = {
8 | test: /\.png$/,
9 | type: "asset/resource",
10 | generator: {
11 | filename: "images/[hash][ext][query]",
12 | },
13 | };
14 |
15 | module.exports = setup({
16 | context: __dirname,
17 | entry: "./app.js",
18 | module: {
19 | rules: [
20 | {
21 | test: /\.less$/,
22 | use: ["style-loader", "css-loader", "less-loader"],
23 | },
24 | {
25 | ...moduleRuleForPNG,
26 | },
27 | ],
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/examples/general/proxy-advanced/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | proxy: {
12 | "/api": {
13 | target: "http://jsonplaceholder.typicode.com/",
14 | changeOrigin: true,
15 | pathRewrite: {
16 | "^/api": "",
17 | },
18 | bypass(req) {
19 | if (req.url === "/api/nope") {
20 | return "/bypass.html";
21 | }
22 | },
23 | },
24 | },
25 | },
26 | });
27 |
--------------------------------------------------------------------------------
/examples/web-socket-server/sockjs/README.md:
--------------------------------------------------------------------------------
1 | # web-socket-server (sockjs)
2 |
3 | To create a custom server implementation.
4 |
5 | ## sockjs
6 |
7 | This mode uses [SockJS-node](https://github.com/sockjs/sockjs-node) as a server.
8 |
9 | **webpack.config.js**
10 |
11 | ```js
12 | module.exports = {
13 | // ...
14 | devServer: {
15 | webSocketServer: "sockjs",
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```console
23 | npx webpack serve --web-socket-server-type sockjs --open
24 | ```
25 |
26 | ### What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. You should see the text on the page itself change to read `Success!`.
30 |
--------------------------------------------------------------------------------
/examples/api/internal-ip/README.md:
--------------------------------------------------------------------------------
1 | # internalIP(family: "v4" | "v6")
2 |
3 | Returns the internal IP address asynchronously.
4 |
5 | ```js
6 | const WebpackDevServer = require("webpack-dev-server");
7 |
8 | const logInternalIPs = async () => {
9 | const localIPv4 = await WebpackDevServer.internalIP("v4");
10 | const localIPv6 = await WebpackDevServer.internalIP("v6");
11 |
12 | console.log("Local IPv4 address:", localIPv4);
13 | console.log("Local IPv6 address:", localIPv6);
14 | };
15 |
16 | logInternalIPs();
17 | ```
18 |
19 | Use the following command to run this example:
20 |
21 | ```console
22 | node app.js
23 | ```
24 |
25 | ## What Should Happen
26 |
27 | - The script should log your local IPv4 and IPv6 address.
28 |
--------------------------------------------------------------------------------
/examples/headers/object/README.md:
--------------------------------------------------------------------------------
1 | # headers option as an object
2 |
3 | Adds headers to all responses.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | headers: {
12 | "X-Custom-Header": "yes",
13 | },
14 | },
15 | };
16 | ```
17 |
18 | To run this example use the following command:
19 |
20 | ```console
21 | npx webpack serve --open
22 | ```
23 |
24 | ## What should happen
25 |
26 | 1. The script should open `http://localhost:8080/`.
27 | 2. You should see the text on the page itself change to read `Success!`.
28 | 3. Open the console in your browser's devtools and select the _Network_ tab.
29 | 4. Find `main.js`. The response headers should contain `X-Custom-Header: yes`.
30 |
--------------------------------------------------------------------------------
/examples/api/simple/README.md:
--------------------------------------------------------------------------------
1 | # API: Simple Server
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also
4 | choose to start a server via the API. This example starts a simple server setup.
5 |
6 | ```console
7 | node server.js
8 | ```
9 |
10 | ## What should happen
11 |
12 | 1. Open `http://localhost:8080/` in your preferred browser.
13 | 2. You should see the text on the page itself change to read `Success!`.
14 | 3. In `app.js`, uncomment the code that results in an error and save. This error
15 | should be visible in the console/terminal and in browser devtools.
16 | 4. In `app.js`, uncomment the code that results in a warning. This warning should
17 | be visible in the console/terminal and in browser devtools.
18 |
--------------------------------------------------------------------------------
/test/cli/port-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { normalizeStderr, testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-port-option"];
5 |
6 | describe('"port" CLI option', () => {
7 | it('should work using "--port "', async () => {
8 | const { exitCode, stderr } = await testBin(["--port", port]);
9 |
10 | expect(exitCode).toBe(0);
11 | expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr");
12 | });
13 |
14 | it('should work using "--port auto"', async () => {
15 | const { exitCode, stderr } = await testBin(["--port", "auto"]);
16 |
17 | expect(exitCode).toBe(0);
18 | expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot("stderr");
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/test/helpers/snapshotResolver.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("node:path");
4 | const webpack = require("webpack");
5 |
6 | const [webpackVersion] = webpack.version;
7 | const snapshotExtension = `.snap.webpack${webpackVersion}`;
8 |
9 | module.exports = {
10 | resolveSnapshotPath: (testPath) =>
11 | path.join(
12 | path.dirname(testPath),
13 | "__snapshots__",
14 | `${path.basename(testPath)}${snapshotExtension}`,
15 | ),
16 | resolveTestPath: (snapshotPath) =>
17 | snapshotPath
18 | .replace(`${path.sep}__snapshots__`, "")
19 | .slice(0, -snapshotExtension.length),
20 | testPathForConsistencyCheck: path.join(
21 | "consistency_check",
22 | "__tests__",
23 | "example.test.js",
24 | ),
25 | };
26 |
--------------------------------------------------------------------------------
/examples/bonjour/object/README.md:
--------------------------------------------------------------------------------
1 | # Bonjour (ZeroConf)
2 |
3 | The Bonjour capability broadcasts server information via ZeroConf when the Server
4 | is started.
5 |
6 | ## Bonjour options
7 |
8 | Allows options from bonjour for more [configuration](https://github.com/watson/bonjour#initializing):
9 |
10 | ```js
11 | // webpack.config.js
12 | module.exports = {
13 | // ...
14 | devServer: {
15 | bonjour: {
16 | name: "webpack-dev-server",
17 | type: "https",
18 | subtype: "webpack",
19 | },
20 | },
21 | };
22 | ```
23 |
24 | ```console
25 | npx webpack serve --config webpack.config.js
26 | ```
27 |
28 | ## What Should Happen
29 |
30 | A Zeroconf broadcast should occur, containing data with a type of `https` and a
31 | subtype of `webpack`.
32 |
--------------------------------------------------------------------------------
/examples/client/logging/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | plugins: [
11 | {
12 | apply(compiler) {
13 | compiler.hooks.thisCompilation.tap(
14 | "warnings-webpack-plugin",
15 | (compilation) => {
16 | compilation.warnings.push(
17 | new Error("Manual warnings produced during compilation."),
18 | );
19 | },
20 | );
21 | },
22 | },
23 | ],
24 | devServer: {
25 | client: {
26 | logging: "info",
27 | },
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/examples/general/proxy-simple/README.md:
--------------------------------------------------------------------------------
1 | # General: Simple Proxy
2 |
3 | ```console
4 | npx webpack serve --open
5 | ```
6 |
7 | In `webpack.config.js` there is a very simple configuration for a proxy. Note that this only works when proxying to a direct ip address. See the proxy-advanced example if you want to proxy to a domain.
8 |
9 | ## What Should Happen
10 |
11 | 1. The script should open `http://localhost:8080/` in your default browser.
12 | 2. You should see the text on the page itself change to read `Success!`.
13 | 3. Navigate to `http://localhost:8080/api/hey`.
14 | 4. Since the proxy target does not actually exist, the console/terminal should
15 | display an error that reads
16 | `[HPM] PROXY ERROR: ECONNREFUSED. localhost -> http://127.0.0.1:50545/api/hey`.
17 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = (api) => {
4 | api.cache(true);
5 |
6 | return {
7 | presets: [
8 | [
9 | "@babel/preset-env",
10 | {
11 | modules: false,
12 | targets: {
13 | esmodules: true,
14 | node: "0.12",
15 | },
16 | },
17 | ],
18 | ],
19 | plugins: ["@babel/plugin-transform-object-assign"],
20 | env: {
21 | test: {
22 | presets: [
23 | [
24 | "@babel/preset-env",
25 | {
26 | targets: {
27 | node: "18.12.0",
28 | },
29 | },
30 | ],
31 | ],
32 | plugins: ["@babel/plugin-transform-runtime"],
33 | },
34 | },
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/examples/headers/function/README.md:
--------------------------------------------------------------------------------
1 | # headers option as a function
2 |
3 | Adds headers to all responses.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | headers: () => ({ "X-Custom-Header": ["key1=value1", "key2=value2"] }),
12 | },
13 | };
14 | ```
15 |
16 | To run this example use the following command:
17 |
18 | ```console
19 | npx webpack serve --open
20 | ```
21 |
22 | ## What should happen
23 |
24 | 1. The script should open `http://localhost:8080/`.
25 | 2. You should see the text on the page itself change to read `Success!`.
26 | 3. Open the console in your browser's devtools and select the _Network_ tab.
27 | 4. Find `main.js`. The response headers should contain `X-Custom-Header: key1=value1` and `X-Custom-Header: key2=value2`.
28 |
--------------------------------------------------------------------------------
/examples/general/universal-config/client.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const target = document.querySelector("#target");
4 |
5 | if (!globalThis.fetch) {
6 | target.classList.add("fail");
7 | target.innerHTML = "fetch is not supported";
8 | } else {
9 | fetch("/server.js")
10 | .then((res) => {
11 | if (res.status === 404) throw new Error("[server.js]: Not Found");
12 | return res;
13 | })
14 | .then((res) => res.text())
15 | .then((res) => {
16 | if (res.includes("console.log('webpack-dev-server/server');")) {
17 | target.classList.add("pass");
18 | target.innerHTML = "[client.js, server.js]: Success!";
19 | }
20 | })
21 | .catch((err) => {
22 | target.classList.add("fail");
23 | target.innerHTML = err.message;
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig, globalIgnores } from "eslint/config";
2 | import config from "eslint-config-webpack";
3 | import configs from "eslint-config-webpack/configs.js";
4 |
5 | export default defineConfig([
6 | globalIgnores(["client/**/*", "examples/**/*"]),
7 | {
8 | extends: [config],
9 | ignores: ["client-src/**/*", "!client-src/webpack.config.js"],
10 | rules: {
11 | // TODO fix me
12 | "prefer-destructuring": "off",
13 | "jsdoc/require-property-description": "off",
14 | },
15 | },
16 | {
17 | files: ["client-src/**/*"],
18 | ignores: ["client-src/webpack.config.js"],
19 | extends: [configs["browser-outdated-recommended"]],
20 | },
21 | {
22 | files: ["test/**/*"],
23 | extends: [configs["universal-recommended"]],
24 | },
25 | ]);
26 |
--------------------------------------------------------------------------------
/examples/general/proxy-advanced/README.md:
--------------------------------------------------------------------------------
1 | # General: Proxy Advanced
2 |
3 | This example demonstrates a user case whereby the app proxies all urls that start with `/api` to
4 | `http://jsonplaceholder.typicode.com/`, but removes `/api` from the url. So
5 | `http://localhost:8080/api/users` should perform a request to
6 | `http://jsonplaceholder.typicode.com/users`.
7 |
8 | ```console
9 | npx webpack serve --open
10 | ```
11 |
12 | ## What should happen
13 |
14 | 1. The script should open `http://localhost:8080/` in your default browser.
15 | 2. You should see the text on the page itself change to read `Success!`.
16 | 3. Navigate to `http://localhost:8080/api/users`.
17 | 4. The page should display several JSON objects.
18 | 5. Navigate to `http://localhost:8080/api/nope`.
19 | 6. The page should display `Bypassed proxy!``.
20 |
--------------------------------------------------------------------------------
/test/fixtures/custom-client/CustomSockJSClient.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const SockJS = require("sockjs-client/dist/sockjs");
4 |
5 | module.exports = class SockJSClient {
6 | constructor(url) {
7 | this.sock = new SockJS(
8 | url.replace(/^ws:/i, "http://").replace(/^wss:/i, "https://"),
9 | );
10 | }
11 |
12 | onOpen(f) {
13 | this.sock.onopen = () => {
14 | console.log("open");
15 | f();
16 | };
17 | }
18 |
19 | onClose(f) {
20 | this.sock.onclose = () => {
21 | console.log("close");
22 | f();
23 | };
24 | }
25 |
26 | // call f with the message string as the first argument
27 | onMessage(f) {
28 | this.sock.onmessage = (e) => {
29 | const obj = JSON.parse(e.data);
30 | console.log(obj.type);
31 | f(e.data);
32 | };
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/client-src/globals.d.ts:
--------------------------------------------------------------------------------
1 | declare interface CommunicationClient {
2 | onOpen(fn: (...args: any[]) => void): void;
3 | onClose(fn: (...args: any[]) => void): void;
4 | onMessage(fn: (...args: any[]) => void): void;
5 | }
6 |
7 | declare interface CommunicationClientConstructor {
8 | new (url: string): CommunicationClient; // Defines a constructor that takes a string and returns a GreeterInstance
9 | }
10 |
11 | declare const __webpack_dev_server_client__:
12 | | CommunicationClientConstructor
13 | | { default: CommunicationClientConstructor }
14 | | undefined;
15 |
16 | declare module "ansi-html-community" {
17 | function ansiHtmlCommunity(str: string): string;
18 |
19 | namespace ansiHtmlCommunity {
20 | function setColors(colors: Record): void;
21 | }
22 |
23 | export = ansiHtmlCommunity;
24 | }
25 |
--------------------------------------------------------------------------------
/examples/on-listening/README.md:
--------------------------------------------------------------------------------
1 | # onListening
2 |
3 | Provides the ability to execute a custom function when webpack-dev-server starts listening for connections on a port.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | onListening: (devServer) => {
12 | const { port } = devServer.server.address();
13 | console.log("Listening on port:", port);
14 | },
15 | },
16 | };
17 | ```
18 |
19 | To run this example use the following command:
20 |
21 | ```console
22 | npx webpack serve --open
23 | ```
24 |
25 | ## What Should Happen
26 |
27 | 1. The script should open `http://localhost:8080/` in your default browser.
28 | 2. You should see the text on the page itself change to read `Success!`.
29 | 3. Check the terminal output, you should see `Listening on port: 8080` in the output.
30 |
--------------------------------------------------------------------------------
/examples/client/progress/README.md:
--------------------------------------------------------------------------------
1 | # client.progress Option
2 |
3 | **webpack.config.js**
4 |
5 | ```js
6 | module.exports = {
7 | // ...
8 | devServer: {
9 | client: {
10 | progress: true | "linear" | "circular",
11 | },
12 | },
13 | };
14 | ```
15 |
16 | Usage via CLI:
17 |
18 | ```shell
19 | npx webpack serve --open --client-progress
20 | npx webpack serve --open --client-progress linear
21 | npx webpack serve --open --client-progress circular
22 | ```
23 |
24 | To disable:
25 |
26 | ```shell
27 | npx webpack serve --open --no-client-progress
28 | ```
29 |
30 | ## What Should Happen
31 |
32 | 1. The script should open `http://localhost:8080/` in your default browser.
33 | 2. You should see the text on the page itself change to read `Success!`.
34 | 3. In `app.js` change the text and save.
35 | 4. You should see the compilation progress in the browser console.
36 |
--------------------------------------------------------------------------------
/examples/headers/array/README.md:
--------------------------------------------------------------------------------
1 | # headers option as an object
2 |
3 | Adds headers to all responses.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | headers: [
12 | {
13 | key: "X-Foo",
14 | value: "value1",
15 | },
16 | {
17 | key: "X-Bar",
18 | value: "value2",
19 | },
20 | ],
21 | },
22 | };
23 | ```
24 |
25 | To run this example use the following command:
26 |
27 | ```console
28 | npx webpack serve --open
29 | ```
30 |
31 | ## What should happen
32 |
33 | 1. The script should open `http://localhost:8080/`.
34 | 2. You should see the text on the page itself change to read `Success!`.
35 | 3. Open the console in your browser's devtools and select the _Network_ tab.
36 | 4. Find `main.js`. The response headers should contain `X-Foo: value1` and `X-Bar: value2`.
37 |
--------------------------------------------------------------------------------
/examples/open-target-multiple/README.md:
--------------------------------------------------------------------------------
1 | # Open Target Option (Multiple)
2 |
3 | **webpack.config.js**
4 |
5 | ```js
6 | module.exports = {
7 | // ...
8 | devServer: {
9 | open: {
10 | target: ["/example1.html", "example2.html"],
11 | },
12 | },
13 | };
14 | ```
15 |
16 | Usage via CLI:
17 |
18 | ```console
19 | npx webpack serve --open-target example1.html --open-target example2.html
20 | ```
21 |
22 | Some applications may consist of multiple pages. During development it may
23 | be useful to directly open multiple pages at the same time. The pages to open
24 | may be specified as the argument to the `open-target` option.
25 |
26 | ## What Should Happen
27 |
28 | The script should open `http://localhost:8080/example1.html` and
29 | `http://localhost:8080/example2.html` in your default browser.
30 | You should see the text on the page itself change to read `Success!`.
31 |
--------------------------------------------------------------------------------
/scripts/prepare-test-for-old-node.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const fs = require("node:fs");
4 | const path = require("node:path");
5 |
6 | /**
7 | * @returns {Promise}
8 | */
9 | async function setup() {
10 | const serverCodePath = path.resolve(__dirname, "../lib/Server.js");
11 | let serverCode = await fs.promises.readFile(serverCodePath, "utf8");
12 |
13 | serverCode = serverCode.replaceAll(
14 | /\(await import\((".+")\)\)\.default/g,
15 | "require($1)",
16 | );
17 |
18 | await fs.promises.writeFile(serverCodePath, serverCode);
19 | }
20 |
21 | Promise.resolve()
22 | .then(() => setup())
23 | // eslint-disable-next-line unicorn/prefer-top-level-await
24 | .then(
25 | () => {
26 | // eslint-disable-next-line no-console
27 | console.log("The setup was successful");
28 | },
29 | (error) => {
30 | throw error;
31 | },
32 | );
33 |
--------------------------------------------------------------------------------
/examples/proxy/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const express = require("express");
4 | // our setup function adds behind-the-scenes bits to the config that all of our
5 | // examples need
6 | const { setup } = require("../util");
7 |
8 | /**
9 | *
10 | */
11 | async function listenProxyServer() {
12 | const proxyApp = express();
13 |
14 | proxyApp.get("/proxy", (req, res) => {
15 | res.send("response from proxy");
16 | });
17 |
18 | await new Promise((resolve) => {
19 | proxyApp.listen(5000, () => {
20 | resolve();
21 | });
22 | });
23 | }
24 |
25 | module.exports = setup({
26 | context: __dirname,
27 | entry: "./app.js",
28 | devServer: {
29 | onBeforeSetupMiddleware: async () => {
30 | await listenProxyServer();
31 | },
32 | proxy: {
33 | "/proxy": {
34 | target: "http://localhost:5000",
35 | },
36 | },
37 | },
38 | });
39 |
--------------------------------------------------------------------------------
/examples/proxy/README.md:
--------------------------------------------------------------------------------
1 | # proxy
2 |
3 | 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.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | proxy: {
12 | "/proxy": {
13 | target: "http://localhost:5000",
14 | },
15 | },
16 | },
17 | };
18 | ```
19 |
20 | To run this example use the following command:
21 |
22 | ```console
23 | npx webpack serve --open
24 | ```
25 |
26 | ## What Should Happen
27 |
28 | 1. The script start a proxy server on `http://localhost:5000/` and open `http://localhost:8080/` in your default browser.
29 | 2. You should see the text on the page itself change to read `Success! Now visit /proxy`.
30 | 3. Now visit the `/proxy` route by clicking on the `/proxy` text, you should see the text on the page itself change to read `response from proxy`.
31 |
--------------------------------------------------------------------------------
/test/fixtures/simple-config-other/foo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | console.log(
4 | "Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Long Line.",
5 | );
6 |
--------------------------------------------------------------------------------
/examples/default/README.md:
--------------------------------------------------------------------------------
1 | # Default State
2 |
3 | This example demonstrates how to use `webpack-dev-server`.
4 |
5 | ```console
6 | npx webpack serve --open
7 | ```
8 |
9 | To run your app using an alternative config, use:
10 |
11 | ```console
12 | npx webpack serve --open --config alternative.config.js
13 | ```
14 |
15 | ## What Should Happen
16 |
17 | 1. The script should open `http://localhost:8080/` in your default browser.
18 | 2. You should see the text on the page itself change to read `Success!`.
19 | 3. In `app.js` uncomment the code that results in an error and save.
20 | 4. This error should be visible in the console/terminal and in the browser's devtools.
21 | 5. In `app.js` uncomment the code that results in a warning. This warning should
22 | be visible in the console/terminal and in the browser's devtools.
23 | 6. Try changing something in `style.less`. The browser should refresh, and the
24 | change should be visible in the app.
25 |
--------------------------------------------------------------------------------
/test/cli/ipc-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const os = require("node:os");
4 | const path = require("node:path");
5 | const { normalizeStderr, testBin } = require("../helpers/test-bin");
6 |
7 | describe('"ipc" CLI option', () => {
8 | it('should work using "--ipc"', async () => {
9 | const { exitCode, stderr } = await testBin(["--ipc"]);
10 |
11 | expect(exitCode).toBe(0);
12 | expect(normalizeStderr(stderr)).toMatchSnapshot("stderr");
13 | });
14 |
15 | it('should work using "--ipc="', async () => {
16 | const isWindows = process.platform === "win32";
17 | const pipePrefix = isWindows ? "\\\\.\\pipe\\" : os.tmpdir();
18 | const pipeName = "webpack-dev-server.cli.sock";
19 | const ipc = path.join(pipePrefix, pipeName);
20 |
21 | const { exitCode, stderr } = await testBin(["--ipc", ipc]);
22 |
23 | expect(exitCode).toBe(0);
24 | expect(normalizeStderr(stderr)).toMatchSnapshot("stderr");
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/examples/.assets/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WDS ▻ <%= htmlWebpackPlugin.options.title %>
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 | webpack-dev-server
23 |
24 |
25 |
26 | <%= htmlWebpackPlugin.options.title %>
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/test/cli/historyApiFallback-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { normalizeStderr, testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-history-api-fallback"];
5 |
6 | describe('"historyApiFallback" CLI option', () => {
7 | it('should work using "--history-api-fallback"', async () => {
8 | const { exitCode, stderr } = await testBin(
9 | ["--port", port, "--history-api-fallback"],
10 | {
11 | outputKillStr: /404s will fallback/,
12 | },
13 | );
14 |
15 | expect(exitCode).toBe(0);
16 | expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot();
17 | });
18 |
19 | it('should work using "--no-history-api-fallback"', async () => {
20 | const { exitCode, stderr } = await testBin([
21 | "--port",
22 | port,
23 | "--no-history-api-fallback",
24 | ]);
25 |
26 | expect(exitCode).toBe(0);
27 | expect(normalizeStderr(stderr, { ipv6: true })).toMatchSnapshot();
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/examples/client/reconnect/false/README.md:
--------------------------------------------------------------------------------
1 | # client.reconnect: false
2 |
3 | ## false
4 |
5 | Tells dev-server the number of times it should try to reconnect the client. When `false` it will not try to reconnect.
6 |
7 | **webpack.config.js**
8 |
9 | ```js
10 | module.exports = {
11 | // ...
12 | devServer: {
13 | client: {
14 | reconnect: false,
15 | },
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```shell
23 | npx webpack serve --open --no-client-reconnect
24 | ```
25 |
26 | ## What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. Open the console tab in your browser's devtools.
30 | 3. Now close the server with `Ctrl+C` to disconnect the client.
31 |
32 | In the devtools console you should see that webpack-dev-server is not trying to reconnect:
33 |
34 | ```
35 | [webpack-dev-server] Hot Module Replacement enabled.
36 | [webpack-dev-server] Live Reloading enabled.
37 | [webpack-dev-server] Disconnected!
38 | ```
39 |
--------------------------------------------------------------------------------
/scripts/extend-webpack-types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("node:path");
4 | const fs = require("graceful-fs");
5 |
6 | /**
7 | * @returns {Promise}
8 | */
9 | async function extendTypes() {
10 | const typesPath = path.resolve(__dirname, "../types/lib/Server.d.ts");
11 | const content = await fs.promises.readFile(typesPath, "utf8");
12 | const newContent = `${content}
13 | // DO NOT REMOVE THIS!
14 | type DevServerConfiguration = Configuration;
15 | declare module "webpack" {
16 | interface Configuration {
17 | /**
18 | * Can be used to configure the behaviour of webpack-dev-server when
19 | * the webpack config is passed to webpack-dev-server CLI.
20 | */
21 | devServer?: DevServerConfiguration | undefined;
22 | }
23 | }
24 | `;
25 |
26 | await fs.promises.writeFile(typesPath, newContent);
27 | }
28 |
29 | // eslint-disable-next-line unicorn/prefer-top-level-await
30 | Promise.resolve().then(
31 | () => extendTypes(),
32 | (error) => {
33 | throw error;
34 | },
35 | );
36 |
--------------------------------------------------------------------------------
/examples/setup-middlewares/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | entry: "./app.js",
10 | devServer: {
11 | setupMiddlewares: (middlewares, devServer) => {
12 | if (!devServer) {
13 | throw new Error("webpack-dev-server is not defined");
14 | }
15 |
16 | devServer.app.get("/setup-middleware/some/path", (_, response) => {
17 | response.send("setup-middlewares option GET");
18 | });
19 |
20 | middlewares.push({
21 | name: "hello-world-test-one",
22 | // `path` is optional
23 | path: "/foo/bar",
24 | middleware: (req, res) => {
25 | res.send("Foo Bar!");
26 | },
27 | });
28 |
29 | middlewares.push((req, res) => {
30 | res.send("Hello World!");
31 | });
32 |
33 | return middlewares;
34 | },
35 | },
36 | });
37 |
--------------------------------------------------------------------------------
/client-src/clients/WebSocketClient.js:
--------------------------------------------------------------------------------
1 | import { log } from "../utils/log.js";
2 |
3 | /** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */
4 |
5 | /**
6 | * @implements {CommunicationClient}
7 | */
8 | export default class WebSocketClient {
9 | /**
10 | * @param {string} url url to connect
11 | */
12 | constructor(url) {
13 | this.client = new WebSocket(url);
14 | this.client.onerror = (error) => {
15 | log.error(error);
16 | };
17 | }
18 |
19 | /**
20 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
21 | */
22 | onOpen(fn) {
23 | this.client.onopen = fn;
24 | }
25 |
26 | /**
27 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
28 | */
29 | onClose(fn) {
30 | this.client.onclose = fn;
31 | }
32 |
33 | // call f with the message string as the first argument
34 | /**
35 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
36 | */
37 | onMessage(fn) {
38 | this.client.onmessage = (err) => {
39 | fn(err.data);
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/test/fixtures/universal-compiler-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = [
6 | {
7 | name: "browser",
8 | mode: "development",
9 | context: __dirname,
10 | stats: "none",
11 | entry: "./browser.js",
12 | output: {
13 | path: "/",
14 | filename: "browser.js",
15 | },
16 | plugins: [new HTMLGeneratorPlugin()],
17 | infrastructureLogging: {
18 | level: "info",
19 | stream: {
20 | write: () => {},
21 | },
22 | },
23 | },
24 | {
25 | name: "server",
26 | mode: "development",
27 | context: __dirname,
28 | target: "node",
29 | stats: "none",
30 | entry: "./server.js",
31 | output: {
32 | path: "/",
33 | filename: "server.js",
34 | },
35 | plugins: [new HTMLGeneratorPlugin()],
36 | infrastructureLogging: {
37 | level: "info",
38 | stream: {
39 | write: () => {},
40 | },
41 | },
42 | },
43 | ];
44 |
--------------------------------------------------------------------------------
/examples/open-target-multiple/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HtmlWebpackPlugin = require("html-webpack-plugin");
4 | // our setup function adds behind-the-scenes bits to the config that all of our
5 | // examples need
6 | const { setup } = require("../util");
7 |
8 | module.exports = [
9 | setup({
10 | context: __dirname,
11 | entry: "./app1.js",
12 | output: {
13 | filename: "app1.js",
14 | },
15 | plugins: [
16 | new HtmlWebpackPlugin({
17 | filename: "example1.html",
18 | template: "../.assets/layout.html",
19 | title: "Open Target (Multiple) / Example / Page 1",
20 | }),
21 | ],
22 | }),
23 | setup({
24 | context: __dirname,
25 | entry: "./app2.js",
26 | output: {
27 | filename: "app2.js",
28 | },
29 | plugins: [
30 | new HtmlWebpackPlugin({
31 | filename: "example2.html",
32 | template: "../.assets/layout.html",
33 | title: "Open Target (Multiple) / Example / Page 2",
34 | }),
35 | ],
36 | }),
37 | ];
38 |
--------------------------------------------------------------------------------
/test/cli/webSocketServer-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-web-socket-server"];
5 |
6 | describe('"webSocketServer" CLI option', () => {
7 | it('should work using "--web-socket-server-type ws"', async () => {
8 | const { exitCode } = await testBin([
9 | "--port",
10 | port,
11 | "--web-socket-server-type",
12 | "ws",
13 | ]);
14 |
15 | expect(exitCode).toBe(0);
16 | });
17 |
18 | it('should work using "--web-socket-server-type sockjs"', async () => {
19 | const { exitCode } = await testBin([
20 | "--port",
21 | port,
22 | "--web-socket-server-type",
23 | "sockjs",
24 | ]);
25 |
26 | expect(exitCode).toBe(0);
27 | });
28 |
29 | it('should work using "--no-web-socket-server"', async () => {
30 | const { exitCode } = await testBin([
31 | "--port",
32 | port,
33 | "--no-web-socket-server",
34 | ]);
35 |
36 | expect(exitCode).toBe(0);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = [
6 | {
7 | name: "app",
8 | dependencies: ["worker"],
9 | devtool: false,
10 | target: "web",
11 | entry: "./index.js",
12 | mode: "development",
13 | context: __dirname,
14 | stats: "none",
15 | output: {
16 | path: "/",
17 | },
18 | infrastructureLogging: {
19 | level: "info",
20 | stream: {
21 | write: () => {},
22 | },
23 | },
24 | plugins: [new HTMLGeneratorPlugin()],
25 | },
26 | {
27 | name: "worker",
28 | devtool: false,
29 | target: "webworker",
30 | entry: "./worker.js",
31 | mode: "development",
32 | context: __dirname,
33 | stats: "none",
34 | output: {
35 | path: "/",
36 | filename: "worker.js",
37 | },
38 | infrastructureLogging: {
39 | level: "info",
40 | stream: {
41 | write: () => {},
42 | },
43 | },
44 | },
45 | ];
46 |
--------------------------------------------------------------------------------
/examples/api/start/README.md:
--------------------------------------------------------------------------------
1 | # API: start
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also
4 | choose to start a server via the API.
5 |
6 | This example demonstrates using `start` method. It instructs `webpack-dev-server` instance to start the server.
7 |
8 | ```js
9 | const Webpack = require("webpack");
10 | const WebpackDevServer = require("webpack-dev-server");
11 | const webpackConfig = require("./webpack.config");
12 |
13 | const compiler = Webpack(webpackConfig);
14 | const devServerOptions = { ...webpackConfig.devServer };
15 | const server = new WebpackDevServer(devServerOptions, compiler);
16 |
17 | const runServer = async () => {
18 | console.log("Starting server...");
19 | await server.start();
20 | };
21 |
22 | runServer();
23 | ```
24 |
25 | Use the following command to run this example:
26 |
27 | ```console
28 | node server.js
29 | ```
30 |
31 | ## What Should Happen
32 |
33 | 1. Open `http://localhost:8080/` in your preferred browser.
34 | 2. You should see the text on the page itself change to read `Success!`.
35 |
--------------------------------------------------------------------------------
/examples/client/trusted-types-overlay/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("node:path");
4 | const HtmlWebpackPlugin = require("html-webpack-plugin");
5 | // our setup function adds behind-the-scenes bits to the config that all of our
6 | // examples need
7 | const { setup } = require("../../util");
8 |
9 | const config = setup({
10 | context: __dirname,
11 | // create error for overlay
12 | entry: "./app.js",
13 | output: {
14 | trustedTypes: { policyName: "webpack" },
15 | },
16 | devServer: {
17 | headers: {
18 | "Content-Security-Policy": "require-trusted-types-for 'script'",
19 | },
20 | client: {
21 | overlay: {
22 | trustedTypesPolicyName: "webpack#dev-overlay",
23 | },
24 | },
25 | },
26 | });
27 |
28 | // overwrite the index.html with our own to enable Trusted Types
29 | config.plugins[0] = new HtmlWebpackPlugin({
30 | filename: "index.html",
31 | template: path.join(__dirname, "./layout.html"),
32 | title: "trusted types overlay",
33 | });
34 |
35 | module.exports = config;
36 |
--------------------------------------------------------------------------------
/test/fixtures/multi-compiler-two-configurations/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
4 |
5 | module.exports = [
6 | {
7 | target: "web",
8 | name: "one",
9 | mode: "development",
10 | context: __dirname,
11 | entry: "./one.js",
12 | stats: "none",
13 | output: {
14 | path: "/",
15 | filename: "one-[name].js",
16 | },
17 | plugins: [new HTMLGeneratorPlugin()],
18 | infrastructureLogging: {
19 | level: "info",
20 | stream: {
21 | write: () => {},
22 | },
23 | },
24 | },
25 | {
26 | target: "web",
27 | name: "two",
28 | mode: "development",
29 | context: __dirname,
30 | entry: "./two.js",
31 | stats: "none",
32 | output: {
33 | path: "/",
34 | filename: "two-[name].js",
35 | },
36 | plugins: [new HTMLGeneratorPlugin()],
37 | infrastructureLogging: {
38 | level: "info",
39 | stream: {
40 | write: () => {},
41 | },
42 | },
43 | },
44 | ];
45 |
--------------------------------------------------------------------------------
/test/cli/__snapshots__/port-option.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`"port" CLI option should work using "--port ": stderr 1`] = `
4 | " [webpack-dev-server] Project is running at:
5 | Loopback: http://localhost:/, http://:/, http://[]:/
6 | [webpack-dev-server] On Your Network (IPv4): http://:/
7 | [webpack-dev-server] On Your Network (IPv6): http://[]:/
8 | [webpack-dev-server] Content not from webpack is served from '/public' directory"
9 | `;
10 |
11 | exports[`"port" CLI option should work using "--port auto": stderr 1`] = `
12 | " [webpack-dev-server] Project is running at:
13 | Loopback: http://localhost:/, http://:/, http://[]:/
14 | [webpack-dev-server] On Your Network (IPv4): http://:/
15 | [webpack-dev-server] On Your Network (IPv6): http://[]:/
16 | [webpack-dev-server] Content not from webpack is served from '/public' directory"
17 | `;
18 |
--------------------------------------------------------------------------------
/examples/general/proxy-hot-reload/README.md:
--------------------------------------------------------------------------------
1 | # General: Proxy Hot Reload
2 |
3 | ```shell
4 | npx webpack serve --open
5 | ```
6 |
7 | Enables hot reloading for proxy config. If function is provided instead of
8 | object, dev server calls it on each request to get proxy config and replaces proxy middleware if config was changed.
9 |
10 | ## What should happen
11 |
12 | 1. The script should open `http://localhost:8080/` in your default browser.
13 | 2. You should see the text on the page itself change to read `Success!`.
14 | 3. Navigate to `http://localhost:8080/api/users`.
15 | 4. The page should display several JSON objects.
16 |
17 | While the server is running, open `proxy-config.js` and replace the following:
18 |
19 | ```js
20 | module.exports = {
21 | target: "http://jsonplaceholder.typicode.com/",
22 | pathRewrite: {
23 | "^/api": "",
24 | },
25 | };
26 | ```
27 |
28 | with:
29 |
30 | ```js
31 | module.exports = {
32 | target: "http://reqres.in/",
33 | };
34 | ```
35 |
36 | A request to `http://localhost:8080/api/users` should return a response from `http://reqres.in/`.
37 |
--------------------------------------------------------------------------------
/examples/ipc/README.md:
--------------------------------------------------------------------------------
1 | # IPC
2 |
3 | The Unix socket to listen to (instead of a [host](../host-and-port/README.md)).
4 |
5 | ## true
6 |
7 | Setting it to `true` will listen to a socket at `/your-os-temp-dir/webpack-dev-server.sock`:
8 |
9 | **webpack.config.js**
10 |
11 | ```js
12 | module.exports = {
13 | // ...
14 | devServer: {
15 | ipc: true,
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```console
23 | npx webpack serve --ipc
24 | ```
25 |
26 | ## string
27 |
28 | You can also listen to a different socket with:
29 |
30 | **webpack.config.js**
31 |
32 | ```js
33 | const path = require("node:path");
34 |
35 | module.exports = {
36 | // ...
37 | devServer: {
38 | ipc: path.join(__dirname, "my-socket.sock"),
39 | },
40 | };
41 | ```
42 |
43 | Usage via CLI:
44 |
45 | ```console
46 | npx webpack serve --ipc ./my-socket.sock
47 | ```
48 |
49 | ## What Should Happen
50 |
51 | 1. The script should listen to the socket provided.
52 | 1. A proxy server should be created.
53 | 1. Go to `http://localhost:8080/`, you should see the text on the page itself change to read `Success!`.
54 |
--------------------------------------------------------------------------------
/examples/client/trusted-types-overlay/README.md:
--------------------------------------------------------------------------------
1 | # client.overlay.trustedTypesPolicyName option
2 |
3 | **webpack.config.js**
4 |
5 | ```js
6 | module.exports = {
7 | // ...
8 | output: {
9 | trustedTypes: { policyName: "webpack" },
10 | },
11 | devServer: {
12 | client: {
13 | overlay: {
14 | trustedTypesPolicyName: "webpack#dev-overlay",
15 | },
16 | },
17 | },
18 | };
19 | ```
20 |
21 | Usage via CLI:
22 |
23 | ```shell
24 | npx webpack serve --open
25 | ```
26 |
27 | ## What Should Happen
28 |
29 | 1. The script should open `http://localhost:8080/` in your default browser.
30 | 2. You should see an overlay in browser for compilation errors.
31 | 3. Modify `devServer.client.overlay.trustedTypesPolicyName` in webpack.config.js to `disallowed-policy` and save.
32 | 4. Restart the command and you should not see an overlay at all. In the console you should see the following error:
33 |
34 | ```
35 | Refused to create a TrustedTypePolicy named 'disallowed-policy' because it violates the following Content Security Policy directive: "trusted-types webpack webpack#dev-overlay".
36 | ```
37 |
--------------------------------------------------------------------------------
/examples/client/logging/README.md:
--------------------------------------------------------------------------------
1 | # client.logging Option
2 |
3 | `'log' | 'info' | 'warn' | 'error' | 'none' | 'verbose'`
4 |
5 | Allows to set log level in the browser, e.g. before reloading, before an error or when Hot Module Replacement is enabled.
6 |
7 | **webpack.config.js**
8 |
9 | ```js
10 | module.exports = {
11 | // ...
12 | devServer: {
13 | client: {
14 | logging: "info",
15 | },
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```shell
23 | npx webpack serve --open --client-logging info
24 | ```
25 |
26 | ## What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. You should see an overlay in browser for compilation warnings.
30 | 3. Open the console in your browser's devtools.
31 |
32 | In the devtools console you should see:
33 |
34 | ```
35 | [HMR] Waiting for update signal from WDS...
36 | [webpack-dev-server] Hot Module Replacement enabled.
37 | [webpack-dev-server] Live Reloading enabled.
38 | [webpack-dev-server] Warnings while compiling.
39 | [webpack-dev-server] Manual warnings produced during compilation.
40 | ```
41 |
--------------------------------------------------------------------------------
/examples/ipc/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const http = require("node:http");
4 | const httpProxy = require("http-proxy");
5 | // our setup function adds behind-the-scenes bits to the config that all of our
6 | // examples need
7 | const { setup } = require("../util");
8 |
9 | module.exports = setup({
10 | context: __dirname,
11 | entry: "./app.js",
12 | devServer: {
13 | webSocketServer: "ws",
14 | onAfterSetupMiddleware: (server) => {
15 | const proxyPort = 8080;
16 | const proxyHost = "127.0.0.1";
17 | const proxy = httpProxy.createProxyServer({
18 | target: { socketPath: server.options.ipc },
19 | });
20 |
21 | const proxyServer = http.createServer((request, response) => {
22 | // You can define here your custom logic to handle the request
23 | // and then proxy the request.
24 | proxy.web(request, response);
25 | });
26 |
27 | proxyServer.on("upgrade", (request, socket, head) => {
28 | proxy.ws(request, socket, head);
29 | });
30 |
31 | proxyServer.listen(proxyPort, proxyHost);
32 | },
33 | },
34 | });
35 |
--------------------------------------------------------------------------------
/examples/client/overlay/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | module.exports = setup({
8 | context: __dirname,
9 | // create error for overlay
10 | entry: "./app.js",
11 | devServer: {
12 | client: {
13 | overlay: {
14 | warnings: false,
15 | runtimeErrors: (msg) => {
16 | if (msg) {
17 | if (msg instanceof DOMException && msg.name === "AbortError") {
18 | return false;
19 | }
20 |
21 | let msgString;
22 |
23 | if (msg instanceof Error) {
24 | msgString = msg.message;
25 | } else if (typeof msg === "string") {
26 | msgString = msg;
27 | }
28 |
29 | if (msgString) {
30 | return !/something/i.test(msgString);
31 | }
32 | }
33 |
34 | return true;
35 | },
36 | },
37 | },
38 | },
39 | // uncomment to test for IE
40 | // target: ["web", "es5"],
41 | });
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | 'Software'), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/scripts/globalSetupTest.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const tcpPortUsed = require("tcp-port-used");
4 | const { version } = require("webpack");
5 | const ports = require("../test/ports-map");
6 |
7 | // eslint-disable-next-line no-console
8 | console.log(`\n Running tests for webpack @${version} \n`);
9 |
10 | /**
11 | * @returns {Promise}
12 | */
13 | async function validatePorts() {
14 | const samples = [];
15 |
16 | for (const key of Object.keys(ports)) {
17 | const value = ports[key];
18 | const arr = Array.isArray(value) ? value : [value];
19 |
20 | for (const port of arr) {
21 | const check = tcpPortUsed.check(port, "localhost").then((inUse) => {
22 | if (inUse) {
23 | throw new Error(`${port} has already used. [${key}]`);
24 | }
25 | });
26 |
27 | samples.push(check);
28 | }
29 | }
30 |
31 | try {
32 | await Promise.all(samples);
33 | } catch (err) {
34 | // eslint-disable-next-line no-console
35 | console.error(err);
36 | // eslint-disable-next-line n/no-process-exit
37 | process.exit(1);
38 | }
39 | }
40 |
41 | module.exports = validatePorts;
42 |
--------------------------------------------------------------------------------
/test/helpers/normalize-options.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | /**
4 | * @param {import("https").ServerOptions} options server options
5 | * @returns {Record} normalized server options
6 | */
7 | function normalizeOptions(options) {
8 | const normalizedOptions = {};
9 |
10 | for (const propertyName in options) {
11 | let value = options[propertyName];
12 |
13 | if (Array.isArray(value)) {
14 | value = value.map((item) => {
15 | if (Buffer.isBuffer(item)) {
16 | return "";
17 | } else if (
18 | typeof item.pem !== "undefined" &&
19 | Buffer.isBuffer(item.pem)
20 | ) {
21 | item.pem = "";
22 | } else if (
23 | typeof item.buf !== "undefined" &&
24 | Buffer.isBuffer(item.buf)
25 | ) {
26 | item.buf = "";
27 | }
28 |
29 | return item;
30 | });
31 | } else if (Buffer.isBuffer(value)) {
32 | value = "";
33 | }
34 |
35 | normalizedOptions[propertyName] = value;
36 | }
37 |
38 | return normalizedOptions;
39 | }
40 |
41 | module.exports = normalizeOptions;
42 |
--------------------------------------------------------------------------------
/test/cli/__snapshots__/historyApiFallback-option.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`"historyApiFallback" CLI option should work using "--history-api-fallback" 1`] = `
4 | " [webpack-dev-server] Project is running at:
5 | Loopback: http://localhost:/, http://:/, http://[]:/
6 | [webpack-dev-server] On Your Network (IPv4): http://:/
7 | [webpack-dev-server] On Your Network (IPv6): http://[]:/
8 | [webpack-dev-server] Content not from webpack is served from '/public' directory
9 | [webpack-dev-server] 404s will fallback to '/index.html'"
10 | `;
11 |
12 | exports[`"historyApiFallback" CLI option should work using "--no-history-api-fallback" 1`] = `
13 | " [webpack-dev-server] Project is running at:
14 | Loopback: http://localhost:/, http://:/, http://[]:/
15 | [webpack-dev-server] On Your Network (IPv4): http://:/
16 | [webpack-dev-server] On Your Network (IPv6): http://[]:/
17 | [webpack-dev-server] Content not from webpack is served from '/public' directory"
18 | `;
19 |
--------------------------------------------------------------------------------
/test/fixtures/ssl/localhost-cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDCTCCAfGgAwIBAgIUevWiuCfenWuq9KyC8aQ/tc1Io14wDQYJKoZIhvcNAQEL
3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDQyNDE2MDYyMloXDTI0MDUy
4 | NDE2MDYyMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
5 | AAOCAQ8AMIIBCgKCAQEA1v/lb9u9WkqkF7zjIKe2R+b4S0sQnWIfBFZ0ggtaOL0a
6 | ntud/EuaGQgLtJgSwO2M2xIqKx+yoLhoM+273EJe0KmfJMxYNAkhwP9h6vrKnaQJ
7 | mpAhoalfEGyCrnHHMKISAAn4Rlc8NXnULoFhHzNm8bdqvP33rCmsJ+tNYC5kwzyt
8 | HvRNFyg9BOUfACiPW17opFH0rao3IfZrQ6yRbknef1pX1x2pbDAH14rCT/vXaTs6
9 | VGuqLE/wRsSt+7nMHy/PmXxMyb4G4/UflYtnKfmXpDRw+TDEGzvTZedtoOz+rrJC
10 | e989R9qYGrlPfyfZbI+O348FV66I+jcD+/EUQs+HkwIDAQABo1MwUTAdBgNVHQ4E
11 | FgQU6bk4LSwtVQEt7V/ev+Zj270zdAkwHwYDVR0jBBgwFoAU6bk4LSwtVQEt7V/e
12 | v+Zj270zdAkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAUBgo
13 | E3CZrrc/MaadFg1meNk+eKACmTsIa5cT6zi7MsvoKakXEd4bGd+iLifUzlAa1ygj
14 | dQppfprb5t68I7oO9/lkh2DfKrXxW/RpdhB05KslUd8q/3XY5kyao5quzeiVoMHR
15 | u+XYjoy2mTwdUC2uzFy6rkHsAkJy2vJJoDdlNsrKn6AZmh+voHHKrAtOL4gnanQV
16 | wR1u8eBVfk2MKIl2pNSCA4bD16uZyp3+oqq097BEoVa1pR+l8nwbsh/YfALifq/d
17 | P3yiN5+EqgiOIF9b8PZORe+Ry1O7uvPnU2ZRkVWPJ1S17Ms0lnr7IY3qjSBTuK66
18 | 5uYi7ojrb5Vf0UL5oQ==
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/client-src/clients/SockJSClient.js:
--------------------------------------------------------------------------------
1 | import SockJS from "../modules/sockjs-client/index.js";
2 | import { log } from "../utils/log.js";
3 |
4 | /** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */
5 |
6 | /**
7 | * @implements {CommunicationClient}
8 | */
9 | export default class SockJSClient {
10 | /**
11 | * @param {string} url url
12 | */
13 | constructor(url) {
14 | // SockJS requires `http` and `https` protocols
15 | this.sock = new SockJS(
16 | url.replace(/^ws:/i, "http:").replace(/^wss:/i, "https:"),
17 | );
18 | this.sock.onerror = (error) => {
19 | log.error(error);
20 | };
21 | }
22 |
23 | /**
24 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
25 | */
26 | onOpen(fn) {
27 | this.sock.onopen = fn;
28 | }
29 |
30 | /**
31 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
32 | */
33 | onClose(fn) {
34 | this.sock.onclose = fn;
35 | }
36 |
37 | // call f with the message string as the first argument
38 | /**
39 | * @param {(...args: EXPECTED_ANY[]) => void} fn function
40 | */
41 | onMessage(fn) {
42 | this.sock.onmessage = (err) => {
43 | fn(err.data);
44 | };
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples/app/hono/ssl/localhost-cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDCTCCAfGgAwIBAgIUevWiuCfenWuq9KyC8aQ/tc1Io14wDQYJKoZIhvcNAQEL
3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDQyNDE2MDYyMloXDTI0MDUy
4 | NDE2MDYyMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
5 | AAOCAQ8AMIIBCgKCAQEA1v/lb9u9WkqkF7zjIKe2R+b4S0sQnWIfBFZ0ggtaOL0a
6 | ntud/EuaGQgLtJgSwO2M2xIqKx+yoLhoM+273EJe0KmfJMxYNAkhwP9h6vrKnaQJ
7 | mpAhoalfEGyCrnHHMKISAAn4Rlc8NXnULoFhHzNm8bdqvP33rCmsJ+tNYC5kwzyt
8 | HvRNFyg9BOUfACiPW17opFH0rao3IfZrQ6yRbknef1pX1x2pbDAH14rCT/vXaTs6
9 | VGuqLE/wRsSt+7nMHy/PmXxMyb4G4/UflYtnKfmXpDRw+TDEGzvTZedtoOz+rrJC
10 | e989R9qYGrlPfyfZbI+O348FV66I+jcD+/EUQs+HkwIDAQABo1MwUTAdBgNVHQ4E
11 | FgQU6bk4LSwtVQEt7V/ev+Zj270zdAkwHwYDVR0jBBgwFoAU6bk4LSwtVQEt7V/e
12 | v+Zj270zdAkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAUBgo
13 | E3CZrrc/MaadFg1meNk+eKACmTsIa5cT6zi7MsvoKakXEd4bGd+iLifUzlAa1ygj
14 | dQppfprb5t68I7oO9/lkh2DfKrXxW/RpdhB05KslUd8q/3XY5kyao5quzeiVoMHR
15 | u+XYjoy2mTwdUC2uzFy6rkHsAkJy2vJJoDdlNsrKn6AZmh+voHHKrAtOL4gnanQV
16 | wR1u8eBVfk2MKIl2pNSCA4bD16uZyp3+oqq097BEoVa1pR+l8nwbsh/YfALifq/d
17 | P3yiN5+EqgiOIF9b8PZORe+Ry1O7uvPnU2ZRkVWPJ1S17Ms0lnr7IY3qjSBTuK66
18 | 5uYi7ojrb5Vf0UL5oQ==
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/test/fixtures/worker-config-dev-server-false/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 | const HTMLGeneratorPlugin = require("../../helpers/html-generator-plugin");
5 |
6 | module.exports = [
7 | {
8 | name: "app",
9 | // dependencies: ["worker"],
10 | devtool: false,
11 | target: "web",
12 | entry: "./index.js",
13 | mode: "development",
14 | context: __dirname,
15 | stats: "none",
16 | output: {
17 | path: path.resolve(__dirname, "./dist/"),
18 | },
19 | infrastructureLogging: {
20 | level: "info",
21 | stream: {
22 | write: () => {},
23 | },
24 | },
25 | plugins: [new HTMLGeneratorPlugin()],
26 | },
27 | {
28 | name: "worker",
29 | devtool: false,
30 | target: "webworker",
31 | entry: "./worker.js",
32 | mode: "development",
33 | context: __dirname,
34 | stats: "none",
35 | output: {
36 | path: path.resolve(__dirname, "public"),
37 | filename: "worker-bundle.js",
38 | },
39 | infrastructureLogging: {
40 | level: "info",
41 | stream: {
42 | write: () => {},
43 | },
44 | },
45 | devServer: false,
46 | },
47 | ];
48 |
--------------------------------------------------------------------------------
/examples/api/start-callback/README.md:
--------------------------------------------------------------------------------
1 | # API: startCallback(callback)
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also choose to start a server via the API.
4 |
5 | This example demonstrates using `startCallback(callback)` method. It instructs `webpack-dev-server` instance to start the server and then run the callback function.
6 |
7 | ```js
8 | const Webpack = require("webpack");
9 | const WebpackDevServer = require("webpack-dev-server");
10 | const webpackConfig = require("./webpack.config");
11 |
12 | const compiler = Webpack(webpackConfig);
13 | const devServerOptions = { ...webpackConfig.devServer };
14 | const server = new WebpackDevServer(devServerOptions, compiler);
15 |
16 | server.startCallback(() => {
17 | console.log("Successfully started server on http://localhost:8080");
18 | });
19 | ```
20 |
21 | Use the following command to run this example:
22 |
23 | ```console
24 | node server.js
25 | ```
26 |
27 | ## What Should Happen
28 |
29 | 1. Open `http://localhost:8080/` in your preferred browser.
30 | 2. You should see the text on the page itself change to read `Success!`.
31 | 3. You should see `Successfully started server on http://localhost:8080` in the terminal output.
32 |
--------------------------------------------------------------------------------
/examples/compression/true/README.md:
--------------------------------------------------------------------------------
1 | # Gzip Compression
2 |
3 | Website gzip compression makes it possible to reduce the file size of a file
4 | to roughly 30% of its original size before the files are sent to the browser.
5 |
6 | It is enabled by default.
7 |
8 | ## true
9 |
10 | **webpack.config.js**
11 |
12 | ```js
13 | module.exports = {
14 | // ...
15 | devServer: {
16 | compress: true,
17 | },
18 | };
19 | ```
20 |
21 | Usage via CLI:
22 |
23 | ```console
24 | npx webpack serve --open --compress
25 | ```
26 |
27 | ### What should happen
28 |
29 | 1. The script should open `http://localhost:8080/`.
30 | 2. Files being sent to the browser from the `webpack` bundle should be gzipped.
31 | 3. Open the console in your browser's devtools and select the _Network_ tab.
32 | 4. Find `main.js`. The response headers should contain `Content-Encoding: gzip`.
33 |
34 | ## Notes
35 |
36 | Some browsers, such as Chrome, won't show the `Content-Encoding: gzip` within
37 | the _Response Headers_. This has been documented [here](https://github.com/expressjs/compression/issues/96).
38 |
39 | To enable `Content-Encoding` for _Response Headers_ in Chrome, you can follow
40 | [this tutorial](https://www.youtube.com/watch?v=47R6uv0RKCk).
41 |
--------------------------------------------------------------------------------
/examples/hmr/only/README.md:
--------------------------------------------------------------------------------
1 | # Hot Module Reloading
2 |
3 | Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload of the page.
4 |
5 | ## only
6 |
7 | Enables Hot Module Replacement without page refresh as a fallback in case of build failures.
8 |
9 | **webpack.config.js**
10 |
11 | ```js
12 | module.exports = {
13 | // ...
14 | devServer: {
15 | hot: "only",
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```console
23 | npx webpack serve --open --hot only
24 | ```
25 |
26 | ## What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. In your editor, open `example.js` and change any part of the `innerHTML` string.
30 | 3. Open the console in your browser's devtools.
31 |
32 | In the devtools console you should see:
33 |
34 | ```
35 | [webpack-dev-server] App updated. Recompiling...
36 | [webpack-dev-server] App hot update...
37 | [HMR] Checking for updates on the server...
38 | ⚠️ Ignored an update to unaccepted module ./example.js -> ./app.js
39 | [HMR] Nothing hot Updated.
40 | [HMR] App is up to date.
41 | ```
42 |
43 | 5. Refresh the page and see the text on the page itself change to match your edits in `example.js`.
44 |
--------------------------------------------------------------------------------
/examples/general/proxy-hot-reload/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const fs = require("node:fs");
4 | // our setup function adds behind-the-scenes bits to the config that all of our
5 | // examples need
6 | const { setup } = require("../../util");
7 | const proxyConfig = require("./proxy-config");
8 |
9 | let proxyOptions = {
10 | context: "/api",
11 | target: proxyConfig.target,
12 | pathRewrite: proxyConfig.pathRewrite,
13 | changeOrigin: true,
14 | };
15 |
16 | fs.watch("./proxy-config.js", () => {
17 | delete require.cache[require.resolve("./proxy-config")];
18 | try {
19 | const newProxyConfig = require("./proxy-config");
20 |
21 | if (proxyOptions.target !== newProxyConfig.target) {
22 | console.log("Proxy target changed:", newProxyConfig.target);
23 | proxyOptions = {
24 | context: "/api",
25 | target: newProxyConfig.target,
26 | pathRewrite: newProxyConfig.pathRewrite,
27 | changeOrigin: true,
28 | };
29 | }
30 | } catch {
31 | // ignore
32 | }
33 | });
34 |
35 | module.exports = setup({
36 | context: __dirname,
37 | entry: "./app.js",
38 | devServer: {
39 | proxy: [
40 | function proxy() {
41 | return proxyOptions;
42 | },
43 | ],
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | Each example showcases a particular feature of `webpack-dev-server`. You can use
4 | these examples to learn how to use certain features, or as a means to test features
5 | when working on a Pull Request.
6 |
7 | An example should be as minimal as possible and consists of at least:
8 |
9 | - An `app.js` file - the entry point for an example app.
10 | - A `README.md` file containing information about, and how to run the example app.
11 | - A description of what should happen when running the example.
12 | - A `webpack.config.js` file containing the `webpack` configuration for the example app.
13 |
14 | ## API
15 |
16 | API examples can be found in the `api` directory. These examples demonstrate how
17 | to access and run `webpack-dev-server` directly in your application / script.
18 |
19 | ## Notes
20 |
21 | - Each example's `webpack` config is wrapped with `util.setup`; a helper function
22 | that adds plugins and configuration needed by each example to render in a consistent
23 | and visually pleasing way.
24 | - Examples' `bundle.js` and `index.html` files are compiled and served from memory.
25 | You won't actually see these files written to disk, but if you examine the `webpack`
26 | output, you should see their file indicators.
27 |
--------------------------------------------------------------------------------
/examples/client/web-socket-url/README.md:
--------------------------------------------------------------------------------
1 | # Web Socket URL Option Protocol
2 |
3 | **webpack.config.js**
4 |
5 | ```js
6 | module.exports = {
7 | // ...
8 | devServer: {
9 | host: "0.0.0.0",
10 | client: {
11 | webSocketURL: "ws://:8080",
12 | },
13 | },
14 | };
15 | ```
16 |
17 | Usage via CLI:
18 |
19 | ```console
20 | npx webpack serve --open --host 0.0.0.0 --client-web-socket-url ws://:8080
21 | ```
22 |
23 | _NOTE: replace `` with your local IP Address._
24 |
25 | In order to make the server publicly accessible the client needs to know with
26 | what host to connect to the server. If `--host 0.0.0.0` is given, the client
27 | would try to connect to `0.0.0.0`. With the `--client-web-socket-url` and related options it is possible to
28 | override this.
29 |
30 | You're now able to explicitly define the protocol used with the `client.webSocketURL` option
31 | (have a look at the config provided in `webpack.config.js`).
32 |
33 | ## What Should Happen
34 |
35 | The script should open `http://localhost:8080/` in your default browser.
36 |
37 | You should see a failed attempt to establish a connection to `/ws`
38 | via the explicitly defined `https://localhost:8080`. This fails of course since
39 | we're not hosting https.
40 |
--------------------------------------------------------------------------------
/examples/compression/false/README.md:
--------------------------------------------------------------------------------
1 | # Gzip Compression
2 |
3 | Website gzip compression makes it possible to reduce the file size of a file
4 | to roughly 30% of its original size before the files are sent to the browser.
5 |
6 | It is enabled by default. To disable it set `compress` option to `false`.
7 |
8 | ## false
9 |
10 | **webpack.config.js**
11 |
12 | ```js
13 | module.exports = {
14 | // ...
15 | devServer: {
16 | compress: false,
17 | },
18 | };
19 | ```
20 |
21 | Usage via CLI:
22 |
23 | ```console
24 | npx webpack serve --open --no-compress
25 | ```
26 |
27 | ### What should happen
28 |
29 | 1. The script should open `http://localhost:8080/`.
30 | 2. Files being sent to the browser from the `webpack` bundle should be gzipped.
31 | 3. Open the console in your browser's devtools and select the _Network_ tab.
32 | 4. Find `main.js`. The response headers should not contain `Content-Encoding: gzip`.
33 |
34 | ## Notes
35 |
36 | Some browsers, such as Chrome, won't show the `Content-Encoding: gzip` within
37 | the _Response Headers_. This has been documented [here](https://github.com/expressjs/compression/issues/96).
38 |
39 | To enable `Content-Encoding` for _Response Headers_ in Chrome, you can follow
40 | [this tutorial](https://www.youtube.com/watch?v=47R6uv0RKCk).
41 |
--------------------------------------------------------------------------------
/examples/client/trusted-types-overlay/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 | WDS ▻ <%= htmlWebpackPlugin.options.title %>
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 | webpack-dev-server
30 |
31 |
32 |
33 | <%= htmlWebpackPlugin.options.title %>
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/cli/hot-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-hot"];
5 |
6 | describe('"hot" CLI option', () => {
7 | it('should work using "--hot"', async () => {
8 | const { exitCode, stdout } = await testBin(
9 | ["--port", port, "--hot", "--stats=detailed"],
10 | {
11 | outputKillStr: /compiled successfully/,
12 | },
13 | );
14 |
15 | expect(exitCode).toBe(0);
16 | expect(stdout).toContain("webpack/hot/dev-server.js");
17 | });
18 |
19 | it('should work using "--no-hot"', async () => {
20 | const { exitCode, stdout } = await testBin(
21 | ["--port", port, "--no-hot", "--stats=detailed"],
22 | {
23 | outputKillStr: /compiled successfully/,
24 | },
25 | );
26 |
27 | expect(exitCode).toBe(0);
28 | expect(stdout).not.toContain("webpack/hot/dev-server.js");
29 | });
30 |
31 | it('should work using "--hot only"', async () => {
32 | const { exitCode, stdout } = await testBin(
33 | ["--port", port, "--hot", "only"],
34 | {
35 | outputKillStr: /compiled successfully/,
36 | },
37 | );
38 |
39 | expect(exitCode).toBe(0);
40 | expect(stdout).toContain("/hot/only-dev-server.js");
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/examples/server/https/ssl/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDXTCCAkWgAwIBAgIJALz8gD/gAt0OMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4 | aWRnaXRzIFB0eSBMdGQwHhcNMTgxMDIzMTgyMTQ5WhcNMTkxMDIzMTgyMTQ5WjBF
5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
7 | CgKCAQEAxAUVLFM+K3XDLQkBi7xt0s1Ip7JoHYDskzUDQNHjjMkUq5kvC/hf5Ei1
8 | J6qruJs3Xqg86Nl4+ed4ynUajAkRRibhp0P1SG1tgPssIK6iC7g8heYuDy9WkFuM
9 | ie0513zjSn6bMEAK5TegxYAWCbaCZX/Fw9bDniabL/zuOv4sf8J4EPhsEENnH6sU
10 | E9HxPUgQmNt1Tbd0j1Cd5PXrSTLyfVPRh0m9QhXTUHuxsse8XSn9U2swduxJTWRI
11 | NmhffYn+O7kbJGI77xYr8u58Rsf3HCMI8DTKZNvQLChvvtLJ9ckyu7Q+T8emgklS
12 | tASm3V2UtnriaK/IQEhgSdxqVRib3QIDAQABo1AwTjAdBgNVHQ4EFgQUDZBhVKdb
13 | 3BRhLIhuuE522Vsul0IwHwYDVR0jBBgwFoAUDZBhVKdb3BRhLIhuuE522Vsul0Iw
14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABh9WWZwWLgb9/DcTxL72
15 | 6pI96t4jiF79Q+pPefkaIIi0mE6yodWrTAsBQu9I6bNRaEcCSoiXkP2bqskD/UGg
16 | LwUFgSrDOAA3UjdHw3QU5g2NocduG7mcFwA40TB98sOsxsUyYlzSyWzoiQWwPYwb
17 | hek1djuWkqPXsTjlj54PTPN/SjTFmo4p5Ip6nbRf2nOREl7v0rJpGbJvXiCMYyd+
18 | Zv+j4mRjCGo8ysMR2HjCUGkYReLAgKyyz3M7i8vevJhKslyOmy6Txn4F0nPVumaU
19 | DDIy4xXPW1STWfsmSYJfYW3wa0wk+pJQ3j2cTzkPQQ8gwpvM3U9DJl43uwb37v6I
20 | 7Q==
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/examples/server/spdy/ssl/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDXTCCAkWgAwIBAgIJALz8gD/gAt0OMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4 | aWRnaXRzIFB0eSBMdGQwHhcNMTgxMDIzMTgyMTQ5WhcNMTkxMDIzMTgyMTQ5WjBF
5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
7 | CgKCAQEAxAUVLFM+K3XDLQkBi7xt0s1Ip7JoHYDskzUDQNHjjMkUq5kvC/hf5Ei1
8 | J6qruJs3Xqg86Nl4+ed4ynUajAkRRibhp0P1SG1tgPssIK6iC7g8heYuDy9WkFuM
9 | ie0513zjSn6bMEAK5TegxYAWCbaCZX/Fw9bDniabL/zuOv4sf8J4EPhsEENnH6sU
10 | E9HxPUgQmNt1Tbd0j1Cd5PXrSTLyfVPRh0m9QhXTUHuxsse8XSn9U2swduxJTWRI
11 | NmhffYn+O7kbJGI77xYr8u58Rsf3HCMI8DTKZNvQLChvvtLJ9ckyu7Q+T8emgklS
12 | tASm3V2UtnriaK/IQEhgSdxqVRib3QIDAQABo1AwTjAdBgNVHQ4EFgQUDZBhVKdb
13 | 3BRhLIhuuE522Vsul0IwHwYDVR0jBBgwFoAUDZBhVKdb3BRhLIhuuE522Vsul0Iw
14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABh9WWZwWLgb9/DcTxL72
15 | 6pI96t4jiF79Q+pPefkaIIi0mE6yodWrTAsBQu9I6bNRaEcCSoiXkP2bqskD/UGg
16 | LwUFgSrDOAA3UjdHw3QU5g2NocduG7mcFwA40TB98sOsxsUyYlzSyWzoiQWwPYwb
17 | hek1djuWkqPXsTjlj54PTPN/SjTFmo4p5Ip6nbRf2nOREl7v0rJpGbJvXiCMYyd+
18 | Zv+j4mRjCGo8ysMR2HjCUGkYReLAgKyyz3M7i8vevJhKslyOmy6Txn4F0nPVumaU
19 | DDIy4xXPW1STWfsmSYJfYW3wa0wk+pJQ3j2cTzkPQQ8gwpvM3U9DJl43uwb37v6I
20 | 7Q==
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/test/e2e/__snapshots__/mime-types.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`mimeTypes option as an object with a custom type should request file with different js mime type: console messages 1`] = `[]`;
4 |
5 | exports[`mimeTypes option as an object with a custom type should request file with different js mime type: page errors 1`] = `[]`;
6 |
7 | exports[`mimeTypes option as an object with a custom type should request file with different js mime type: response headers content-type 1`] = `"text/html; charset=utf-8"`;
8 |
9 | exports[`mimeTypes option as an object with a custom type should request file with different js mime type: response status 1`] = `200`;
10 |
11 | exports[`mimeTypes option as an object with a remapped type should request file with different js mime type: console messages 1`] = `[]`;
12 |
13 | exports[`mimeTypes option as an object with a remapped type should request file with different js mime type: page errors 1`] = `[]`;
14 |
15 | exports[`mimeTypes option as an object with a remapped type should request file with different js mime type: response headers content-type 1`] = `"text/plain; charset=utf-8"`;
16 |
17 | exports[`mimeTypes option as an object with a remapped type should request file with different js mime type: response status 1`] = `200`;
18 |
--------------------------------------------------------------------------------
/test/fixtures/https-certificate/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDXTCCAkWgAwIBAgIJALz8gD/gAt0OMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4 | aWRnaXRzIFB0eSBMdGQwHhcNMTgxMDIzMTgyMTQ5WhcNMTkxMDIzMTgyMTQ5WjBF
5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
7 | CgKCAQEAxAUVLFM+K3XDLQkBi7xt0s1Ip7JoHYDskzUDQNHjjMkUq5kvC/hf5Ei1
8 | J6qruJs3Xqg86Nl4+ed4ynUajAkRRibhp0P1SG1tgPssIK6iC7g8heYuDy9WkFuM
9 | ie0513zjSn6bMEAK5TegxYAWCbaCZX/Fw9bDniabL/zuOv4sf8J4EPhsEENnH6sU
10 | E9HxPUgQmNt1Tbd0j1Cd5PXrSTLyfVPRh0m9QhXTUHuxsse8XSn9U2swduxJTWRI
11 | NmhffYn+O7kbJGI77xYr8u58Rsf3HCMI8DTKZNvQLChvvtLJ9ckyu7Q+T8emgklS
12 | tASm3V2UtnriaK/IQEhgSdxqVRib3QIDAQABo1AwTjAdBgNVHQ4EFgQUDZBhVKdb
13 | 3BRhLIhuuE522Vsul0IwHwYDVR0jBBgwFoAUDZBhVKdb3BRhLIhuuE522Vsul0Iw
14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABh9WWZwWLgb9/DcTxL72
15 | 6pI96t4jiF79Q+pPefkaIIi0mE6yodWrTAsBQu9I6bNRaEcCSoiXkP2bqskD/UGg
16 | LwUFgSrDOAA3UjdHw3QU5g2NocduG7mcFwA40TB98sOsxsUyYlzSyWzoiQWwPYwb
17 | hek1djuWkqPXsTjlj54PTPN/SjTFmo4p5Ip6nbRf2nOREl7v0rJpGbJvXiCMYyd+
18 | Zv+j4mRjCGo8ysMR2HjCUGkYReLAgKyyz3M7i8vevJhKslyOmy6Txn4F0nPVumaU
19 | DDIy4xXPW1STWfsmSYJfYW3wa0wk+pJQ3j2cTzkPQQ8gwpvM3U9DJl43uwb37v6I
20 | 7Q==
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/test/e2e/__snapshots__/client.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`client option configure client entry should disable client entry: console messages 1`] = `[]`;
4 |
5 | exports[`client option configure client entry should disable client entry: page errors 1`] = `[]`;
6 |
7 | exports[`client option configure client entry should disable client entry: response status 1`] = `200`;
8 |
9 | exports[`client option default behaviour responds with a 200 status code for /ws path: console messages 1`] = `[]`;
10 |
11 | exports[`client option default behaviour responds with a 200 status code for /ws path: page errors 1`] = `[]`;
12 |
13 | exports[`client option default behaviour responds with a 200 status code for /ws path: response status 1`] = `200`;
14 |
15 | exports[`client option override client entry should disable client entry: response status 1`] = `200`;
16 |
17 | exports[`client option should respect path option responds with a 200 status code for /foo/test/bar path: console messages 1`] = `[]`;
18 |
19 | exports[`client option should respect path option responds with a 200 status code for /foo/test/bar path: page errors 1`] = `[]`;
20 |
21 | exports[`client option should respect path option responds with a 200 status code for /foo/test/bar path: response status 1`] = `200`;
22 |
--------------------------------------------------------------------------------
/examples/dev-middleware/README.md:
--------------------------------------------------------------------------------
1 | # devMiddleware option
2 |
3 | Provide options to [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) which handles webpack assets.
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | devMiddleware: {
12 | index: true,
13 | headers: {
14 | "X-Custom-Header": "yes",
15 | },
16 | },
17 | },
18 | };
19 | ```
20 |
21 | To run this example use the following command:
22 |
23 | ```console
24 | npx webpack serve --open
25 | ```
26 |
27 | ## What should happen
28 |
29 | 1. The script should open `http://localhost:8080/`.
30 | 2. You should see the text on the page itself change to read `Success!`.
31 | 3. Open the console in your browser's devtools and select the _Network_ tab.
32 | 4. Find `main.js`. The response headers should contain `X-Custom-Header: yes`.
33 |
34 | Now update `webpack.config.js` with [`index: false`](https://github.com/webpack/webpack-dev-middleware#index), this will tell the server to not respond to requests to the root URL.
35 |
36 | Now close and restart the server with:
37 |
38 | ```console
39 | npx webpack serve --open
40 | ```
41 |
42 | ## What should happen
43 |
44 | 1. The script should open `http://localhost:8080/`.
45 | 2. You should see the `Cannot GET /` text on the page.
46 |
--------------------------------------------------------------------------------
/examples/general/config-array/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // our setup function adds behind-the-scenes bits to the config that all of our
4 | // examples need
5 | const { setup } = require("../../util");
6 |
7 | const moduleRuleForPNG = {
8 | test: /\.png$/,
9 | type: "asset/resource",
10 | generator: {
11 | filename: "images/[hash][ext][query]",
12 | },
13 | };
14 |
15 | module.exports = [
16 | setup({
17 | context: __dirname,
18 | entry: "./app.js",
19 | module: {
20 | rules: [
21 | {
22 | test: /\.less$/,
23 | use: ["style-loader", "css-loader", "less-loader"],
24 | },
25 | {
26 | ...moduleRuleForPNG,
27 | },
28 | ],
29 | },
30 | }),
31 | {
32 | context: __dirname,
33 | entry: "./app.js",
34 | output: {
35 | filename: "bundle2.js",
36 | },
37 | mode: "development",
38 | module: {
39 | rules: [
40 | {
41 | test: /\.less$/,
42 | use: ["style-loader", "css-loader", "less-loader"],
43 | },
44 | {
45 | test: /\.png$/,
46 | type: "asset/resource",
47 | generator: {
48 | filename: "images/[hash][ext][query]",
49 | },
50 | },
51 | ],
52 | },
53 | optimization: {
54 | minimize: true,
55 | },
56 | },
57 | ];
58 |
--------------------------------------------------------------------------------
/examples/client/reconnect/number/README.md:
--------------------------------------------------------------------------------
1 | # client.reconnect Option
2 |
3 | ## number
4 |
5 | Tells dev-server the number of times it should try to reconnect the client.
6 |
7 | **webpack.config.js**
8 |
9 | ```js
10 | module.exports = {
11 | // ...
12 | devServer: {
13 | client: {
14 | reconnect: 2,
15 | },
16 | },
17 | };
18 | ```
19 |
20 | Usage via CLI:
21 |
22 | ```shell
23 | npx webpack serve --open --client-reconnect 2
24 | ```
25 |
26 | ## What Should Happen
27 |
28 | 1. The script should open `http://localhost:8080/` in your default browser.
29 | 2. Open the console tab in your browser's devtools.
30 | 3. Now close the server with `Ctrl+C` to disconnect the client.
31 |
32 | In the devtools console you should see that webpack-dev-server tried to reconnect the client 2 times:
33 |
34 | ```
35 | [webpack-dev-server] Hot Module Replacement enabled.
36 | [webpack-dev-server] Live Reloading enabled.
37 | [webpack-dev-server] Disconnected!
38 | [webpack-dev-server] Trying to reconnect...
39 | WebSocket connection to 'ws://127.0.0.1:8163/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
40 | [webpack-dev-server] JSHandle@object
41 | [webpack-dev-server] Trying to reconnect...
42 | WebSocket connection to 'ws://127.0.0.1:8163/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
43 | [webpack-dev-server] JSHandle@object
44 | ```
45 |
--------------------------------------------------------------------------------
/test/client/utils/log.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @jest-environment jsdom
3 | */
4 |
5 | "use strict";
6 |
7 | describe("'log' function", () => {
8 | let logMock;
9 | let setLogLevel;
10 |
11 | beforeEach(() => {
12 | jest.setMock("webpack/lib/logging/runtime", {
13 | getLogger: jest.fn(),
14 | configureDefaultLogger: jest.fn(),
15 | });
16 | logMock = require("webpack/lib/logging/runtime");
17 |
18 | setLogLevel = require("../../../client-src/utils/log").setLogLevel;
19 | });
20 |
21 | afterEach(() => {
22 | logMock.getLogger.mockClear();
23 | logMock.configureDefaultLogger.mockClear();
24 | });
25 |
26 | it("should set info as the default level and create logger", () => {
27 | const { getLogger } = logMock;
28 | const { configureDefaultLogger } = logMock;
29 |
30 | expect(configureDefaultLogger).toHaveBeenCalled();
31 | expect(configureDefaultLogger.mock.calls[0][0]).toEqual({
32 | level: "info",
33 | });
34 |
35 | expect(getLogger).toHaveBeenCalled();
36 | expect(getLogger.mock.calls[0][0]).toBe("webpack-dev-server");
37 | });
38 |
39 | it("should set log level via setLogLevel", () => {
40 | for (const level of ["none", "error", "warn", "info", "log", "verbose"]) {
41 | setLogLevel(level);
42 | }
43 |
44 | expect(logMock.configureDefaultLogger.mock.calls).toMatchSnapshot();
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/test/cli/allowedHosts-option.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { testBin } = require("../helpers/test-bin");
4 | const port = require("../ports-map")["cli-allowed-hosts"];
5 |
6 | describe('"allowedHosts" CLI option', () => {
7 | it('should work using "--allowed-hosts auto"', async () => {
8 | const { exitCode } = await testBin([
9 | "--port",
10 | port,
11 | "--allowed-hosts",
12 | "auto",
13 | ]);
14 |
15 | expect(exitCode).toBe(0);
16 | });
17 |
18 | it('should work using "--allowed-hosts all"', async () => {
19 | const { exitCode } = await testBin([
20 | "--port",
21 | port,
22 | "--allowed-hosts",
23 | "all",
24 | ]);
25 |
26 | expect(exitCode).toBe(0);
27 | });
28 |
29 | it('should work using "--allowed-hosts testhouse.com"', async () => {
30 | const { exitCode } = await testBin([
31 | "--port",
32 | port,
33 | "--allowed-hosts",
34 | "testhouse.com",
35 | ]);
36 |
37 | expect(exitCode).toBe(0);
38 | });
39 |
40 | it('should work using "--allowed-hosts testhost.com --allowed-hosts testhost1.com"', async () => {
41 | const { exitCode } = await testBin([
42 | "--port",
43 | port,
44 | "--allowed-hosts",
45 | "testhost.com",
46 | "--allowed-hosts",
47 | "testhost1.com",
48 | ]);
49 |
50 | expect(exitCode).toBe(0);
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/test/fixtures/multi-public-path-config/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const path = require("path");
4 |
5 | const moduleRuleForHTML = {
6 | test: /\.html$/,
7 | type: "asset/resource",
8 | generator: {
9 | filename: "path/to/file.html",
10 | },
11 | };
12 |
13 | module.exports = [
14 | {
15 | mode: "development",
16 | context: __dirname,
17 | stats: "none",
18 | entry: "./foo.js",
19 | output: {
20 | path: __dirname,
21 | filename: "foo.js",
22 | publicPath: "/bundle1/",
23 | },
24 | infrastructureLogging: {
25 | level: "warn",
26 | },
27 | module: {
28 | rules: [
29 | {
30 | ...moduleRuleForHTML,
31 | },
32 | ],
33 | },
34 | },
35 | {
36 | mode: "development",
37 | context: __dirname,
38 | stats: "none",
39 | entry: "./bar.js",
40 | output: {
41 | path: path.join(__dirname, "named"),
42 | filename: "bar.js",
43 | publicPath: "/bundle2/",
44 | },
45 | name: "named",
46 | infrastructureLogging: {
47 | level: "warn",
48 | },
49 | },
50 | {
51 | mode: "development",
52 | context: __dirname,
53 | entry: "./bar.js",
54 | output: {
55 | path: path.join(__dirname, "dist"),
56 | filename: "bar.js",
57 | publicPath: "auto",
58 | },
59 | name: "other",
60 | stats: false,
61 | },
62 | ];
63 |
--------------------------------------------------------------------------------
/test/e2e/__snapshots__/on-listening.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`onListening option should handle GET request to /listening/some/path route: console messages 1`] = `[]`;
4 |
5 | exports[`onListening option should handle GET request to /listening/some/path route: page errors 1`] = `[]`;
6 |
7 | exports[`onListening option should handle GET request to /listening/some/path route: response headers content-type 1`] = `"text/html; charset=utf-8"`;
8 |
9 | exports[`onListening option should handle GET request to /listening/some/path route: response status 1`] = `200`;
10 |
11 | exports[`onListening option should handle GET request to /listening/some/path route: response text 1`] = `"listening"`;
12 |
13 | exports[`onListening option should handle POST request to /listening/some/path route: console messages 1`] = `[]`;
14 |
15 | exports[`onListening option should handle POST request to /listening/some/path route: page errors 1`] = `[]`;
16 |
17 | exports[`onListening option should handle POST request to /listening/some/path route: response headers content-type 1`] = `"text/html; charset=utf-8"`;
18 |
19 | exports[`onListening option should handle POST request to /listening/some/path route: response status 1`] = `200`;
20 |
21 | exports[`onListening option should handle POST request to /listening/some/path route: response text 1`] = `"listening POST"`;
22 |
--------------------------------------------------------------------------------
/examples/watch-static/README.md:
--------------------------------------------------------------------------------
1 | # Static
2 |
3 | ## Watching a single directory
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | static: ["assets"],
12 | },
13 | };
14 | ```
15 |
16 | Usage via CLI:
17 |
18 | ```console
19 | npx webpack serve --static assets --open
20 | ```
21 |
22 | ### What Should Happen
23 |
24 | 1. The script should open `http://localhost:8080/` in your default browser.
25 | 2. You should see the text on the page itself change to read `Success!`.
26 | 3. In your editor, edit `assets/index.html` and save your changes.
27 | 4. The app should reload in the browser.
28 |
29 | ## Watching an Array of Directories
30 |
31 | ```js
32 | // webpack.conf.js
33 | module.exports = {
34 | /* ... */
35 | devServer: {
36 | static: ["assets", "css"],
37 | },
38 | };
39 | ```
40 |
41 | ```console
42 | npx webpack serve --open
43 | ```
44 |
45 | or via CLI only:
46 |
47 | ```console
48 | npx webpack serve --static assets --static css --open
49 | ```
50 |
51 | ### What Should Happen
52 |
53 | 1. The script should open `http://localhost:8080/` in your default browser.
54 | 2. You should see the text on the page itself change to read `Success!`.
55 | 3. In your editor, edit `assets/index.html` and save your changes.
56 | 4. The app should reload.
57 | 5. In your editor, edit `css/styles.css` and save your changes.
58 | 6. The app should reload.
59 |
--------------------------------------------------------------------------------
/test/e2e/__snapshots__/setup-exit-signals.test.js.snap.webpack5:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2 |
3 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGINT: console messages 1`] = `
4 | [
5 | "[webpack-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay enabled.",
6 | "[HMR] Waiting for update signal from WDS...",
7 | "Hey.",
8 | ]
9 | `;
10 |
11 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGINT: page errors 1`] = `[]`;
12 |
13 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGINT: response status 1`] = `200`;
14 |
15 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGTERM: console messages 1`] = `
16 | [
17 | "[webpack-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay enabled.",
18 | "[HMR] Waiting for update signal from WDS...",
19 | "Hey.",
20 | ]
21 | `;
22 |
23 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGTERM: page errors 1`] = `[]`;
24 |
25 | exports[`setupExitSignals option should handle 'SIGINT' and 'SIGTERM' signals should close and exit on SIGTERM: response status 1`] = `200`;
26 |
--------------------------------------------------------------------------------
/examples/setup-middlewares/README.md:
--------------------------------------------------------------------------------
1 | # setupMiddlewares
2 |
3 | Provides the ability to execute a custom function and apply custom middleware(s).
4 |
5 | **webpack.config.js**
6 |
7 | ```js
8 | module.exports = {
9 | // ...
10 | devServer: {
11 | setupMiddlewares: (middlewares, devServer) => {
12 | if (!devServer) {
13 | throw new Error("webpack-dev-server is not defined");
14 | }
15 |
16 | devServer.app.get("/setup-middleware/some/path", (_, response) => {
17 | response.send("setup-middlewares option GET");
18 | });
19 |
20 | middlewares.push({
21 | name: "hello-world-test-one",
22 | // `path` is optional
23 | path: "/foo/bar",
24 | middleware: (req, res) => {
25 | res.send("Foo Bar!");
26 | },
27 | });
28 |
29 | middlewares.push((req, res) => {
30 | res.send("Hello World!");
31 | });
32 |
33 | return middlewares;
34 | },
35 | },
36 | };
37 | ```
38 |
39 | To run this example use the following command:
40 |
41 | ```console
42 | npx webpack serve --open
43 | ```
44 |
45 | ## What Should Happen
46 |
47 | 1. The script should open `http://localhost:8080/` in your default browser.
48 | 2. You should see the text on the page itself change to read `Success!`.
49 | 3. Go to `http://localhost:8080/setup-middleware/some/path`, you should see the text on the page itself change to read `setup-middlewares option GET`.
50 |
--------------------------------------------------------------------------------
/examples/api/stop/README.md:
--------------------------------------------------------------------------------
1 | # API: stop
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also
4 | choose to stop a server via the API.
5 |
6 | This example demonstrates using `stop` method. It instructs `webpack-dev-server` instance to stop the server.
7 |
8 | ```js
9 | const Webpack = require("webpack");
10 | const WebpackDevServer = require("webpack-dev-server");
11 | const webpackConfig = require("./webpack.config");
12 |
13 | const compiler = Webpack(webpackConfig);
14 | const devServerOptions = { ...webpackConfig.devServer };
15 | const server = new WebpackDevServer(devServerOptions, compiler);
16 |
17 | const runServer = async () => {
18 | console.log("Starting server...");
19 | await server.start();
20 | };
21 |
22 | const stopServer = async () => {
23 | console.log("Stopping server...");
24 | await server.stop();
25 | };
26 |
27 | runServer();
28 |
29 | setTimeout(stopServer, 5000);
30 | ```
31 |
32 | Use the following command to run this example:
33 |
34 | ```console
35 | node server.js
36 | ```
37 |
38 | ## What Should Happen
39 |
40 | 1. The script should start the server and open `http://localhost:8080/` in your default browser.
41 | 2. You should see the text on the page itself change to read `Success! Reload the page after 5 seconds.`.
42 | 3. After 5 seconds, the script will stop the server. Confirm by reloading the browser page after 5 seconds.
43 | 4. You should see `Stopping server...` in your terminal output.
44 |
--------------------------------------------------------------------------------
/test/fixtures/lazy-compilation-single-entry/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const HTMLContent = `
4 |
5 |
6 |
7 |
8 | test
9 |
10 |
11 |
12 |
13 | `;
14 |
15 | module.exports = {
16 | devtool: false,
17 | mode: "development",
18 | context: __dirname,
19 | stats: "none",
20 | entry: "./entry.js",
21 | output: {
22 | path: "/",
23 | },
24 | experiments: {
25 | lazyCompilation: true,
26 | },
27 | infrastructureLogging: {
28 | level: "info",
29 | stream: {
30 | write: () => {},
31 | },
32 | },
33 | plugins: [
34 | {
35 | apply(compiler) {
36 | const pluginName = "html-generator-plugin-test";
37 | const filename = "test.html";
38 |
39 | compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
40 | const { RawSource } = compiler.webpack.sources;
41 |
42 | compilation.hooks.processAssets.tap(
43 | {
44 | name: pluginName,
45 | stage:
46 | compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
47 | },
48 | () => {
49 | const source = new RawSource(HTMLContent);
50 |
51 | compilation.emitAsset(filename, source);
52 | },
53 | );
54 | });
55 | },
56 | },
57 | ],
58 | };
59 |
--------------------------------------------------------------------------------
/examples/client/overlay/app.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const createButton = require("./create-button");
4 |
5 | /**
6 | * @param {string} errorMessage
7 | */
8 | function unsafeOperation(errorMessage) {
9 | throw new Error(errorMessage);
10 | }
11 |
12 | const target = document.querySelector("#target");
13 |
14 | target.insertAdjacentElement(
15 | "afterend",
16 | createButton("Click to throw ignored promise rejection", () => {
17 | const abortController = new AbortController();
18 |
19 | fetch("https://google.com", {
20 | signal: abortController.signal,
21 | mode: "no-cors",
22 | });
23 |
24 | setTimeout(() => abortController.abort(), 100);
25 | }),
26 | );
27 |
28 | target.insertAdjacentElement(
29 | "afterend",
30 | createButton("Click to throw unhandled promise rejection", () => {
31 | setTimeout(() => Promise.reject(new Error("Async error")), 100);
32 | }),
33 | );
34 |
35 | target.insertAdjacentElement(
36 | "afterend",
37 | createButton("Click to throw ignored error", () => {
38 | unsafeOperation("something something");
39 | }),
40 | );
41 |
42 | target.insertAdjacentElement(
43 | "afterend",
44 | createButton("Click to throw error", () => {
45 | unsafeOperation("Error message thrown from JS");
46 | }),
47 | );
48 |
49 | // eslint-disable-next-line import/no-unresolved, import/extensions
50 | const invalid = require("./invalid.js");
51 |
52 | console.log(invalid);
53 | target.classList.add("pass");
54 | target.innerHTML = "Success!";
55 |
--------------------------------------------------------------------------------
/examples/api/stop-callback/README.md:
--------------------------------------------------------------------------------
1 | # API: stopCallback(callback)
2 |
3 | While it's recommended to run `webpack-dev-server` via the CLI, you may also choose to start a server via the API.
4 |
5 | This example demonstrates using `stopCallback(callback)` method. It instructs `webpack-dev-server` instance to stop the server and then run the callback function.
6 |
7 | ```js
8 | const Webpack = require("webpack");
9 | const WebpackDevServer = require("webpack-dev-server");
10 | const webpackConfig = require("./webpack.config");
11 |
12 | const compiler = Webpack(webpackConfig);
13 | const devServerOptions = { ...webpackConfig.devServer };
14 | const server = new WebpackDevServer(devServerOptions, compiler);
15 |
16 | server.startCallback(() => {
17 | console.log("Successfully started server on http://localhost:8080");
18 | });
19 |
20 | const stopServer = () =>
21 | server.stopCallback(() => {
22 | console.log("Server stopped.");
23 | });
24 |
25 | setTimeout(stopServer, 5000);
26 | ```
27 |
28 | Use the following command to run this example:
29 |
30 | ```console
31 | node server.js
32 | ```
33 |
34 | ## What Should Happen
35 |
36 | 1. The script should start the server and open `http://localhost:8080/` in your default browser.
37 | 2. You should see the text on the page itself change to read `Success! Reload the page after 5 seconds.`.
38 | 3. After 5 seconds, the script will stop the server. Confirm by reloading the browser page after 5 seconds.
39 | 4. You should see `Server stopped.` in your terminal output.
40 |
--------------------------------------------------------------------------------