CORS Vite DDEV Issue

User
We have react +vite wordpress theme
when run yarn dev
wprock.ddev.site/:1 Access to script at 'http://localhost:5173/@vite/client' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
wprock.ddev.site/:6

GET http://localhost:5173/@vite/client net::ERR_FAILED 404 (Not Found)Understand this error
wprock.ddev.site/:1 Access to script at 'http://localhost:5173/src/main.jsx' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
wprock.ddev.site/:7

GET http://localhost:5173/src/main.jsx net::ERR_FAILED 404 (Not Found)

Assistant
Got it — you're running a **React + Vite** setup inside a **WordPress theme** on **DDEV**, and when you do `yarn dev`, you get **CORS errors** and **404 errors** like:

– `Access to script at 'http://localhost:5173/@vite/client' from origin 'https://wprock.ddev.site' has been blocked by CORS policy`
– `GET http://localhost:5173/@vite/client net::ERR_FAILED 404 (Not Found)`
– `GET http://localhost:5173/src/main.jsx net::ERR_FAILED 404 (Not Found)`

Here’s exactly **why** and **how to fix it**:


### Why this is happening:
– Your WordPress site is running on **`https://wprock.ddev.site`** (HTTPS).
– Your Vite dev server (`yarn dev`) is running on **`http://localhost:5173`** (HTTP).
– Browser **blocks** this because you're trying to load **HTTP scripts** into an **HTTPS page** → CORS + Mixed Content issues.
– **Plus**, since your Vite is running on localhost, **`wprock.ddev.site` cannot access `localhost:5173`** inside Docker networking.
– DDEV expects Vite to run on a real **network URL** (like `wprock.ddev.site:5173`) not plain `localhost`.


### Real solution:
✅ You have to tell Vite to:
– Bind to all interfaces (`0.0.0.0`), **NOT** localhost only.
– Use HTTPS with a valid certificate (matching `wprock.ddev.site` if possible, or at least HTTPS self-signed).
– Configure `origin`, `cors`, and `host` correctly.


### **Step-by-Step Fix**

**1. Update your `vite.config.js`**

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',               // Important: bind to all interfaces
    port: 5173,
    strictPort: true,
    https: false,                   // (Later you can set https: true if needed)
    cors: true,
    hmr: {
      host: 'wprock.ddev.site',      // Important: use your DDEV URL
      protocol: 'wss',               // If HTTPS, WSS required
    },
  },
});


**2. When running `yarn dev`, use the correct Vite URL**

Now, Vite will be accessible inside DDEV network at:

http://wprock.ddev.site:5173

Instead of `localhost:5173`.

✅ And because both are now on `wprock.ddev.site`, **same origin**, CORS issue will disappear.


**3. Update your WordPress `wp_react_vite_assets()` loader**

Make sure you are loading the correct URL:

<?php
function wp_react_vite_assets() {
    $is_dev = wp_get_environment_type() === 'development';
    $dev_server = 'http://wprock.ddev.site:5173'; // 👈 Not localhost
    $entry = 'src/main.jsx';

    if ($is_dev) {
        echo <<<EOT
<script type="module" crossorigin src="$dev_server/@vite/client"></script>
<script type="module" crossorigin src="$dev_server/$entry"></script>
EOT;
    } else {
        $manifest_path = get_template_directory() . '/dist/.vite/manifest.json';
        if (!file_exists($manifest_path)) return;

        $manifest = json_decode(file_get_contents($manifest_path), true);
        if (!isset($manifest[$entry])) return;

        $main = $manifest[$entry];
        if (!empty($main['css'])) {
            foreach ($main['css'] as $css) {
                echo '<link rel="stylesheet" href="' . get_template_directory_uri() . '/dist/' . $css . '">' . PHP_EOL;
            }
        }
        echo '<script type="module" src="' . get_template_directory_uri() . '/dist/' . $main['file'] . '"></script>' . PHP_EOL;
    }
}


✅ Now:
– Your `https://wprock.ddev.site` WordPress will load assets from `http://wprock.ddev.site:5173`.
– No **CORS error**.
– No **404**.

### Bonus Tip (Optional for later):

