サイトロゴ
SvelteKit Created: 2026/05/25 Updated: 2026/05/26

SvelteKitのvite.config.tsとtsconfig.jsonの役割を整理する

SvelteKitで迷いやすいvite.config.tsとtsconfig.jsonの役割を整理。include/exclude、SSR external/noExternal、ビルドに含める・含めない設定、よくあるハマりポイントを初心者向けに解説します。

この記事で整理すること

01 設定ファイルごとの役割

02 tsconfig.json の include / exclude

03 vite.config.ts の external / noExternal

04 ビルド時によくあるハマりポイント

05 実践用の設定例

SvelteKit を使っていると、あるタイミングで必ず設定ファイルまわりに迷います。

vite.config.ts svelte.config.js tsconfig.json 、そして自動生成される.svelte-kit/tsconfig.json 。それぞれ名前は見たことがあっても、 どの設定をどこに書くべきか は意外とわかりにくいです。

特にハマりやすいのが、「このファイルをビルドに含めたくない」「この依存パッケージはバンドルしたくない」「exclude に書いたのにビルドエラーが消えない」といった場面です。

🎯 この記事の結論

tsconfig.json は TypeScript の型チェックやエディタ補完のための設定です。SvelteKit のビルド対象を直接コントロールする設定ではありません。
ビルド・バンドル・SSR の依存関係を調整する場合は、主にvite.config.ts を見ます。

SvelteKit に登場する設定ファイルの全体像

まずは、それぞれのファイルの役割をざっくり整理します。ここが曖昧なままだと、tsconfig.json に書くべきではない設定を追加してしまったり、逆にvite.config.ts で制御すべき内容を見落としたりします。

svelte.config.js

SvelteKit 本体の設定

adapter、alias、kit 設定などを書きます。SvelteKit としての振る舞いを決める中心的な設定ファイルです。

vite.config.ts

Vite の設定

plugins、dev server、build、SSR 外部化、Vitest 設定などを書きます。ビルド挙動に大きく関わります。

tsconfig.json

TypeScript の設定

型チェック、パス解決、include / exclude、strict などを設定します。ビルド除外の設定ファイルではありません。

.svelte-kit/tsconfig.json

SvelteKit が自動生成する設定

SvelteKit が必要とする TypeScript 設定が入ります。基本的に直接編集しません。

やりたいこと 主に見るファイル 理由
adapter を変更したいsvelte.config.js SvelteKit 本体の設定だから
開発サーバーのポートを変えたいvite.config.ts Vite dev server の設定だから
型チェック対象を調整したいtsconfig.json TypeScript の対象ファイルを調整するため
SSR ビルドで特定パッケージを外部化したいvite.config.ts Vite の SSR / Rollup 設定で制御するため
本番で開発用ページを見せたくないhooks.server.ts など 型設定ではなくルーティング制御が必要だから

💡 SvelteKit は Vite プロジェクトでもある

SvelteKit プロジェクトは、@sveltejs/kit/vite プラグインを使った Vite プロジェクトです。そのため、開発サーバーやビルドの細かい挙動はvite.config.ts 側で調整することが多くなります。

tsconfig.json の役割:型チェックとエディタ補完

tsconfig.json は、TypeScript がプロジェクトをどのように解釈するかを決める設定ファイルです。SvelteKit では、基本的に.svelte-kit/tsconfig.json を継承して使います。

json
{
  "extends": "./.svelte-kit/tsconfig.json",
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "strict": true,
    "moduleResolution": "bundler"
  }
}

重要なのはextends です。SvelteKit は.svelte-kit/tsconfig.json を自動生成し、その中に$lib $types など、SvelteKit プロジェクトに必要な設定を含めます。

⚠️ 直接編集しない

.svelte-kit/tsconfig.json は生成物です。.svelte-kit を削除したり、svelte-kit sync が走ったりすると再生成されます。自分の設定はプロジェクトルートのtsconfig.json に書きます。

