Claude-skill-registry dev-assets-vite-asset-loading

Vite 6 asset loading patterns that avoid '?import' query parameter pollution. Use when working with static assets (FBX models, images, fonts), dealing with Vite 6's new asset handling, or loading assets from public vs src/assets directories.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-assets-vite-asset-loading" ~/.claude/skills/majiayu000-claude-skill-registry-dev-assets-vite-asset-loading && rm -rf "$T"
manifest: skills/data/dev-assets-vite-asset-loading/SKILL.md
source content

Vite 6 Asset Loading Patterns

When to Use

  • Working with static assets (FBX models, images, fonts)
  • Dealing with Vite 6's new asset handling
  • Avoiding '?import' query parameter pollution
  • Loading assets from public directory vs src/assets

Quick Start

For FBX Models (public/ directory)

import { useFBX } from '@react-three/drei';

// CORRECT - Uses public directory with absolute path
function CharacterModel({ characterType }: { characterType: string }) {
  const fbx = useFBX(`/assets/${characterType}.fbx`);
  return <primitive object={fbx} />;
}

// For public assets that need URL
const imageUrl = new URL('/assets/images/splash.png', import.meta.url);

For CSS/JS Assets (src/assets/ directory)

// For assets that need processing
import backgroundImage from '@/assets/images/background.jpg';

// For CSS imports
import '@/styles/global.css';

Anti-Patterns

DON'T: Use

import
statements for public directory assets

import characterModel from '/assets/character.fbx'; // Creates '?import' query

DO: Use absolute paths for public assets

// In JSX
<img src="/assets/logo.png" alt="Logo" />

// Or with URL constructor
const assetUrl = new URL('/assets/data.json', import.meta.url);

DON'T: Mix public and src/assets references arbitrarily

// Bad - inconsistent approach
function MixedAsset() {
  // This should be in public/ with absolute path
  const localAsset = require('@/assets/icon.png');
  // This should be imported properly
  const publicAsset = '/assets/icon.png';
}

DO: Consistent directory strategy

// All public assets use absolute paths
function ConsistentAssets() {
  return (
    <div>
      <img src="/assets/public-image.jpg" alt="Public" />
      <Model assetUrl="/assets/model.fbx" />
    </div>
  );
}

Asset Directory Strategy

Public Directory (
public/
)

Use for:

  • Static files that won't change (favicons, fonts)
  • Third-party assets (Blaster Kit, Animated Characters)
  • Files served as-is without processing

Reference pattern:

// Always use absolute paths starting with /
const assetPath = '/assets/Blaster Kit/Models/FBX format/rifle.fbx';
const fbx = useFBX(assetPath);

Src Assets Directory (
src/assets/
)

Use for:

  • Application-specific assets
  • Assets that need processing (images, CSS)
  • Assets bundled with your code

Import pattern:

import processedImage from '@/assets/images/hero.png';
import styles from '@/styles/component.module.css';

Vite 6 Specific Considerations

Base URL Configuration

// vite.config.js
export default defineConfig({
  base: '/your-app-path/', // Important for public assets
  assetsInclude: ['**/*.fbx', '**/*.glb'],
  // ... other config
});

Asset Optimization

  • Vite 6 automatically optimizes images, fonts, and media
  • Use modern formats (WebP, AVIF when supported)
  • Consider lazy loading for non-critical assets

Cache Busting

// For cache busting on public assets
const versionedAsset = `/assets/image.jpg?v=${APP_VERSION}`;

// Or for dynamic assets
const dynamicAsset = new URL(`/assets/${assetId}.png?theme=${theme}`, import.meta.url);

Environment-Specific Paths

Development

// Absolute paths work in dev
const devAsset = '/assets/development-only.json';

Production

// Ensure base path is correct for production deployment
const prodAsset = `${import.meta.env.BASE_URL}assets/production.json`;

FBX Model Loading Pattern

Sequential Loading (Recommended)

import { useFBX, useProgress } from '@react-three/drei';
import { Suspense } from 'react';

function SequentialLoader({ characters }: { characters: string[] }) {
  return (
    <Suspense fallback={<LoadingScreen />}>
      {characters.map((char, index) => (
        <CharacterModel key={index} characterType={char} />
      ))}
    </Suspense>
  );
}

function CharacterModel({ characterType }: { characterType: string }) {
  const fbx = useFBX(`/assets/${characterType}.fbx`);

  // Process and return the model
  return (
    <primitive
      object={fbx}
      position={[0, 0, 0]}
      scale={[1, 1, 1]}
    />
  );
}

Loading State Management

function AssetLoader() {
  const { active, progress, errors, item } = useProgress();

  if (errors.length > 0) {
    return <div>Error loading assets</div>;
  }

  return (
    <div>
      {active && <div>Loading: {item} - {progress.toFixed(0)}%</div>}
    </div>
  );
}

Reference