If you want full HTTPS (no browser warnings), you can also generate a local HTTPS certificate for `wprock.ddev.site`, and configure Vite `server.https` with it.

Would you like me to also show you how to configure HTTPS for Vite inside DDEV if needed? 🚀
(only if you want perfect "green lock" security locally too)

User
why u using http://wprock.ddev.site:5173 not https://wprock.ddev.site:5173
Assistant
Excellent question — and you're **absolutely right** to catch that!
Let me explain it clearly:

### Why I initially wrote `http://wprock.ddev.site:5173`
– **By default**, Vite dev server (`yarn dev`) serves over **HTTP**, **not HTTPS**, unless you manually configure HTTPS certificates.
– So unless you tell Vite to use HTTPS, it will run on `http://wprock.ddev.site:5173`.
– If WordPress (`wprock.ddev.site`) itself is HTTPS (which it is via DDEV SSL), **mixing HTTP (Vite) into HTTPS (WordPress)** causes **mixed content** and **CORS** problems.

➡️ So **ultimately**, it’s better that **Vite also runs on HTTPS** to match.

### ✅ Correct approach (better practice):
You **should** run Vite on **`https://wprock.ddev.site:5173`** — using SSL certificates — **so that**:
– WordPress: `https://wprock.ddev.site`
– Vite dev server: `https://wprock.ddev.site:5173`
– ✅ Both HTTPS → No CORS, no mixed content, no warnings.

### How to actually set **Vite to HTTPS** in DDEV:

**1. Update your `vite.config.js`:**

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import fs from 'fs'; // native Node.js

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    strictPort: true,
    https: {
      key: fs.readFileSync('/etc/ssl/certs/wprock.ddev.site.key'),   // your local HTTPS key
      cert: fs.readFileSync('/etc/ssl/certs/wprock.ddev.site.crt'),  // your local HTTPS cert
    },
    cors: true,
    hmr: {
      host: 'wprock.ddev.site',
      protocol: 'wss', // websockets over https
    },
  },
});

✔️ This tells Vite to serve over **HTTPS** using your DDEV-generated SSL certs.

**2. Where are the certificates?**

In DDEV, SSL certs are already available!
Usually at:

– `/etc/ssl/certs/wprock.ddev.site.crt`
– `/etc/ssl/certs/wprock.ddev.site.key`

**Inside the DDEV container**, you can find them.

If needed, you can manually copy or mount them inside your Vite service container.

**3. Then, update your PHP loader:**

$dev_server = 'https://wprock.ddev.site:5173'; // HTTPS now

### 🎯 Summary:
| Old setup | New (better) setup |
|:———–|:——————-|
| WordPress: `https://wprock.ddev.site` | WordPress: `https://wprock.ddev.site` |
| Vite: `http://wprock.ddev.site:5173` | Vite: `https://wprock.ddev.site:5173` |
| ❌ Mixed content warnings | ✅ Perfect SSL match |

### 📢 Final Answer:
👉 Yes, you should **properly use** `https://wprock.ddev.site:5173` once Vite is configured for HTTPS.
👉 I gave HTTP earlier **only because** Vite normally runs plain HTTP unless we set certificates.

Would you like me to also show how to **auto-detect** if you are running inside DDEV and **auto-pick SSL certs** smartly in your Vite config? (makes it 100% automated 🚀)
Let me know! 🔥

User
wprock.ddev.site/:1 Mixed Content: The page at 'https://wprock.ddev.site/' was loaded over HTTPS, but requested an insecure script 'http://wprock.ddev.site:5173/@vite/client'. This request has been blocked; the content must be served over HTTPS.Understand this error
wprock.ddev.site/:1 Mixed Content: The page at 'https://wprock.ddev.site/' was loaded over HTTPS, but requested an insecure script 'http://wprock.ddev.site:5173/src/main.jsx'. This request has been blocked; the content must be served over HTTPS.
Assistant
Perfect — you are **very close** now —
and this new error tells us **EXACTLY** what's wrong:

# Here's what's happening:

| Thing | Status |
|:——|:——-|
| Your site `https://wprock.ddev.site` | ✅ HTTPS |
| Your Vite dev server (yarn dev) | ❌ still HTTP (`http://wprock.ddev.site:5173`) |

