Skip to main content

Frequently Asked Questions

SvelteKit で HMR を使うにはどうすればよいですか?

SvelteKit は svelte-hmr によってデフォルトで HMR が有効になっています。Rich の 2020 Svelte Summit のプレゼンテーション を見たことがあるなら、より強力そうに見えるバージョンの HMR をご覧になったかもしれません。あのデモでは svelte-hmrpreserveLocalState フラグがオンになっていました。このフラグは想定外の動作やエッジケースにつながる可能性があるため、現在はデフォルトでオフになっています。でもご心配なく、SvelteKit で HMR を利用することはできます!もしローカルの状態を保持したい場合は、svelte-hmr ページに説明があるように、@hmr:keep または @hmr:keep-all ディレクティブを使用することができます。

package.json の詳細をアプリケーションに含めるにはどうすればよいですか?

SvelteKit は svelte.config.js を ES module として想定しているため、JSON ファイルを直接要求することはできません。もしアプリケーションに package.json からバージョン番号またはその他の情報を含めたい場合は、このように JSON をロードすることができます:

svelte.config.js
ts
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
const file = fileURLToPath(new URL('package.json', import.meta.url));
const json = readFileSync(file, 'utf8');
const pkg = JSON.parse(json);

パッケージをインクルードしようとするとエラーが発生するのですが、どうすれば直せますか?

ライブラリのインクルードに関する問題は、ほとんどが不適切なパッケージングによるものです。ライブラリのパッケージングが Node.js に対応しているかどうかは、publint の web サイト でチェックできます。

以下は、ライブラリが正しくパッケージングされているかどうかをチェックする際に気を付けるべき点です:

  • exportsmainmodule などの他のエントリーポイントのフィールドよりも優先されます。exports フィールドを追加すると、deep import を妨げることになるため、後方互換性が失われる場合があります。
  • "type": "module" が指定されていない限り、ESM ファイルは .mjs で終わる必要があり、CommonJS ファイルは .cjs で終わる必要があります。
  • exports が定義されていない場合、main を定義する必要があり、それは CommonJS ファイル か ESM ファイル でなければならず、前項に従わなければならない。module フィールドが定義されている場合、ESM ファイルを参照している必要があります。
  • Svelte コンポーネントは、コンパイルされていない .svelte ファイルとして配布し、パッケージに含まれる JS は ESM のみとして記述していなければなりません。TypeScript などのカスタムスクリプトや SCSS などのスタイル言語は、それぞれ vanilla JS と CSS にするために前処理(preprocess)をしなければなりません。Svelte ライブラリのパッケージングには、svelte-package を使用することを推奨しています。このパッケージによって、これらの作業が行われます。

ライブラリが ESM バージョンを配布している場合、特に Svelte コンポーネントライブラリがその依存関係に含まれている場合、Vite を使用するとブラウザ上で最適に動作します。ライブラリの作者に ESM バージョンを提供するよう提案すると良いでしょう。しかし、CommonJS (CJS) の依存関係も上手く扱えるようにするため、デフォルトで、vite-plugin-svelte が Vite にそれらを事前バンドルするよう指示します。Vite は esbuild を使ってそれらを ESM に変換します。

それでもまだ問題が解消されない場合は、Vite の issue tracker と 該当のライブラリの issue tracker を検索することを推奨します。optimizeDepsssr の設定値をいじることで問題を回避できる場合もありますが、これはあくまで一時的な回避策とし、問題のあるライブラリの修正を優先したほうが良いでしょう。

SvelteKit で X を使うにはどうすればよいですか?

ドキュメントのインテグレーションのセクション をしっかり読み込んでください。それでも問題が解決しない場合のために、よくある問題の解決策を以下に示します。

データベースのセットアップはどう行えばよいですか?

データベースに問い合わせを行うコードを サーバールート(server route) に置いてください。.svelte ファイルの中でデータベースに問い合わせを行わないでください。コネクションをすぐにセットアップし、シングルトンとしてアプリ全体からクライアントにアクセスできるように db.js.ts のようなものを作ることができます。hooks.js.ts で1回セットアップするコードを実行し、データベースヘルパーを必要とするすべてのエンドポイントにインポートできます。

documentwindow に依存しているクライアントサイドオンリーなライブラリはどう使えばよいですか?

もし documentwindow 変数にアクセスする必要があったり、クライアントサイドだけで実行するコードが必要な場合は、browser チェックでラップしてください:

ts
import { browser } from '$app/environment';
if (browser) {
// client-only code here
}

コンポーネントが最初にDOMにレンダリングされた後にコードを実行したい場合は、onMount で実行することもできます:

ts
import { onMount } from 'svelte';
onMount(async () => {
const { method } = await import('some-browser-only-library');
method('hello world');
});

使用したいライブラリに副作用がなければ静的にインポートすることができますし、サーバー側のビルドでツリーシェイクされ、onMount が自動的に no-op に置き換えられます:

ts
import { onMount } from 'svelte';
import { method } from 'some-browser-only-library';
onMount(() => {
method('hello world');
});

一方、ライブラリに副作用があっても静的にインポートをしたい場合は、vite-plugin-iso-import をチェックして ?client インポートサフィックスをサポートしてください。このインポートは SSR ビルドでは取り除かれます。しかし、この手法を使用すると VS Code Intellisense が使用できなくなることにご注意ください。

ts
import { onMount } from 'svelte';
import { method } from 'some-browser-only-library?client';
onMount(() => {
method('hello world');
});

別のバックエンド API サーバーを使用するにはどうすれば良いですか?

外部の API サーバーにデータをリクエストするのに event.fetch を使用することができますが、CORS に対応しなければならず、一般的にはリクエストのプリフライトが必要になり、結果として高レイテンシーになるなど、複雑になることにご注意ください。別のサブドメインへのリクエストも、追加の DNS ルックアップや TLS セットアップなどのためにレイテンシーが増加する可能性があります。この方法を使いたい場合は、handleFetch が参考になるかもしれません。

別の方法は、頭痛の種である CORS をバイパスするためのプロキシーをセットアップすることです。本番環境では、/api などのパスを API サーバーに書き換えます(rewrite)。ローカルの開発環境では、Vite の server.proxy オプションを使用します。

本番環境で書き換え(rewrite)をセットアップする方法は、デプロイ先のプラットフォームに依存します。もし、書き換える方法がなければ、代わりに API route を追加します:

src/routes/api/[...path]/+server.js
ts
/** @type {import('./$types').RequestHandler} */
export function GET({ params, url }) {
return fetch(`https://my-api-server.com/${params.path + url.search}`);
}
src/routes/api/[...path]/+server.ts
ts
import type { RequestHandler } from './$types';
export const GET = (({ params, url }) => {
return fetch(`https://my-api-server.com/${params.path + url.search}`);
}) satisfies RequestHandler;

(必要に応じて、POST/PATCH などのリクエストもプロキシし、request.headers も転送(forward)する必要があることにご注意ください)

ミドルウェア(middleware)を使うにはどうすればよいですか?

adapter-node は、プロダクションモードで使用するためのミドルウェアを自分のサーバで構築します。開発モードでは、Vite プラグインを使用して Vite にミドルウェア(middleware) を追加することができます。例えば:

ts
import { sveltekit } from '@sveltejs/kit/vite';
/** @type {import('vite').Plugin} */
const myPlugin = {
name: 'log-request-middleware',
configureServer(server) {
server.middlewares.use((req, res, next) => {
console.log(`Got request ${req.url}`);
next();
});
}
};
/** @type {import('vite').UserConfig} */
const config = {
plugins: [myPlugin, sveltekit()]
};
export default config;

順序を制御する方法など、詳しくは Vite の configureServer のドキュメント をご覧ください。

Yarn 2 で動作しますか?

多少は。Plug'n'Play 機能、通称 'pnp' は動きません (Node のモジュール解決アルゴリズムから逸脱しており、SvelteKitが数多くのライブラリとともに使用しているネイティブの JavaScript モジュールではまだ動作しません)。.yarnrc.ymlnodeLinker: 'node-modules' を使用して pnp を無効にできますが、おそらく npm や pnpm を使用するほうが簡単でしょう。同じように高速で効率的ですが、互換性に頭を悩ませることはありません。

Yarn 3 を使用するにはどうすれば良いですか?

現時点の、最新の Yarn (version 3) の ESM サポート は experimental であるようです。

結果は異なるかもしれませんが、下記が有効なようです。

最初に新しいアプリケーションを作成します:

yarn create svelte myapp
cd myapp

そして Yarn Berry を有効にします:

yarn set version berry
yarn install

Yarn 3 global cache

Yarn Berry の興味深い機能の1つに、ディスク上のプロジェクトごとに複数のコピーを持つのではなく、パッケージ用に単一のグローバルキャッシュを持つことができる、というのがあります。しかし、enableGlobalCache の設定を true にするとビルドが失敗するため、.yarnrc.yml ファイルに以下を追加することを推奨します:

nodeLinker: node-modules

これによってパッケージはローカルの node_modules ディレクトリにダウンロードされますが、上記の問題は回避され、現時点では Yarn の version 3 を使用するベストな方法となります。