include / exclude は何をする設定か

include exclude は、TypeScript がどのファイルを型チェック対象として扱うかを調整するための設定です。

text
{
  "extends": "./.svelte-kit/tsconfig.json",
  "exclude": [
    "node_modules",
    "build",
    ".svelte-kit",
    "dist",
    "coverage",
    "playwright-report",
    "test-results"
  ]
}

ここで一番大事なのは、exclude は「ビルドに含めない設定」ではない という点です。

✨ よくある誤解

exclude に書いたファイルでも、アプリ側からimport していれば依存関係として読み込まれます。つまり、exclude は「絶対に使わせない設定」ではありません。

exclude に書いたのに読み込まれる例

たとえばscripts フォルダを除外したとします。

json
{
  "exclude": ["scripts/**"]
}

しかし、アプリ側で次のように import していたら、TypeScript やビルドツールはそのファイルを依存関係として扱います。

ts
import { runTask } from '../../scripts/run-task';

export const load = async () => {
  await runTask();
};

この場合、exclude に書いたからといって安全ではありません。使いたくないファイルは、そもそもアプリ側から import しない設計にする必要があります。


vite.config.ts の役割:開発サーバー・ビルド・SSR の設定

vite.config.ts は、SvelteKit アプリを Vite がどのように扱うかを決める設定ファイルです。

ts
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [sveltekit()]
});

Tailwind CSS v4 を使っている場合は、次のように@tailwindcss/vite を追加する構成もよく使います。

ts
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],

  server: {
    port: 5160,
    strictPort: true
  }
});
設定 役割
plugins Vite プラグインを読み込むsveltekit() tailwindcss()
server 開発サーバーの設定 ポート番号、host、strictPort
build ビルド時の Rollup 設定rollupOptions.external
ssr SSR ビルド時の依存関係制御external noExternal
test Vitest の設定 テスト対象、browser test 設定など

ビルドに含めたくないものはどこで制御するのか

ここが一番ハマりやすいポイントです。「含めたくない」と言っても、実は何を外したいのかによって書く場所が変わります。

やりたいこと 書く場所 考え方
型チェック対象から外したいtsconfig.jsonexclude を使う
SSR ビルドでバンドルしたくないvite.config.tsssr.external を使う
Rollup のバンドル対象から外したいvite.config.tsbuild.rollupOptions.external を使う
ルーティング対象にしたくない ファイル配置src/routes の外へ出す
本番でアクセスさせたくないhooks.server.ts など production 時に 404 などで制御する

Node.js 専用ライブラリをバンドルしたくない例

たとえばplaywright playwright-core chromium-bidi のようなパッケージは、通常の画面表示では使わず、OG画像生成や開発用処理でだけ使うことがあります。 このような依存関係を SSR ビルドにそのまま巻き込むと、ビルド後のサーバーチャンクに不要な参照が残ったり、実行環境でCannot find module 系のエラーが出たりすることがあります。

ts
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';

const isExternal = (id: string) => {
  return (
    id === 'playwright' ||
    id === 'playwright-core' ||
    id === 'chromium-bidi' ||
    id.startsWith('playwright/') ||
    id.startsWith('playwright-core/') ||
    id.startsWith('chromium-bidi/')
  );
};

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],

  ssr: {
    external: ['playwright', 'playwright-core', 'chromium-bidi']
  },

  build: {
    rollupOptions: {
      external: isExternal
    }
  }
});

⚠️ external は削除ではない

external は「不要だから消す」設定ではありません。ビルド成果物にバンドルせず、実行時にnode_modules から読み込むようにする設定です。 つまり、本番環境でそのコードが実行されるなら、該当パッケージは本番環境にもインストールされている必要があります。

コード側では dynamic import も検討する

そもそも通常のリクエスト処理で使わない重いライブラリは、静的 import ではなく dynamic import にする方が安全です。