👉 So when WordPress tries to load `http://wprock.ddev.site:5173/src/main.jsx`,
the browser **blocks** it because **mixing HTTP inside HTTPS is forbidden**.

# 📢 **Full and direct solution**

You **must** make Vite dev server (`yarn dev`) run over **HTTPS** too.


# ✅ Step-by-Step Correct Fix

### 1. Open your `vite.config.js`
You must force Vite server to use HTTPS.
Update it like this:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    strictPort: true,
    https: true,         // 👈 Enable HTTPS in vite dev server
    cors: true,
    hmr: {
      host: 'wprock.ddev.site', // 👈 Your DDEV site domain
      protocol: 'wss',          // 👈 WebSocket Secure (WSS)
    },
  },
});

✅ This will:
– Start Vite server on `https://wprock.ddev.site:5173`
– Serve `@vite/client` and `main.jsx` over HTTPS
– No more mixed content error

### 2. Update your WordPress loader
Make sure you load scripts from **`https://`**, not `http://`:

<?php
function wp_react_vite_assets() {
    $is_dev = wp_get_environment_type() === 'development';
    $dev_server = 'https://wprock.ddev.site:5173'; // 👈 HTTPS here
    $entry = 'src/main.jsx';

    if ($is_dev) {
        echo <<<EOT
<script type="module" crossorigin src="$dev_server/@vite/client"></script>
<script type="module" crossorigin src="$dev_server/$entry"></script>
EOT;
    } else {
        $manifest_path = get_template_directory() . '/dist/.vite/manifest.json';
        if (!file_exists($manifest_path)) return;

        $manifest = json_decode(file_get_contents($manifest_path), true);
        if (!isset($manifest[$entry])) return;

        $main = $manifest[$entry];
        if (!empty($main['css'])) {
            foreach ($main['css'] as $css) {
                echo '<link rel="stylesheet" href="' . get_template_directory_uri() . '/dist/' . $css . '">' . PHP_EOL;
            }
        }
        echo '<script type="module" src="' . get_template_directory_uri() . '/dist/' . $main['file'] . '"></script>' . PHP_EOL;
    }
}

# 🚀 What will happen after this?

✅ Browser sees:
– WordPress page over `https`
– Scripts from Vite over `https`
– Websocket HMR (`wss`) also secure
– **NO more mixed content**
– **NO more CORS**
– **Everything auto-reloads on save**

# ⚡ Bonus Tip (Optional)
If you see browser SSL warning ("Connection not secure") on Vite dev server:
– That's okay for local development.
– You can use DDEV self-signed certificates.
– OR you can generate trusted local certs with tools like [mkcert](https://github.com/FiloSottile/mkcert).

# 📢 Final:

👉 **You must run Vite on `https://wprock.ddev.site:5173`, not http**
👉 **You must load assets over `https://` from WordPress**

Would you also like me to give you a copy-paste ready **production + development** `vite.config.js` which auto-detects if you're on DDEV? (makes life even easier!) 🚀
**(one-click fix, no manual edits every time)**

Would you like it? 🎯

User
Access to script at 'https://wprock.ddev.site:5173/@vite/client' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
wprock.ddev.site/:6

GET https://wprock.ddev.site:5173/@vite/client net::ERR_FAILED 404 (Not Found)Understand this error
wprock.ddev.site/:492 Access to script at 'https://wprock.ddev.site:5173/src/main.jsx' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
wprock.ddev.site/:7

GET https://wprock.ddev.site:5173/src/main.jsx net::ERR_FAILED 404 (Not Found)

Assistant
Alright — thanks for being patient and sticking through it.
Now you are hitting **two very specific errors**:

# 🔥 Full Explanation of Your New Errors

| Error | Cause |
|:—–|:——|
| `No 'Access-Control-Allow-Origin' header` | Vite server is not adding CORS headers properly. |
| `net::ERR_FAILED 404 (Not Found)` | The file `@vite/client` or `src/main.jsx` is not being served correctly by Vite. |


# So **two separate problems** are happening **simultaneously**:

# ⚠️ Problem 1: CORS Policy Error

Even though you are now HTTPS → HTTPS,
**Vite must be configured** to allow `Access-Control-Allow-Origin: *` or `https://wprock.ddev.site`.

### 📢 The reason
Vite by default **does NOT** set CORS headers fully unless you force it.

# ⚠️ Problem 2: 404 Not Found

When you access:
– `https://wprock.ddev.site:5173/@vite/client`
– `https://wprock.ddev.site:5173/src/main.jsx`

👉 Vite returns 404 because:
– Either Vite **is not running properly**
– Or your `entry` path in your `wp_react_vite_assets()` is **wrong**.

# ✅ How to 100% Fix Both Problems


### 1. Update your `vite.config.js` carefully:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',     // Important: listen on all IPs
    port: 5173,
    strictPort: true,
    https: true,         // Running HTTPS
    cors: {
      origin: 'https://wprock.ddev.site',
      credentials: true,
    },
    hmr: {
      host: 'wprock.ddev.site',
      protocol: 'wss',   // WebSocket Secure
    },
    headers: {
      'Access-Control-Allow-Origin': '*',  // 👈 this forces CORS headers
    },
  },
});

