> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Vite에 의한 에셋 번들

> Laravel 프로젝트에서 Vite를 사용해 JavaScript·CSS를 번들하고, 핫 리로드로 쾌적한 개발 환경을 구축하는 방법을 설명합니다.

## Laravel과 Vite란

[Vite](https://vitejs.dev)는 고속의 프론트엔드 빌드 도구입니다. 개발 중에는 즉시 파일의 변경을 반영하는 핫 모듈 리플레이스먼트(HMR)를 제공하고, 프로덕션 빌드에서는 최적화된 에셋을 생성합니다.

Laravel 9 이후, Vite가 표준의 프론트엔드 빌드 도구로서 채용되어 있어, `laravel-vite-plugin`을 통해 Laravel과 연계합니다. 이 플러그인이 담당하는 주요 역할은 다음과 같습니다.

* 엔트리 포인트의 관리
* 개발 서버의 HMR 지원
* `@vite()` Blade 디렉티브와의 연계
* 프로덕션 빌드 시의 에셋의 버전 관리 (캐시 버스팅)

<Info>
  Laravel의 스타터 킷(Laravel Breeze 등)을 사용하고 있는 경우, Vite와 Tailwind의 설정은 이미 포함되어 있습니다. 이 페이지에서는 제로부터 설정하는 방법을 설명합니다.
</Info>

<Tip>
  Vite가 Laravel 전체의 프론트엔드 구성 안에서 어떤 위치 부여인지는, [프론트엔드](/ko/frontend)에서 먼저 전체상을 확인할 수 있습니다.
</Tip>

## 설치와 설정

### Node의 설치 확인

Vite를 사용하려면 Node.js(16 이상)와 npm이 필요합니다. 설치된 상태인지 확인합니다.

```shell theme={null}
node -v
npm -v
```

### 패키지의 설치

신규 설치한 Laravel 프로젝트에는, 이미 `package.json`에 `vite`와 `laravel-vite-plugin`이 포함되어 있습니다. 다음 명령으로 의존 패키지를 설치합니다.

```shell theme={null}
npm install
```

### vite.config.js의 설정

프로젝트 루트에 `vite.config.js`가 생성되어 있습니다. 엔트리 포인트(번들의 기점이 되는 파일)를 지정합니다.

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css',
            'resources/js/app.js',
        ]),
    ],
});
```

<Tip>
  SPA나 Inertia를 사용하는 경우는, CSS를 JavaScript로부터 임포트하는 형식이 권장됩니다. 그 경우는 엔트리 포인트에서 `resources/css/app.css`를 제거하고, `resources/js/app.js`의 선두에 `import '../css/app.css';`를 추가합니다.
</Tip>

## 개발 서버의 기동

개발 중에는 `npm run dev`로 Vite의 개발 서버를 기동합니다. 파일을 변경하면 브라우저가 자동적으로 갱신됩니다(HMR).

```shell theme={null}
npm run dev
```

Laravel의 개발 서버와 동시에 기동할 수도 있습니다.

```shell theme={null}
composer run dev
```

<Info>
  `composer run dev`는 `php artisan serve`와 `npm run dev`를 동시에 기동합니다.
</Info>

### Blade 뷰의 자동 리로드

`refresh: true`를 설정하면, Blade 뷰나 라우트 파일을 보존했을 때에 브라우저가 자동 리로드됩니다.

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
    ],
});
```

`refresh: true`일 때, 다음의 디렉터리에의 변경이 감시 대상이 됩니다.

* `resources/views/**`
* `app/Livewire/**`
* `routes/**`
* `lang/**`

## 프로덕션 빌드

프로덕션 환경에 배포하기 전에 `npm run build`를 실행합니다. 에셋이 번들·버전 관리되어, `public/build/`에 출력됩니다.

```shell theme={null}
npm run build
```

빌드 후의 디렉터리 구조의 예:

```text theme={null}
public/
  build/
    assets/
      app-Cv82Mlke.css
      app-DnAZBF4U.js
    manifest.json
```

`manifest.json`에는 파일명과 해시의 매핑이 기록되어 있어, `@vite()` 디렉티브가 이를 참조해 올바른 파일을 로드합니다.

<Warning>
  `public/build/` 디렉터리는 빌드 성과물이므로 `.gitignore`에 추가할 것을 권장합니다. 배포처에서 빌드를 실행하거나, CI에서 빌드해 배포합니다.
</Warning>

## Blade로부터의 에셋 로드

`@vite()` Blade 디렉티브를 레이아웃의 `<head>`에 추가합니다.

```blade theme={null}
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name') }}</title>

    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
    @yield('content')
</body>
</html>
```

CSS를 JavaScript로부터 임포트하고 있는 경우는, JavaScript의 엔트리 포인트만 지정합니다.

```blade theme={null}
@vite('resources/js/app.js')
```

`@vite()` 디렉티브는 개발 중과 프로덕션에서 자동적으로 동작을 전환합니다.

| 상황           | 동작                                             |
| ------------ | ---------------------------------------------- |
| 개발 서버 기동 중   | Vite 개발 서버로부터 에셋을 로드하고, HMR을 활성화               |
| 프로덕션 (빌드 완료) | `public/build/manifest.json`을 참조해 버전 첨부 파일을 로드 |

## JavaScript·CSS의 엔트리 포인트 설정

### JavaScript의 설정

`resources/js/app.js`가 메인 엔트리 포인트입니다. 여기서 다른 모듈을 임포트합니다.

```js theme={null}
import './bootstrap';
import '../css/app.css';

// 자작 모듈의 임포트
import './components/modal';
import './utils/format';
```

