返回 Skill 列表
extension
分类: 开发与工程无需 API Key

dev-assets-vite-asset-loading

Vite 6 资源加载模式,避免使用 '?import' 查询参数污染。在处理静态资源(如 FBX 模型、图片、字体)时使用,应对 Vite 6 新的资源处理方式,或者从 public 目录与 src/assets 目录加载资源时。

person作者: jakexiaohubgithub

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