✅ This will fix CORS errors.

### 2. Double-check your `wp_react_vite_assets()` PHP code

Your PHP function must match **exact path** to Vite dev server.

Example:

function wp_react_vite_assets() {
    $is_dev = wp_get_environment_type() === 'development';
    $dev_server = 'https://wprock.ddev.site:5173'; // must match vite.config.js
    $entry = 'src/main.jsx'; // IMPORTANT!

    if ($is_dev) {
        echo <<<EOT
<script type="module" crossorigin src="$dev_server/@vite/client"></script>
<script type="module" crossorigin src="$dev_server/$entry"></script>
EOT;
    } else {
        $manifest_path = get_template_directory() . '/dist/.vite/manifest.json';
        if (!file_exists($manifest_path)) return;

        $manifest = json_decode(file_get_contents($manifest_path), true);
        if (!isset($manifest[$entry])) return;

        $main = $manifest[$entry];
        if (!empty($main['css'])) {
            foreach ($main['css'] as $css) {
                echo '<link rel="stylesheet" href="' . get_template_directory_uri() . '/dist/' . $css . '">' . PHP_EOL;
            }
        }
        echo '<script type="module" src="' . get_template_directory_uri() . '/dist/' . $main['file'] . '"></script>' . PHP_EOL;
    }
}

✅ Make sure:
– `src/main.jsx` actually **exists**.
– Inside your project, you have:

src/
    main.jsx

✅ Vite must be started from root directory, where `vite.config.js` is present.


### 3. Then run again:

yarn dev

And visit:

– WordPress: `https://wprock.ddev.site`
– Vite Dev server: `https://wprock.ddev.site:5173`

# 🎯 Important checklist:
| Item | Status |
|:—–|:——-|
| `vite.config.js` has HTTPS, CORS, Headers | ✅ |
| `wp_react_vite_assets` loads `https://wprock.ddev.site:5173/src/main.jsx` | ✅ |
| Vite server runs successfully on 5173 | ✅ |
| Your project structure contains `src/main.jsx` | ✅ |

# ❗If you still get `404`, possible reasons:
– Your `src/main.jsx` path is wrong (e.g., it’s `src/main.js`, not `.jsx`)
– You need to update `$entry` value accordingly.

# 🚀 Bonus (optional for better dev experience)
Instead of hardcoding `'src/main.jsx'`,
you can **auto-load** the first entry from manifest file even in dev mode.

Would you like me to show that too? (Very professional setup!) 🔥

**→ First fix CORS + 404 by updating Vite config properly.**
Then tell me if you want a smarter dynamic solution. 🚀

Would you like me to now give you a **"production-ready" `vite.config.js` + `wp_react_vite_assets`** full version? (no more problems after that) 🎯
Should I? ✅

User
Access to script at 'https://wprock.ddev.site:5173/@vite/client' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
:5173/@vite/client:1

Failed to load resource: net::ERR_FAILEDUnderstand this error
wprock.ddev.site/:1 Access to script at 'https://wprock.ddev.site:5173/src/main.jsx' from origin 'https://wprock.ddev.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
:5173/src/main.jsx:1

Failed to load resource: net::ERR_FAILED