### CSS의 설정

`resources/css/app.css`에 글로벌한 스타일을 기술합니다.

```css theme={null}
/* Tailwind CSS를 사용하는 경우 */
@import 'tailwindcss';

/* 커스텀 스타일 */
body {
    font-family: 'Noto Sans KR', sans-serif;
}
```

### 여러 엔트리 포인트

관리 화면 등, 페이지별로 다른 에셋을 번들하고 싶은 경우는, 여러 엔트리 포인트를 지정합니다.

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css',
            'resources/js/app.js',
            'resources/css/admin.css',
            'resources/js/admin.js',
        ]),
    ],
});
```

Blade에서는 대응하는 엔트리 포인트만 로드합니다.

```blade theme={null}
{{-- 관리 화면 레이아웃 --}}
@vite(['resources/css/admin.css', 'resources/js/admin.js'])
```

## Tailwind CSS와의 연계

Tailwind CSS v4 이후는 Vite 플러그인으로서 통합됩니다.

<Steps>
  <Step title="Tailwind를 설치">
    ```shell theme={null}
    npm install tailwindcss @tailwindcss/vite
    ```
  </Step>

  <Step title="vite.config.js에 플러그인을 추가">
    ```js theme={null}
    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    import tailwindcss from '@tailwindcss/vite';

    export default defineConfig({
        plugins: [
            tailwindcss(),
            laravel([
                'resources/css/app.css',
                'resources/js/app.js',
            ]),
        ],
    });
    ```
  </Step>

  <Step title="CSS에 Tailwind를 임포트">
    ```css theme={null}
    /* resources/css/app.css */
    @import 'tailwindcss';
    ```
  </Step>
</Steps>

<Info>
  Tailwind CSS v3을 사용하는 경우는 `tailwind.config.js`와 `postcss.config.js`가 필요합니다. 최신의 Tailwind CSS v4에서는 이러한 파일은 불필요합니다.
</Info>

## 에일리어스 설정

`laravel-vite-plugin`은 `@` 에일리어스를 자동으로 설정합니다. 이는 `resources/js` 디렉터리를 가리킵니다.

```js theme={null}
// 에일리어스를 사용한 임포트
import UserCard from '@/components/UserCard.vue';
// 위는 다음과 같음
import UserCard from '/resources/js/components/UserCard.vue';
```

커스텀 에일리어스를 추가하고 싶은 경우는 `resolve.alias`로 설정합니다.

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import path from 'path';

export default defineConfig({
    plugins: [
        laravel(['resources/js/app.js']),
    ],
    resolve: {
        alias: {
            '@': '/resources/js',
            '@css': '/resources/css',
            '@images': '/resources/images',
        },
    },
});
```

에일리어스를 사용한 임포트 예:

```js theme={null}
import logo from '@images/logo.png';
import '@css/custom.css';
```

## 프레임워크별의 설정

### Vue

```shell theme={null}
npm install --save-dev @vitejs/plugin-vue
```

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        laravel(['resources/js/app.js']),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});
```

### React

```shell theme={null}
npm install --save-dev @vitejs/plugin-react
```

```js theme={null}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel(['resources/js/app.jsx']),
        react(),
    ],
});
```

React를 사용하는 경우, Blade 템플릿에 `@viteReactRefresh` 디렉티브를 `@vite`보다 앞에 추가합니다.

```blade theme={null}
@viteReactRefresh
@vite('resources/js/app.jsx')
```

## 정적 에셋의 처리

Blade 템플릿으로부터 참조하는 이미지나 폰트도 Vite로 버전 관리할 수 있습니다. `assets` 옵션으로 대상 디렉터리를 지정합니다.

```js theme={null}
laravel({
    input: 'resources/js/app.js',
    assets: ['resources/images/**', 'resources/fonts/**'],
})
```

Blade 템플릿에서는 `Vite::asset()` 메서드로 버전 첨부 URL을 취득합니다.

```blade theme={null}
<img src="{{ Vite::asset('resources/images/logo.png') }}" alt="로고">
```

## 정리

| 하고 싶은 일             | 방법                                                        |
| ------------------- | --------------------------------------------------------- |
| 개발 서버를 기동           | `npm run dev`                                             |
| 프로덕션용 에셋을 빌드        | `npm run build`                                           |
| Blade에서 에셋을 로드      | `@vite(['resources/css/app.css', 'resources/js/app.js'])` |
| Blade 뷰 변경으로 자동 리로드 | `refresh: true`를 `vite.config.js`에 설정                     |
| Tailwind CSS를 사용    | `@tailwindcss/vite` 플러그인을 추가                              |
| `@` 에일리어스를 사용       | 기본으로 `resources/js`를 가리킴                                  |
| 정적 에셋을 버전 관리        | `assets` 옵션과 `Vite::asset()`을 사용                          |

## 다음 단계

<Card title="캐시" href="/ko/cache" icon="database">
  Laravel의 캐시 기능으로 애플리케이션의 성능을 더욱 향상시키는 방법을 배웁니다.
</Card>


## Related topics

- [프런트엔드](/ko/frontend.md)
- [Copilot CLI 번들](/ko/packages/laravel-copilot-sdk/bundle-cli.md)
- [Laravel LSP — Language Server Protocol에 의한 IDE 기능 확장](/ko/blog/laravel-lsp-introduction.md)
- [Svelte 입문 — Inertia × Laravel에서 사용하는 기초 지식](/ko/blog/svelte-introduction.md)
- [Laravel Maestro — 스타터 킷 개발의 오케스트레이터](/ko/blog/maestro-introduction.md)
