Skip to content

Commit 6eac902

Browse files
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
1 parent c76ab1c commit 6eac902

File tree

5 files changed

+65
-4
lines changed

5 files changed

+65
-4
lines changed

packages/create-webpack-app/templates/init/default/webpack.config.js.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %>
55
import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %>
66
import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %>
77
import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %>
8+
<% const { execFileSync } = await import("node:child_process");
9+
let host;
10+
try {
11+
const family = execFileSync(process.execPath, [
12+
"--input-type=module",
13+
"--eval",
14+
`import dns from "node:dns/promises";
15+
const { family } = await dns.lookup("localhost");
16+
process.stdout.write(String(family));`
17+
], { encoding: "utf8", timeout: 3000 }).trim();
18+
host = family === "6" ? "::1" : "127.0.0.1";
19+
} catch { host = null; } %>
820

921
const __filename = fileURLToPath(import.meta.url);
1022
const __dirname = path.dirname(__filename);
@@ -27,7 +39,8 @@ const config = {
2739
},<% if (devServer) { %>
2840
devServer: {
2941
open: true,
30-
host: "localhost",
42+
host: "localhost",<% if (host) { %>
43+
allowedHosts: ["<%= host %>"],<% } %>
3144
},<% } %>
3245
plugins: [<% if (htmlWebpackPlugin) { %>
3346
new HtmlWebpackPlugin({

packages/create-webpack-app/templates/init/react/webpack.config.js.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %>
55
import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %>
66
import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %>
77
import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %>
8+
<% const { execFileSync } = await import("node:child_process")
9+
let host;
10+
try {
11+
const family = execFileSync(process.execPath, [
12+
"--input-type=module",
13+
"--eval",
14+
`import dns from "node:dns/promises";
15+
const { family } = await dns.lookup("localhost");
16+
process.stdout.write(String(family));`
17+
], { encoding: "utf8", timeout: 3000 }).trim();
18+
host = family === "6" ? "::1" : "127.0.0.1";
19+
} catch { host = null; } %>
820

921
const __filename = fileURLToPath(import.meta.url);
1022
const __dirname = path.dirname(__filename);
@@ -27,7 +39,8 @@ const config = {
2739
},<% if (devServer) { %>
2840
devServer: {
2941
open: true,
30-
host: "localhost",
42+
host: "localhost",<% if (host) { %>
43+
allowedHosts: ["<%= host %>"],<% } %>
3144
},<% } %>
3245
plugins: [<% if (htmlWebpackPlugin) { %>
3346
new HtmlWebpackPlugin({

packages/create-webpack-app/templates/init/svelte/webpack.config.js.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %>
55
import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %>
66
import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %>
77
import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %>
8+
<% const { execFileSync } = await import("node:child_process")
9+
let host;
10+
try {
11+
const family = execFileSync(process.execPath, [
12+
"--input-type=module",
13+
"--eval",
14+
`import dns from "node:dns/promises";
15+
const { family } = await dns.lookup("localhost");
16+
process.stdout.write(String(family));`
17+
], { encoding: "utf8", timeout: 3000 }).trim();
18+
host = family === "6" ? "::1" : "127.0.0.1";
19+
} catch { host = null; } %>
820

921
const __filename = fileURLToPath(import.meta.url);
1022
const __dirname = path.dirname(__filename);
@@ -27,7 +39,8 @@ const config = {
2739
},<% if (devServer) { %>
2840
devServer: {
2941
open: true,
30-
host: "localhost",
42+
host: "localhost",<% if (host) { %>
43+
allowedHosts: ["<%= host %>"],<% } %>
3144
},<% } %>
3245
plugins: [<% if (htmlWebpackPlugin) { %>
3346
new HtmlWebpackPlugin({

packages/create-webpack-app/templates/init/vue/webpack.config.js.tpl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ import { fileURLToPath } from "node:url";<% if (htmlWebpackPlugin) { %>
66
import HtmlWebpackPlugin from "html-webpack-plugin";<% } %><% if (extractPlugin !== "No") { %>
77
import MiniCssExtractPlugin from "mini-css-extract-plugin";<% } %><% if (workboxWebpackPlugin) { %>
88
import WorkboxWebpackPlugin from "workbox-webpack-plugin";<% } %>
9+
<% const { execFileSync } = await import("node:child_process")
10+
let host;
11+
try {
12+
const family = execFileSync(process.execPath, [
13+
"--input-type=module",
14+
"--eval",
15+
`import dns from "node:dns/promises";
16+
const { family } = await dns.lookup("localhost");
17+
process.stdout.write(String(family));`
18+
], { encoding: "utf8", timeout: 3000 }).trim();
19+
host = family === "6" ? "::1" : "127.0.0.1";
20+
} catch { host = null; } %>
921

1022
const __filename = fileURLToPath(import.meta.url);
1123
const __dirname = path.dirname(__filename);
@@ -28,7 +40,8 @@ const config = {
2840
},<% if (devServer) { %>
2941
devServer: {
3042
open: true,
31-
host: "localhost",
43+
host: "localhost",<% if (host) { %>
44+
allowedHosts: ["<%= host %>"],<% } %>
3245
},<% } %>
3346
plugins: [
3447
new VueLoaderPlugin(),<% if (htmlWebpackPlugin) { %>

test/create-webpack-app/init/__snapshots__/init.test.js.snap.webpack5

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ const config = {
8686
devServer: {
8787
open: true,
8888
host: "localhost",
89+
allowedHosts: ["::1"],
8990
},
9091
plugins: [
9192
// Add your plugins here
@@ -394,6 +395,7 @@ const config = {
394395
devServer: {
395396
open: true,
396397
host: "localhost",
398+
allowedHosts: ["::1"],
397399
},
398400
plugins: [
399401
new HtmlWebpackPlugin({
@@ -481,6 +483,7 @@ const config = {
481483
devServer: {
482484
open: true,
483485
host: "localhost",
486+
allowedHosts: ["::1"],
484487
},
485488
plugins: [
486489
new HtmlWebpackPlugin({
@@ -566,6 +569,7 @@ const config = {
566569
devServer: {
567570
open: true,
568571
host: "localhost",
572+
allowedHosts: ["::1"],
569573
},
570574
plugins: [
571575
new HtmlWebpackPlugin({
@@ -653,6 +657,7 @@ const config = {
653657
devServer: {
654658
open: true,
655659
host: "localhost",
660+
allowedHosts: ["::1"],
656661
},
657662
plugins: [
658663
new HtmlWebpackPlugin({
@@ -740,6 +745,7 @@ const config = {
740745
devServer: {
741746
open: true,
742747
host: "localhost",
748+
allowedHosts: ["::1"],
743749
},
744750
plugins: [
745751
new HtmlWebpackPlugin({
@@ -891,6 +897,7 @@ const config = {
891897
devServer: {
892898
open: true,
893899
host: "localhost",
900+
allowedHosts: ["::1"],
894901
},
895902
plugins: [
896903
new HtmlWebpackPlugin({
@@ -1010,6 +1017,7 @@ const config = {
10101017
devServer: {
10111018
open: true,
10121019
host: "localhost",
1020+
allowedHosts: ["::1"],
10131021
},
10141022
plugins: [
10151023
new HtmlWebpackPlugin({
@@ -1221,6 +1229,7 @@ const config = {
12211229
devServer: {
12221230
open: true,
12231231
host: "localhost",
1232+
allowedHosts: ["::1"],
12241233
},
12251234
plugins: [
12261235
new VueLoaderPlugin(),

0 commit comments

Comments
 (0)