aindrajaya / aindrajaya/tmat-gis
Failed to load module script: MIME type error when deployed via HAProxy with path-based routing
- Lenguaje dominante
- TypeScript
- Estrellas
- 0
- Forks
- 0
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Descripción
## 🐛 Bug Report: Module Script MIME Type Error in Production Deployment
### 📋 Issue Description
**Summary:**
Vite React application fails to load JavaScript modules in production when deployed behind HAProxy with path-based routing (`/spagambut`). Browser throws MIME type error expecting JavaScript but receiving HTML instead.
**Environment:**
- **Framework:** Vite 5.x + React 18
- **Deployment:** Docker (nginx alpine) + HAProxy reverse proxy
- **Routing:** Path-based routing (`/spagambut/`)
- **Server:** Ubuntu 20.04.6 LTS, Docker 29.1.3
---
### 🔴 Error Message
```
Failed to load module script: Expected a JavaScript module script but the server
responded with a MIME type of "text/html". Strict MIME type checking is enforced
for module scripts per HTML spec.
```
**Browser Console:**
```
GET http://27.50.21.155/assets/index-abc123.js 404 (Not Found)
```
**Expected:**
```
GET http://27.50.21.155/spagambut/assets/index-abc123.js 200 OK
```
---
### 🔍 Root Cause
**Issue:** Vite application built with default base path (`/`) but deployed at subpath (`/spagambut/`) via HAProxy.
**What happened:**
1. Vite builds `index.html` with asset references like: `/assets/main.js`
2. HAProxy strips `/spagambut` prefix before forwarding to application
3. Browser requests `/assets/main.js` (wrong - not found)
4. Nginx returns `index.html` for non-existent routes (SPA fallback)
5. Browser receives HTML instead of JavaScript → MIME type error
**Technical Details:**
HAProxy configuration strips path:
```haproxy
backend spagambut
http-request replace-path /(/)?(.*) /\2
server tmat-gis-app 27.50.21.155:9001 check
```
Built `index.html` references:
```html
```
Should reference:
```html
```
---
### 📸 Screenshots
**Browser Network Tab (Before Fix):**
```
Request URL: http://27.50.21.155/assets/index-abc123.js
Status: 404 Not Found
Content-Type: text/html
```
**Browser Console (Before Fix):**
```
❌ Failed to load module script
❌ GET /assets/main.js 404
```
---
### 🔄 Steps to Reproduce
1. **Create Vite React app:**
```bash
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
```
2. **Build with default config:**
```javascript
// vite.config.ts (default - no base path)
export default defineConfig({
plugins: [react()],
})
```
3. **Deploy to Docker with Nginx:**
```dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
```
4. **Configure HAProxy with path-based routing:**
```haproxy
backend my_app
http-request replace-path /(/)?(.*) /\2
server app 127.0.0.1:3000 check
```
5. **Access via path:** `http://example.com/my-app/`
6. **Result:** Module script MIME type error
---
### ✅ Solution
**Fix:** Configure Vite `base` option to match deployment path.
#### Option 1: Static Base Path
```javascript
// vite.config.ts
export default defineConfig({
plugins: [react()],
base: '/spagambut/', // Match HAProxy path
})
```
#### Option 2: Environment Variable (Recommended)
```javascript
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, '.', '')
return {
base: env.VITE_BASE_PATH || '/',
plugins: [react()],
}
})
```
```bash
# .env (production)
VITE_BASE_PATH=/spagambut/
```
#### Option 3: Use Subdomain Routing (Avoids Issue)
Instead of path-based routing, use subdomain:
```haproxy
acl is_my_app hdr(host) -i app.example.com
use_backend my_app if is_my_app
backend my_app
server app 127.0.0.1:3000 check
# No path stripping needed
```
Then keep Vite base as `/`:
```javascript
export default defineConfig({
base: '/', // No path prefix needed
})
```
---
### 🧪 Verification
**After fix:**
1. **Build output includes base path:**
```html
```
2. **Browser requests correct paths:**
```
GET http://27.50.21.155/spagambut/assets/index-abc123.js
Status: 200 OK
Content-Type: application/javascript
```
3. **No console errors:**
```
✅ All modules loaded successfully
✅ No MIME type errors
```
---
### 📚 Related Issues
- Similar to: #[issue_number] (if exists)
- Vite docs: [[Base Path Configuration](https://vitejs.dev/guide/build.html#public-base-path)](https://vitejs.dev/guide/build.html#public-base-path)
- Related to SPA routing with Nginx fallback
---
### 🔧 Environment Details
```yaml
OS: Ubuntu 20.04.6 LTS
Node: 20.x
npm: 10.x
Vite: 5.x
React: 18.x
Docker: 29.1.3
HAProxy: 2.x
Nginx: 1.25-alpine
Browser: Chrome 120 / Firefox 121
```
**Package versions:**
```json
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.1",
"vite": "^5.0.8"
}
}
```
---
### 💡 Additional Context
**Why this happens:**
- Vite builds assets with absolute paths from root
- HAProxy path stripping changes the effective root
- Mismatch between build-time paths and runtime paths
- Nginx SPA fallback serves HTML for 404s, causing MIME type confusion
**Alternative workarounds:**
1. Configure HAProxy to NOT strip path (pass `/spagambut/` to backend)
2. Use subdomain routing instead of path-based
3. Configure Vite's `base` option to match deployment path ✅ (Recommended)
**Production deployment checklist:**
- [ ] Set `base` in `vite.config.ts`
- [ ] Add `VITE_BASE_PATH` to environment variables
- [ ] Rebuild Docker image with `--no-cache`
- [ ] Verify `index.html` has correct asset paths
- [ ] Test in browser console (no MIME errors)
- [ ] Check Network tab (200 OK for all assets)
---
### 🏷️ Labels
`bug` `vite` `deployment` `docker` `haproxy` `mime-type` `production` `module-script`
---
### 👥 Assignees
@aindrajaya
---
### 🔗 References
- [[Vite Build Options - Public Base Path](https://vitejs.dev/config/build-options.html#build-base)](https://vitejs.dev/config/build-options.html#build-base)
- [[MDN: JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
- [[HAProxy Path Rewriting](https://www.haproxy.com/documentation/hapee/latest/traffic-routing/rewrites/rewrite-url/)](https://www.haproxy.com/documentation/hapee/latest/traffic-routing/rewrites/rewrite-url/)
---
**Status:** ✅ Resolved
**Resolution:** Added `base: env.VITE_BASE_PATH || '/'` to `vite.config.ts` and set `VITE_BASE_PATH=/spagambut/` in production environment.
---
### 📝 Commit Reference
```
fix: Add configurable base path for HAProxy deployment
- Added VITE_BASE_PATH environment variable support
- Allows deployment at /spagambut/ path via HAProxy
- Defaults to / for local development
- Resolves module script MIME type error in production
Fixes #[issue_number]
```
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Evaluación
Este issue todavía no se ha evaluado.