From 6eac902a2fe02edbac65ea2490edc30c8d8f054e Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Sat, 21 Mar 2026 13:24:10 +0300 Subject: [PATCH 1/3] fix(init): resolve localhost IP family for allowedHosts in devServer config - Windows 10/11 can prioritize IPv6, making localhost resolve to ::1 instead of 127.0.0.1 - This causes HMR WebSocket connections to silently fail when the bound address doesn't match - Templates now resolve the OS-preferred IP family at generation time using dns.lookup() - Resolved value is baked into allowedHosts (127.0.0.1 or ::1) - If resolution fails, allowedHosts is omitted and webpack-dev-server falls back to its own 'auto' behavior - Updated templates: default, vue, react, svelte - Updated snapshots --- .../templates/init/default/webpack.config.js.tpl | 15 ++++++++++++++- .../templates/init/react/webpack.config.js.tpl | 15 ++++++++++++++- .../templates/init/svelte/webpack.config.js.tpl | 15 ++++++++++++++- .../templates/init/vue/webpack.config.js.tpl | 15 ++++++++++++++- .../init/__snapshots__/init.test.js.snap.webpack5 | 9 +++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl index 9a08a008cde..a590fd86766 100644 --- a/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl @@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> +<% const { execFileSync } = await import("node:child_process"); +let host; +try { + const family = execFileSync(process.execPath, [ + "--input-type=module", + "--eval", + `import dns from "node:dns/promises"; + const { family } = await dns.lookup("localhost"); + process.stdout.write(String(family));` + ], { encoding: "utf8", timeout: 3000 }).trim(); + host = family === "6" ? "::1" : "127.0.0.1"; +} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -27,7 +39,8 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost", + host: "localhost",<% if (host) { %> + allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl index 512f4dc6b0a..64080bab489 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl @@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> +<% const { execFileSync } = await import("node:child_process") +let host; +try { + const family = execFileSync(process.execPath, [ + "--input-type=module", + "--eval", + `import dns from "node:dns/promises"; + const { family } = await dns.lookup("localhost"); + process.stdout.write(String(family));` + ], { encoding: "utf8", timeout: 3000 }).trim(); + host = family === "6" ? "::1" : "127.0.0.1"; +} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -27,7 +39,8 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost", + host: "localhost",<% if (host) { %> + allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl index ef0fc202556..da1d6752a3e 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl @@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> +<% const { execFileSync } = await import("node:child_process") +let host; +try { + const family = execFileSync(process.execPath, [ + "--input-type=module", + "--eval", + `import dns from "node:dns/promises"; + const { family } = await dns.lookup("localhost"); + process.stdout.write(String(family));` + ], { encoding: "utf8", timeout: 3000 }).trim(); + host = family === "6" ? "::1" : "127.0.0.1"; +} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -27,7 +39,8 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost", + host: "localhost",<% if (host) { %> + allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl index 0d954a2ff67..f9a0958808d 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl @@ -6,6 +6,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> +<% const { execFileSync } = await import("node:child_process") +let host; +try { + const family = execFileSync(process.execPath, [ + "--input-type=module", + "--eval", + `import dns from "node:dns/promises"; + const { family } = await dns.lookup("localhost"); + process.stdout.write(String(family));` + ], { encoding: "utf8", timeout: 3000 }).trim(); + host = family === "6" ? "::1" : "127.0.0.1"; +} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -28,7 +40,8 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost", + host: "localhost",<% if (host) { %> + allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [ new VueLoaderPlugin(),<% if (htmlWebpackPlugin) { %> diff --git a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 index b4073ebfa32..5d70fc69435 100644 --- a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 +++ b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 @@ -86,6 +86,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ // Add your plugins here @@ -394,6 +395,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -481,6 +483,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -566,6 +569,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -653,6 +657,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -740,6 +745,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -891,6 +897,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -1010,6 +1017,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -1221,6 +1229,7 @@ const config = { devServer: { open: true, host: "localhost", + allowedHosts: ["::1"], }, plugins: [ new VueLoaderPlugin(), From 14d614c7c2efd0d504d2eeb78336bb149255c8b0 Mon Sep 17 00:00:00 2001 From: ThierryRakotomanana Date: Tue, 24 Mar 2026 23:06:28 +0300 Subject: [PATCH 2/3] fix(init): set the config to the default host for fixing CORS error --- .../init/default/webpack.config.js.tpl | 14 -------------- .../templates/init/react/webpack.config.js.tpl | 14 -------------- .../init/svelte/webpack.config.js.tpl | 14 -------------- .../templates/init/vue/webpack.config.js.tpl | 14 -------------- .../__snapshots__/init.test.js.snap.webpack5 | 18 ------------------ 5 files changed, 74 deletions(-) diff --git a/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl index a590fd86766..e9620d86333 100644 --- a/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/default/webpack.config.js.tpl @@ -5,18 +5,6 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> -<% const { execFileSync } = await import("node:child_process"); -let host; -try { - const family = execFileSync(process.execPath, [ - "--input-type=module", - "--eval", - `import dns from "node:dns/promises"; - const { family } = await dns.lookup("localhost"); - process.stdout.write(String(family));` - ], { encoding: "utf8", timeout: 3000 }).trim(); - host = family === "6" ? "::1" : "127.0.0.1"; -} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -39,8 +27,6 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost",<% if (host) { %> - allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl index 64080bab489..cf6ce755bf9 100644 --- a/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/react/webpack.config.js.tpl @@ -5,18 +5,6 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> -<% const { execFileSync } = await import("node:child_process") -let host; -try { - const family = execFileSync(process.execPath, [ - "--input-type=module", - "--eval", - `import dns from "node:dns/promises"; - const { family } = await dns.lookup("localhost"); - process.stdout.write(String(family));` - ], { encoding: "utf8", timeout: 3000 }).trim(); - host = family === "6" ? "::1" : "127.0.0.1"; -} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -39,8 +27,6 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost",<% if (host) { %> - allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl index da1d6752a3e..86bd7bdecbe 100644 --- a/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl @@ -5,18 +5,6 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> -<% const { execFileSync } = await import("node:child_process") -let host; -try { - const family = execFileSync(process.execPath, [ - "--input-type=module", - "--eval", - `import dns from "node:dns/promises"; - const { family } = await dns.lookup("localhost"); - process.stdout.write(String(family));` - ], { encoding: "utf8", timeout: 3000 }).trim(); - host = family === "6" ? "::1" : "127.0.0.1"; -} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -39,8 +27,6 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost",<% if (host) { %> - allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [<% if (htmlWebpackPlugin) { %> new HtmlWebpackPlugin({ diff --git a/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl b/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl index f9a0958808d..d4cdf176634 100644 --- a/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl +++ b/packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl @@ -6,18 +6,6 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %> import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %> import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %> import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %> -<% const { execFileSync } = await import("node:child_process") -let host; -try { - const family = execFileSync(process.execPath, [ - "--input-type=module", - "--eval", - `import dns from "node:dns/promises"; - const { family } = await dns.lookup("localhost"); - process.stdout.write(String(family));` - ], { encoding: "utf8", timeout: 3000 }).trim(); - host = family === "6" ? "::1" : "127.0.0.1"; -} catch { host = null; } %> const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -40,8 +28,6 @@ const config = { },<% if (devServer) { %> devServer: { open: true, - host: "localhost",<% if (host) { %> - allowedHosts: ["<%= host %>"],<% } %> },<% } %> plugins: [ new VueLoaderPlugin(),<% if (htmlWebpackPlugin) { %> diff --git a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 index 5d70fc69435..e931c415a9a 100644 --- a/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 +++ b/test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5 @@ -85,8 +85,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ // Add your plugins here @@ -394,8 +392,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -482,8 +478,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -568,8 +562,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -656,8 +648,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -744,8 +734,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -896,8 +884,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -1016,8 +1002,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new HtmlWebpackPlugin({ @@ -1228,8 +1212,6 @@ const config = { }, devServer: { open: true, - host: "localhost", - allowedHosts: ["::1"], }, plugins: [ new VueLoaderPlugin(), From 2c52d57562520c10bff97f629293c70e0aa2a332 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Tue, 24 Mar 2026 23:44:26 +0300 Subject: [PATCH 3/3] Create orange-brooms-admire.md --- .changeset/orange-brooms-admire.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/orange-brooms-admire.md diff --git a/.changeset/orange-brooms-admire.md b/.changeset/orange-brooms-admire.md new file mode 100644 index 00000000000..075864c9ecf --- /dev/null +++ b/.changeset/orange-brooms-admire.md @@ -0,0 +1,5 @@ +--- +"create-webpack-app": patch +--- + +Use default logic to determine the host for webpack-dev-server.