ts
// static import ではなく、必要なタイミングで読み込む
const { chromium } = await import('playwright');

const browser = await chromium.launch({
  headless: true,
  args: ['--no-sandbox', '--disable-setuid-sandbox']
});

この形にしておくと、通常のアプリ起動時に Playwright を読み込まず、OG 画像生成など必要な処理のタイミングだけ読み込めます。

ビルドに含めたいものはどこで制御するのか

逆に、SSR ビルド時に外部化せず、Vite の変換を通したい依存関係もあります。その場合はssr.noExternal を使います。

ts
export default defineConfig({
  plugins: [sveltekit()],

  ssr: {
    noExternal: ['some-package']
  }
});

noExternal は、指定した依存関係を SSR ビルド時に外部化せず、バンドル側に含めたいときに使います。

設定 意味 使う場面
ssr.external SSR ビルドで外部化する Node.js 側でそのまま読み込ませたい依存関係
ssr.noExternal SSR ビルドで外部化しない Vite の変換を通したい依存関係
rollupOptions.external Rollup のバンドルから外す 深い import まで外部化したい場合など

✨ 最小限にする

external noExternal は、何でも追加すればよい設定ではありません。対象を広げすぎると、ビルドが重くなったり、別の依存関係トラブルを招いたりします。必要なパッケージだけを最小限に指定するのが基本です。


src/routes に置いたものはルーティング対象になる

SvelteKit では、src/routes 配下のファイル構成がそのままルーティングに関わります。 そのため、開発用のページや実験用のページをsrc/routes に置いたままにしていると、本番でもルートとして存在することになります。

text
src/routes/
├ devonly/
│ └ og/
│   └ +page.svelte
├ sample/
│ └ +page.svelte
└ posts/
  └ [category]/
    └ [slug]/
      └ +page.svelte

tsconfig.json exclude src/routes/devonly/** と書いても、SvelteKit のルーティング対象から外れるわけではありません。

⚠️ ルーティング除外は exclude ではない

ルーティングさせたくないファイルは、src/routes の外に置くか、本番環境でアクセスできないようにサーバー側で制御します。

本番で開発用ルートを見せない例

開発用ルートを残したい場合は、production では 404 にする方法があります。

ts
import { dev } from '$app/environment';
import { error } from '@sveltejs/kit';
import type { Handle } from '@sveltejs/kit';

const mode = process.env.VITE_NODE_ENV;

export const handle: Handle = async ({ event, resolve }) => {
  const devOnlyRoutes = ['/devonly'];
  const isProd = !dev && mode === 'production';

  if (isProd && devOnlyRoutes.some((path) => event.url.pathname.startsWith(path))) {
    throw error(404, 'Not Found');
  }

  return resolve(event);
};

ただし、もっと安全にするなら、開発専用ページ自体を本番ビルド対象のルートに置かない設計も検討してください。


よくあるハマりポイント

ここからは、SvelteKit の設定まわりで実際によく起きる問題を整理します。

❓ exclude に書いたのにビルドエラーが消えない

exclude は TypeScript の型チェック対象を調整する設定です。アプリ側から import されているファイルや、Vite / SvelteKit が処理する依存関係を強制的に消すものではありません。ビルドや SSR の依存関係はvite.config.ts 側を確認します。

❓ .svelte-kit/tsconfig.json がないと警告が出る

.svelte-kit は生成ディレクトリです。削除直後や、まだ SvelteKit の sync が走っていない状態では警告が出ることがあります。bunx svelte-kit sync 、またはbun run dev で再生成します。

svelte
$ bunx svelte-kit sync

# または開発サーバーを起動する
$ bun run dev

❓ test 設定を vite.config.ts に残してよいかわからない

Vitest を使っているならtest 設定自体は問題ありません。ただし、browser test 用に Playwright などの重い依存を常に読み込む構成だと、本番ビルド側の依存関係が複雑になることがあります。

ts
import { defineConfig } from 'vitest/config';
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],

  test: {
    include: ['src/**/*.{test,spec}.{js,ts}']
  }
});