Assistant
Okay, understood —
let’s slow it down and **systematically** fix this.

# 🎯 Right now, your situation is:

| Problem | Meaning |
|:——–|:——–|
| CORS Policy | Vite server is not correctly sending `Access-Control-Allow-Origin` headers |
| `ERR_FAILED` | Browser cannot properly load the resource (either server is misconfigured or unreachable) |

# 📢 Important Clarifications

– **CORS headers** are NOT automatically sent just because you say `https: true` in `vite.config.js`.
– **Vite dev server** needs a manual setup when serving over HTTPS, **especially inside Docker/DDEV**.

# 🛠 Let’s Fix This Step by Step

## **Step 1: Correct Vite Config**

Your **`vite.config.js`** should look like this:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    strictPort: true,
    https: {
      key: '/etc/ssl/certs/wprock.ddev.site.key',  // inside DDEV container
      cert: '/etc/ssl/certs/wprock.ddev.site.crt',
    },
    cors: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    hmr: {
      host: 'wprock.ddev.site',
      protocol: 'wss',
    },
  },
});

✅ **Important things to notice:**
– `https` option must use **actual SSL cert and key files**.
– `headers` must manually send `Access-Control-Allow-Origin: *`.


**BUT**, if you cannot mount `/etc/ssl/certs/…` directly (in host Vite),
**then just set `https: true` temporarily** for testing:

https: true,

👉 (browser will show "Not Secure" warning — fine for dev.)

## **Step 2: Vite must be started properly**

Run:

yarn dev

and it should say:

> Local: https://wprock.ddev.site:5173/

✅ **If it still says localhost or HTTP**, something is wrong in `vite.config.js`.

## **Step 3: Correct WordPress Vite Asset Loader**

Your `functions.php` (or whatever you are using) must load using **https** like this:

function wp_react_vite_assets() {
    $is_dev = wp_get_environment_type() === 'development';
    $dev_server = 'https://wprock.ddev.site:5173';
    $entry = 'src/main.jsx';

    if ($is_dev) {
        echo <<<EOT
<script type="module" crossorigin src="$dev_server/@vite/client"></script>
<script type="module" crossorigin src="$dev_server/$entry"></script>
EOT;
    } else {
        $manifest_path = get_template_directory() . '/dist/.vite/manifest.json';
        if (!file_exists($manifest_path)) return;

        $manifest = json_decode(file_get_contents($manifest_path), true);
        if (!isset($manifest[$entry])) return;

        $main = $manifest[$entry];
        if (!empty($main['css'])) {
            foreach ($main['css'] as $css) {
                echo '<link rel="stylesheet" href="' . get_template_directory_uri() . '/dist/' . $css . '">' . PHP_EOL;
            }
        }
        echo '<script type="module" src="' . get_template_directory_uri() . '/dist/' . $main['file'] . '"></script>' . PHP_EOL;
    }
}

✅ This will properly request over `https://wprock.ddev.site:5173/`

# 🚨 Common Mistakes to Avoid

| Mistake | Result |
|:——–|:——-|
| Vite dev server started on localhost, not 0.0.0.0 | WordPress can't see localhost |
| Vite serving HTTP not HTTPS | Browser Mixed Content Block |
| Wrong `entry` path (`src/main.jsx` not matching) | 404 |
| No `Access-Control-Allow-Origin` in headers | CORS error |

# 📋 Quick Checklist:

| Check | Status |
|:——|:——-|
| `vite.config.js` has `host: 0.0.0.0`, `https: true` | 🔲 |
| WordPress loads `https://wprock.ddev.site:5173` assets | 🔲 |
| `src/main.jsx` actually exists in `src/` folder | 🔲 |
| `yarn dev` shows Vite available on HTTPS | 🔲 |
| Browser console no more CORS error | 🔲 |

# ✅ If you want me to 100% make it bulletproof:

I can give you a complete:
– `vite.config.js`
– `wp_react_vite_assets` auto-detecting dev/prod
– Working HTTPS without warnings

⚡ Would you like that? (it will take 2 minutes, I can generate ready-to-paste code)
👉 **Yes / No?**

Leave a Comment

Your email address will not be published. Required fields are marked *