CORS Vite DDEV Issue
April 26, 2025 · AI Conversations
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)
– `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)
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! 🔥
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.
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? 🎯
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)
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? ✅
: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
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?**