❓ src/lib/server に置けばクライアントに絶対入らないと思っている

src/lib/server はサーバー専用コードを置く場所として便利です。ただし、クライアント側の.svelte コンポーネントや通常の+page.ts から import しないことが前提です。サーバー専用処理は+page.server.ts +layout.server.ts +server.ts などから使うように整理します。

❓ external にしたのに本番で Cannot find module が出る

external はバンドルしない設定なので、実行時にはnode_modules から対象パッケージを読み込みます。Docker の runner ステージに依存パッケージが存在しない場合、本番実行時にCannot find module が出ることがあります。

設定に迷ったときの判断フロー

何をどこに書けばよいかわからなくなったら、次の順番で考えると整理しやすいです。

1

型チェックやエディタ補完の話か?

はい →tsconfig.json を確認します。include /exclude /compilerOptions の領域です。

2

ビルドや SSR の依存関係の話か?

はい →vite.config.ts を確認します。ssr.external /ssr.noExternal /rollupOptions.external の領域です。

3

SvelteKit の adapter や alias の話か?

はい →svelte.config.js を確認します。SvelteKit 本体の設定はここです。

4

本番でルートを見せたくない話か?

はい →exclude ではなく、ファイル配置、ルーティング、hooks.server.ts で制御します。


実践用の vite.config.ts / tsconfig.json 例

最後に、実運用で使いやすい形のサンプルをまとめます。必要に応じて、自分のプロジェクトに合わせて削ってください。

tsconfig.json

text
{
  "extends": "./.svelte-kit/tsconfig.json",
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "strict": true,
    "moduleResolution": "bundler"
  },
  "exclude": [
    "node_modules",
    "build",
    ".svelte-kit",
    "dist",
    "coverage",
    "playwright-report",
    "test-results"
  ]
}

vite.config.ts

ts
import { defineConfig } from 'vitest/config';
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';

const isExternal = (id: string) => {
  return (
    id === 'playwright' ||
    id === 'playwright-core' ||
    id === 'chromium-bidi' ||
    id.startsWith('playwright/') ||
    id.startsWith('playwright-core/') ||
    id.startsWith('chromium-bidi/')
  );
};

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],

  server: {
    port: 5160,
    strictPort: true
  },

  ssr: {
    external: ['playwright', 'playwright-core', 'chromium-bidi']
  },

  build: {
    rollupOptions: {
      external: isExternal
    }
  },

  test: {
    include: ['src/**/*.{test,spec}.{js,ts}']
  }
});

💡 この設定例の考え方

tsconfig.json では型チェック対象を整理し、vite.config.ts では Vite の開発・ビルド・SSR の挙動を制御しています。

特にplaywright 関連は、通常の画面表示では使わず、OG 画像生成などサーバー側の特定処理でだけ使う場合を想定しています。


まとめ

今回学んだこと

  • tsconfig.json は TypeScript の型チェックやエディタ補完のための設定
  • exclude はビルド除外ではなく、型チェック対象の調整
  • vite.config.ts は Vite の開発サーバー・ビルド・SSR 設定を扱う
  • SSR ビルドでバンドルしたくない依存はssr.external rollupOptions.external を検討する
  • external は削除ではなく、実行時にnode_modules から読む設定
  • src/routes に置いたものはルーティング対象になるため、exclude では制御できない
  • 本番で見せたくないルートは、ファイル配置やhooks.server.ts で制御する

📌 設定ファイルを分けて考える

SvelteKit の設定で迷ったら、「型チェックの話なのか」「ビルドの話なのか」「ルーティングの話なのか」を最初に分けると整理しやすくなります。

tsconfig.json でビルドを制御しようとしない。vite.config.ts で型チェックを制御しようとしない。この線引きを覚えておくだけで、設定まわりのトラブルはかなり解決しやすくなります。