本文へ移動
cccskills
無料GitHub で公開

vite-proxy-folder-name-conflict

Fix 404 errors for frontend JS files when using Vite proxy. Use when: (1) Browser shows "Failed to load resource: 404" for JS/JSX files that exist on disk, (2) Vite serves HTML instead of JavaScript for module imports, (3) You have a client folder named "api" (or similar) AND a Vite proxy configured for "/api". The proxy intercepts requests for client-side files when folder names match proxy paths. Applies to Vite, Vite+React, Vite+Vue projects with dev server proxy configuration.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md5.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Vite Proxy Folder Name Conflict

Problem

Frontend JavaScript/JSX files return 404 errors even though they exist on disk. The browser console shows errors like:

usePeople.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)
useMedia.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)

The files exist at paths like src/client/api/hooks/usePeople.js, but Vite returns 404 or serves HTML instead of JavaScript.

Context / Trigger Conditions

This issue occurs when ALL of these conditions are true:

  1. Vite dev server with proxy configuration in vite.config.js:

    server: {
      proxy: {
        '/api': {
          target: 'http://localhost:3001',
          changeOrigin: true,
        },
      },
    }
    
  2. Client-side folder with the same name as the proxy path:

    src/client/
    ├── api/           ← Folder name matches proxy path "/api"
    │   ├── client.js
    │   └── hooks/
    │       ├── usePeople.js
    │       └── useMedia.js
    
  3. Imports that resolve to the proxied path:

    // In src/client/pages/Directory.jsx
    import { usePeople } from '../api/hooks/usePeople.js';
    // Vite transforms this to: /api/hooks/usePeople.js
    // This matches the proxy rule and gets sent to backend!
    

Root Cause

Vite's module resolution transforms relative imports to absolute paths. When you import ../api/hooks/usePeople.js from a page, Vite resolves it to /api/hooks/usePeople.js.

The proxy configuration matches paths starting with /api and forwards them to the backend server. Since /api/hooks/usePeople.js starts with /api, it gets proxied to the backend instead of being served as a static file.

The backend doesn't have a route for /api/hooks/usePeople.js, so it returns 404.

Solution

Option 1: Rename the client folder (Recommended)

Rename the conflicting folder to something that won't match the proxy path:

# Rename api to services (or lib, helpers, etc.)
mv src/client/api src/client/services

# Update all imports
find src/client -name "*.jsx" -o -name "*.js" | xargs sed -i '' 's|from.*['"'"'"]\.\.\/api|from "../services|g'

Option 2: Use a different proxy path

Change the proxy path to something more specific:

// vite.config.js
server: {
  proxy: {
    '/api/v1': {  // More specific path
      target: 'http://localhost:3001',
      changeOrigin: true,
    },
  },
}

Option 3: Configure proxy to exclude certain patterns

Use a custom function to exclude certain paths:

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:3001',
      changeOrigin: true,
      bypass: (req) => {
        // Don't proxy requests for JS/TS files
        if (req.url.match(/\.(js|jsx|ts|tsx|mjs)$/)) {
          return req.url;
        }
      },
    },
  },
}

Verification

After applying the fix:

  1. Clear Vite's cache: rm -rf node_modules/.vite
  2. Restart the dev server: npm run dev
  3. Check browser console - 404 errors should be gone
  4. Verify the app loads and API calls still work

Test both:

  • Frontend file serving: curl http://localhost:5173/services/hooks/usePeople.js should return JavaScript
  • API proxying: curl http://localhost:5173/api/people should return JSON from backend

Example

Before (broken):

src/client/
├── api/                    ← Conflicts with proxy
│   └── hooks/
│       └── usePeople.js
├── pages/
│   └── Directory.jsx       ← import from '../api/hooks/usePeople.js'

vite.config.js:
  proxy: { '/api': 'http://localhost:3001' }

Result: Browser gets 404 for usePeople.js

After (fixed):

src/client/
├── services/               ← Renamed to avoid conflict
│   └── hooks/
│       └── usePeople.js
├── pages/
│   └── Directory.jsx       ← import from '../services/hooks/usePeople.js'

vite.config.js:
  proxy: { '/api': 'http://localhost:3001' }  ← Unchanged

Result: Frontend files served correctly, API still proxied

Notes

  • This issue is not specific to React—it affects any Vite project with proxies
  • Common conflicting folder names: api, graphql, socket, ws
  • The issue only manifests in development (Vite dev server); production builds don't have this problem
  • If using TypeScript path aliases, ensure they also avoid proxy path conflicts
  • Always clear Vite's cache (node_modules/.vite) after changing folder structure

Related Issues

  • Similar issues can occur with other dev servers (webpack-dev-server, Create React App)
  • If using a monorepo, check proxy configs in both root and package-level configs

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Fix ArgoCD ExternalSecret deployment failing with "namespace X is not permitted in project Y". Use when: (1) ExternalSecret shows OutOfSync in ArgoCD but won't sync, (2) ArgoCD application status shows "namespace X is not permitted in project 'infrastructure'", (3) ExternalSecret targets a namespace managed by a different ArgoCD project, (4) Using apps-of-apps pattern with separate infrastructure and application projects.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

Art direction for any content — reads text, PDF, Word, HTML, PPT, then proposes 2-3 creative directions with photography style, mood, and visual language. After selection, generates AI image prompts and visual briefs section-by-section. Use when the user shares content and needs visual direction, image sourcing, or creative direction for any material.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

Fix "Null check operator used on a null value" errors when an object is set to null during an async await. Use when: (1) Object reference is nullified while awaiting, (2) Code accesses object with ! after await returns, (3) Cancel/dispose operations run concurrently with async operations on same object. Solution: capture local reference before await.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

Add custom metadata headers (x-amz-meta-*) to AWS v4 signed requests for GCS S3-compatible API. Use when: (1) Adding custom metadata to GCS uploads via S3 API, (2) Getting signature mismatch errors after adding new headers, (3) x-amz-meta-* headers being ignored or causing 403 errors. Custom headers MUST be included in canonical headers and signed headers list.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

Fix password/secret authentication failures caused by trailing newlines when creating Google Cloud secrets (or similar) with bash here-strings. Use when: (1) Password authentication fails with correct password, (2) Secret created with `<<< "value"` syntax, (3) Error like "password authentication failed" or "invalid token" despite correct value. Bash here-strings (`<<<`) add a trailing newline that corrupts secrets.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

Fix silent video/media processing failures caused by URL extraction code that filters on file extensions (.mp4, .webm, .webp). Use when: (1) Media moderation, transcoding, or analysis silently skips files from Blossom or content-addressed storage servers, (2) URL extraction from Nostr event tags (imeta, r tags) drops URLs without recognized extensions, (3) CDN fallback URLs append .mp4 but the actual server uses extensionless content-addressed paths like /{sha256}. Common in Nostr video events (kind 34236) where different clients use different URL formats.

日本語の概要は準備中です。原文の説明を表示しています。

divinevideo/divine-mobile2662026年10月12日 更新

divinevideo のスキルをすべて見る

このスキルの問題を報告する