Dev Log
Shopify App Dev
October 12, 2025

Configuring Fixed Port for Shopify App Dev Tunnel (Vite Modification)

Shawn Shen avatar
Shawn Shen
Founder of Selofy
min read
Learn how to pin Shopify App dev server to a fixed port (Vite + React Router), avoid random ports, and fix HMR WebSocket binding errors on Windows.

Watch Video Tutorial

Configuring Fixed Port for Shopify App Dev Tunnel (Vite Modification)

Newcomer-friendly guide to pin the dev server to a stable port and remove common tunnel/HMR pitfalls on Windows.

Why fix the port?

  • The Shopify App dev server (React Router + Vite) may choose a random port when the default is occupied, which complicates tunneling and reverse proxies.
  • Fixing the port (e.g., 3001) makes FRP/Cloudflare Tunnel configuration straightforward and reduces daily friction.

Before vs After (Summary)

  • Before: react-router dev may bind to an unpredictable port; HMR might attempt to bind to your public tunnel hostname, causing EADDRNOTAVAIL on Windows.
  • After: Vite dev server uses port 3001 with strictPort: true; HMR listens locally without binding to the public hostname, while clients connect via the tunnel domain.

Step-by-step Changes

1) Update Vite server port and strict mode

File: vite.config.ts

Before:

server: {
  port: Number(process.env.PORT || 3000),
  host: "0.0.0.0",
  hmr: 
/* dynamic host based on SHOPIFY_APP_URL */
}


After:

server: {
  port: 3001,
  host: "0.0.0.0",
  strictPort: true,
  hmr: hmrConfig, 
// see next section
}

2) Fix HMR to avoid binding to public tunnel IP

In vite.config.ts, the HMR config is derived from SHOPIFY_APP_URL. When using a public tunnel URL, binding HMR host to that domain may resolve to Cloudflare IPs (e.g., 104.21.x.x) and fail to listen on Windows.

Before:

const host = new URL(process.env.SHOPIFY_APP_URL || "http://localhost").hostname;
let hmrConfig;
if (host === "localhost") {
  hmrConfig = { protocol: "ws", host: "localhost", port: 64999, clientPort: 64999 };
else {
  hmrConfig = { protocol: "wss", host, port: parseInt(process.env.FRONTEND_PORT!) || 8002, clientPort: 443 };
}

After:

const host = new URL(process.env.SHOPIFY_APP_URL || "http://localhost").hostname;
let hmrConfig;
if (host === "localhost") {
  hmrConfig = { protocol: "ws", host: "localhost", port: 64999, clientPort: 64999 };
else {
  hmrConfig = {
    protocol: "wss",
    
// Do not bind HMR to the public hostname to avoid EADDRNOTAVAIL on Windows
    port: parseInt(process.env.FRONTEND_PORT!) || 8002,
    clientPort: 443,
  };
}

This lets the HMR server listen locally, while the client still connects via the public tunnel domain.

3) Align FRP config (optional, only if you use FRP)

  • Set local_ip = 127.0.0.1 and local_port = 3001 in your frpc.ini service entry.
  • If netstat shows the dev server listening on ::1:3001 (IPv6), use local_ip = ::1 instead.

4) Start the dev server with your tunnel

Use:

shopify app dev --tunnel-url https://your-tunnel.example.com:443

Common Pitfalls and Lessons Learned

  • Adding --port flags to react-router dev can sometimes cause "React Router Vite plugin not found" errors; prefer setting the port in vite.config.ts.
  • Binding HMR to the public hostname can cause EADDRNOTAVAIL on Windows. Keep HMR server local and let clients connect via your tunnel.
  • If you run behind a global proxy, clear proxy env vars for the dev shell or define NO_PROXY=localhost,127.0.0.1,::1 to avoid ETIMEDOUT during local handshakes.

References

  • Vite server config: https://vitejs.dev/config/server-options
  • React Router dev docs: https://reactrouter.com/en/main/routers/picking-a-router
  • Shopify CLI dev options: https://shopify.dev/docs/apps/tools/cli

Frequently Asked Questions

Related Blogs
How to Deploy FRP on Dokploy Platform logo Image
Dev Log
Shopify App Dev
How to Deploy FRP on Dokploy Platform
Shopify App Dev Localhost Error: Invalid Webhook URI Fix logo Image
Dev Log
Dev Log
Shopify App Dev Localhost Error: Invalid Webhook URI Fix
How I Built an E-commerce Toolkit with Zero Coding Experience - Dev Log #001 logo Image
Dev Log
Dev Log
How I Built an E-commerce Toolkit with Zero Coding Experience - Dev Log #001