Sapper からの移行
SvelteKit は Sapper の後継であり、その設計の多くの要素を共有しています。
もし、既存の Sapper アプリを SvelteKit に移行する予定がある場合、いくつかの変更が必要になります。移行する際には、examples を見ていただくと参考になると思います。
package.json
type: “module”
package.json
に "type": "module"
を追加します。もし Sapper 0.29.3 以降を使用している場合は、インクリメンタルマイグレーションの一部として、このステップを他のステップとは別に行うことができます。
dependencies
polka
や express
を使用している場合はそれを削除し、sirv
や compression
などのミドルウェア(middleware)も削除します。
devDependencies
devDependencies
から sapper
を削除し、@sveltejs/kit
と使用予定の adapterに置き換えます(次のセクションをご覧ください)。
scripts
sapper
を参照しているスクリプトを全て更新します:
sapper build
は、Node adapter を使用したvite build
に更新しますsapper export
は、static adapter を使用したvite build
に更新しますsapper dev
はvite dev
に更新しますnode __sapper__/build
はnode build
に更新します
プロジェクトファイル
アプリの大部分を占める src/routes
の中はそのままで大丈夫ですが、いくつかのプロジェクトファイルを移動または更新する必要があります。
Configuration
こちらに記載されている通り、webpack.config.js
または rollup.config.js
を svelte.config.js
に置き換えてください。Svelte の preprocessor オプション は config.preprocess
に移動してください。
adapter を追加する必要があります。sapper build
は adapter-node とおおよそ同じで、sapper export
は adapter-static とおおよそ同じですが、デプロイ先のプラットフォーム向けにデザインされた adapter を使用するのも良いでしょう。
Vite では自動的に処理されないファイルタイプのプラグインを使用している場合は、Vite において同等なことを行う方法を探し、Vite config に追加する必要があります。
src/client.js
SvelteKit にはこのファイルに相当するものはありません。カスタムロジック(sapper.start(...)
以降) は、+layout.svelte
ファイルで、onMount
コールバック内に記述してくさい。
src/server.js
adapter-node
を使用する場合は、custom server がこれと同等のものです。それ以外の場合は、同等のものに該当するものはありません。なぜなら SvelteKit アプリはサーバーレス環境でも実行可能だからです。
src/service-worker.js
@sapper/service-worker
からインポートするほとんどのものは、$service-worker
に同等なものがあります:
files
は変更されていませんroutes
は削除されましたshell
は現在build
になりましたtimestamp
は現在version
になりました
src/template.html
src/template.html
は src/app.html
にリネームする必要があります。
%sapper.base%
、%sapper.scripts%
、%sapper.styles%
を削除します。%sapper.head%
を %sveltekit.head%
に、%sapper.html%
を %sveltekit.body%
にそれぞれ置き換えます。<div id="sapper">
はもう必要ありません。
src/node_modules
Sapper アプリでよくあるパターンとして、内部ライブラリを src/node_modules
内のディレクトリに配置する、というものがあります。これは Vite だと動作しないため、代わりに src/lib
を使用します。
ページとレイアウト
名前が変わったファイル
ルート(Routes)は曖昧さをなくすためフォルダ名のみで構成されるようになり、+page.svelte
までのフォルダ名がルート(route)に対応するようになりました。概要は ルーティングのドキュメント をご参照ください。以下は 新/旧 の比較です:
Old | New |
---|---|
routes/about/index.svelte | routes/about/+page.svelte |
routes/about.svelte | routes/about/+page.svelte |
カスタムのエラーページコンポーネントは _error.svelte
から +error.svelte
にリネームしてください。また、どの _layout.svelte
ファイルも、同様に +layout.svelte
にリネームしてください。その他のファイルは無視されます.
Imports
@sapper/app
からインポートしていた goto
、prefetch
、prefetchRoutes
は、$app/navigation
からインポートする goto
、preloadData
、preloadCode
にそれぞれ置き換えてください。
@sapper/app
からインポートしていた stores
については置き換える必要があります — 以下の Stores をご覧ください。
src/node_modules
にあるディレクトリからインポートしてたファイルは、$lib
からのインポートに置き換えてください。
Preload
以前と同様に、ページやレイアウトではレンダリングが行われる前にデータをロードできる関数をエクスポートすることができます。
This function has been renamed from preload
to load
, it now lives in a +page.js
(or +layout.js
) next to its +page.svelte
(or +layout.svelte
), and its API has changed. Instead of two arguments — page
and session
— there is a single event
argument.
There is no more this
object, and consequently no this.fetch
, this.error
or this.redirect
. Instead, you can get fetch
from the input methods, and both error
and redirect
are now thrown.
Stores
Sapper では、提供されるストアをこのように参照していたかと思います:
import { module "@sapper/app"
stores } from '@sapper/app';
const { const preloading: any
preloading, const page: any
page, const session: any
session } = module "@sapper/app"
stores();
page
と session
ストアはまだ存在しています。preloading
は、from
プロパティと to
プロパティを含む navigating
ストアに置き換えられました。page
は url
、params
を持つようになりましたが、path
と query
はありません。
SvelteKit では、それらにアクセスする方法が異なります。stores
は getStores
になりましたが、$app/stores
から直接 navigating
、page
、session
をインポートできるので、ほとんどの場合は必要ありません。
ルーティング
ルート(routes) の正規表現はもうサポートされていません。代わりに、advanced route matching をお使いください。
Segments
以前までは、レイアウトコンポーネントは子のセグメントを表す segment
プロパティを受け取っていましたが、この機能は削除されました。より柔軟な $page.url.pathname
の値を使用し、お望みのセグメントを取得してください。
URLs
Sapper では、相対 URL は、現在のページに対してではなく、base URL (basepath
オプションが使用されていない限り、大抵の場合は /
) に対して解決されていました。
これによって問題が発生していましたが、SvelteKit ではもうそのようなことはありません。相対 URL が現在のページ (または load
関数の fetch
URL の場合は移動先のページ) に対して解決されるようになりました。多くの場合、(例えば、/
始まるような) ルート相対な URL を使用するほうが簡単です。なぜなら、それらの意図がコンテキストに依存しないからです。
<a> attributes
sapper:prefetch
はdata-sveltekit-preload-data
になりましたsapper:noscroll
はdata-sveltekit-noscroll
になりました
Endpoints
Sapper では、サーバールート(server routes) は、Node の http
モジュール によって公開される req
と res
オブジェクト(または Polka や Express などのフレームワークが提供するその拡張版) を受け取っていました。
SvelteKit は、アプリが動作する場所に依存しないように設計されています(Node サーバーで動作し、サーバーレスプラットフォームや Cloudflare Worker でも同様に動作します)。そのため、もう req
と res
を直接扱いません。エンドポイントを、新しいシグネチャに合わせて更新する必要があります。
環境非依存な動作をサポートするため、グローバルコンテキストで fetch
が利用できるようになり、node-fetch
や cross-fetch
などのサーバーサイドの fetch 実装をインポートする必要がなくなりました。
インテグレーション
インテグレーションに関する詳細情報については インテグレーション をご参照ください。
HTML minifier
Sapper はデフォルトで html-minifier
を含んでいました。SvelteKit はこれを含まないのですが、本番環境向けの依存関係(prod dependency)としてこれを追加し、hook で使用することができます:
import { module "html-minifier"
minify } from 'html-minifier';
import { const building: boolean
SvelteKit analyses your app during the build
step by running it. During this process, building
is true
. This also applies during prerendering.
building } from '$app/environment';
const const minification_options: {
collapseBooleanAttributes: boolean;
collapseWhitespace: boolean;
conservativeCollapse: boolean;
decodeEntities: boolean;
html5: boolean;
ignoreCustomComments: RegExp[];
minifyCSS: boolean;
... 8 more ...;
sortClassName: boolean;
}
minification_options = {
collapseBooleanAttributes: boolean
collapseBooleanAttributes: true,
collapseWhitespace: boolean
collapseWhitespace: true,
conservativeCollapse: boolean
conservativeCollapse: true,
decodeEntities: boolean
decodeEntities: true,
html5: boolean
html5: true,
ignoreCustomComments: RegExp[]
ignoreCustomComments: [/^#/],
minifyCSS: boolean
minifyCSS: true,
minifyJS: boolean
minifyJS: false,
removeAttributeQuotes: boolean
removeAttributeQuotes: true,
removeComments: boolean
removeComments: false, // some hydration code needs comments, so leave them in
removeOptionalTags: boolean
removeOptionalTags: true,
removeRedundantAttributes: boolean
removeRedundantAttributes: true,
removeScriptTypeAttributes: boolean
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: boolean
removeStyleLinkTypeAttributes: true,
sortAttributes: boolean
sortAttributes: true,
sortClassName: boolean
sortClassName: true
};
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle(input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}): MaybePromise<...>
handle({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) {
let let page: string
page = '';
return resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event, {
ResolveOptions.transformPageChunk?(input: {
html: string;
done: boolean;
}): MaybePromise<string | undefined>
Applies custom transforms to HTML. If done
is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML
(they could include an element’s opening tag but not its closing tag, for example)
but they will always be split at sensible boundaries such as %sveltekit.head%
or layout/page components.
transformPageChunk: ({ html: string
html, done: boolean
done }) => {
let page: string
page += html: string
html;
if (done: boolean
done) {
return const building: boolean
SvelteKit analyses your app during the build
step by running it. During this process, building
is true
. This also applies during prerendering.
building ? module "html-minifier"
minify(let page: string
page, const minification_options: {
collapseBooleanAttributes: boolean;
collapseWhitespace: boolean;
conservativeCollapse: boolean;
decodeEntities: boolean;
html5: boolean;
ignoreCustomComments: RegExp[];
minifyCSS: boolean;
... 8 more ...;
sortClassName: boolean;
}
minification_options) : let page: string
page;
}
}
});
}
サイトのプロダクションビルドをテストするのに vite preview
を使用しているときは、prerendering
が false
となることにご注意ください。そのため、minify の結果を検証するには、ビルド済の HTML を直接確認する必要があります。