
こんにちは。よっしーです(^^)
今日は、SvelteKitでのパッケージングについて解説しています。
背景
SvelteKitでのパッケージングについて調査する機会がありましたので、その時の内容を備忘として記事に残しました。
package.jsonの構造
公開用ライブラリを構築する場合、package.jsonの内容がより重要になります。これを通じて、パッケージのエントリーポイント、npmに公開するファイル、ライブラリの依存関係を設定します。重要なフィールドを一つずつ見ていきましょう。
name
これはパッケージの名前です。この名前を使って他の人がインストールでき、https://npmjs.com/package/<name>で閲覧できるようになります。
{
"name": "your-library"
}
license
すべてのパッケージには、使用方法を他の人が理解できるようにするためのライセンスフィールドが必要です。配布や再利用に関して非常に寛容で、保証なしで使用できる非常に人気のあるライセンスがMITです。
{
"license": "MIT"
}
パッケージにはLICENSEファイルも含める必要があることに注意してください。
files
これは、npmがパッケージ化してnpmにアップロードするファイルを指定します。出力フォルダ(デフォルトではdist)を含める必要があります。package.json、README、LICENSEは常に含まれるため、指定する必要はありません。
{
"files": ["dist"]
}
不必要なファイル(ユニットテストやsrc/routesからのみインポートされるモジュールなど)を除外するには、.npmignoreファイルに追加します。これにより、パッケージのサイズが小さくなり、インストールが高速化されます。
exports
"exports"フィールドはパッケージのエントリーポイントを含みます。npx sv createで新しいライブラリプロジェクトを設定すると、単一のエクスポート(パッケージルート)に設定されます:
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
}
}
}
これは、パッケージにはルートという1つのエントリーポイントしかなく、すべてがそこを通じてインポートされるべきであることをバンドラーやツールに伝えます:
import { Something } from 'your-library';
typesとsvelteキーはエクスポート条件です。これらはyour-libraryインポート時にどのファイルを参照するかをツールに伝えます:
- TypeScriptは
types条件を見て型定義ファイルを参照します。型定義を公開しない場合は、この条件を省略します。 - Svelte対応ツールは
svelte条件を見て、これがSvelteコンポーネントライブラリであることを認識します。Svelteコンポーネントをエクスポートせず、非Svelteプロジェクトでも動作する可能性のあるライブラリ(例:Svelteストアライブラリ)を公開する場合、この条件をdefaultに置き換えることができます。
@sveltejs/packageの以前のバージョンではpackage.jsonエクスポートも追加されていましたが、現在はすべてのツールが明示的にエクスポートされていないpackage.jsonも扱えるため、テンプレートには含まれなくなりました。
exportsは好みに応じて調整し、より多くのエントリーポイントを提供できます。例えば、コンポーネントを再エクスポートするsrc/lib/index.jsファイルの代わりに、src/lib/Foo.svelteコンポーネントを直接公開したい場合、以下のようなエクスポートマップを作成できます:
{
"exports": {
"./Foo.svelte": {
"types": "./dist/Foo.svelte.d.ts",
"svelte": "./dist/Foo.svelte"
}
}
}
そして、ライブラリの利用者は以下のようにコンポーネントをインポートできます:
import Foo from 'your-library/Foo.svelte';
型定義を提供する場合、これを行うには追加の注意が必要です。注意点の詳細についてはこちらを参照してください。
一般的に、exportsマップの各キーはユーザーがパッケージから何かをインポートする際に使用するパスであり、値はインポートされるファイルへのパス、またはそれらのファイルパスを含むエクスポート条件のマップです。
解説
このセクションは、package.jsonのexportsフィールドについて詳しく説明しています。主なポイントを整理します:
- 基本的な構造:
- シンプルなルートエクスポート
- 型定義とSvelteコンポーネントの指定
- エクスポート条件の設定
- エクスポート条件:
types: TypeScript用の型定義svelte: Svelteコンポーネント用default: 一般的なJavaScript用
- カスタマイズ例:
- 個別コンポーネントのエクスポート
- パスマッピングの設定
- 型定義の考慮
- ベストプラクティス:
- 明確なエントリーポイントの定義
- 適切な型定義の提供
- ツール互換性の考慮
実装例:
{
"exports": {
// ルートエクスポート
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
},
// 個別コンポーネント
"./components": {
"types": "./dist/components/index.d.ts",
"svelte": "./dist/components/index.js"
},
// 特定のユーティリティ
"./utils": {
"types": "./dist/utils/index.d.ts",
"default": "./dist/utils/index.js"
}
}
}
このような設定により:
- クリーンなパッケージ構造の維持
- 効率的な型サポート
- 柔軟なインポートオプションの提供
が可能になります。
svelte
これは、Svelteコンポーネントライブラリをツールが認識できるようにするための従来のフィールドです。svelteエクスポート条件を使用する場合には必要ありませんが、エクスポート条件をまだ認識しない古いツールとの後方互換性のために、このフィールドを維持しておくことが推奨されます。これはルートエントリーポイントを指定する必要があります。
{
"svelte": "./dist/index.js"
}
解説
このセクションは、package.jsonのsvelteフィールドについて説明しています。主なポイントを詳しく解説します:
- 目的:
- Svelteライブラリの識別
- 古いツールとの互換性維持
- エントリーポイントの指定
- 現代的な代替手段:
exportsフィールドのsvelte条件- より柔軟な設定が可能
- より明確な意図の表現
- 使用例:
{
"name": "my-svelte-library",
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
}
},
"svelte": "./dist/index.js" // 後方互換性のため
}
- 注意点:
- 新しいプロジェクトでも含めることを推奨
- ルートエントリーポイントと一致させる
exportsフィールドと整合性を保つ
このフィールドは以下の場合に特に重要です:
- 古いビルドツールをサポートする必要がある場合
- 広範な互換性が必要な場合
- 既存のプロジェクトとの統合が必要な場合
ベストプラクティス:
- 常に
exportsフィールドと一緒に使用 - 同じパスを指定して一貫性を保つ
- ドキュメントに互換性情報を記載
sideEffects
package.jsonのsideEffectsフィールドは、モジュールがサイドエフェクトを含む可能性があるかどうかをバンドラーが判断するために使用されます。モジュールがインポートされた際に、モジュール外の他のスクリプトから観察可能な変更を行う場合、そのモジュールはサイドエフェクトを持つとみなされます。例えば、グローバル変数やJavaScriptの組み込みオブジェクトのプロトタイプを変更することなどがサイドエフェクトに含まれます。サイドエフェクトはアプリケーションの他の部分の動作に影響を与える可能性があるため、これらのファイル/モジュールは、そのエクスポートがアプリケーションで使用されているかどうかに関係なく、最終的なバンドルに含まれます。コードにサイドエフェクトを避けることがベストプラクティスです。
package.jsonのsideEffectsフィールドを設定することで、バンドラーが最終バンドルから未使用のエクスポートを除去する処理(ツリーシェイキング)をより積極的に行うことができます。これにより、より小さく効率的なバンドルが実現できます。各バンドラーはsideEffectsを様々な方法で処理します。Viteでは必要ありませんが、ライブラリがwebpackと互換性を持つように、すべてのCSSファイルにサイドエフェクトがあることを宣言することを推奨します。これは新しく作成されたプロジェクトに付属する設定です:
{
"sideEffects": ["**/*.css"]
}
ライブラリのスクリプトにサイドエフェクトがある場合は、sideEffectsフィールドを更新してください。新しく作成されたプロジェクトでは、デフォルトですべてのスクリプトがサイドエフェクトフリーとしてマークされています。サイドエフェクトを持つファイルが誤ってサイドエフェクトなしとしてマークされると、機能が壊れる可能性があります。
パッケージにサイドエフェクトを持つファイルがある場合、それらを配列で指定できます:
{
"sideEffects": [
"**/*.css",
"./dist/sideEffectfulFile.js"
]
}
これにより、指定されたファイルのみがサイドエフェクトを持つものとして扱われます。
解説
このセクションは、package.jsonのsideEffectsフィールドについて詳しく説明しています。主なポイントを整理します:
- サイドエフェクトとは:
- グローバル変数の変更
- プロトタイプの変更
- モジュール外部に影響を与える変更
- ツリーシェイキングへの影響:
- 未使用コードの除去
- バンドルサイズの最適化
- パフォーマンスの向上
- 設定パターン:
- CSSファイルの扱い
- 特定のJSファイルの指定
- グロブパターンの使用
- ベストプラクティス:
{
"sideEffects": [
// すべてのCSSファイル
"**/*.css",
// 特定のJSファイル
"./dist/specific-file.js",
// 特定のディレクトリ内のファイル
"./dist/effects/**/*.js"
]
}
この設定は以下の場合に特に重要です:
- webpack互換性の確保
- バンドルサイズの最適化
- 効率的なツリーシェイキング
- 正確な依存関係の管理
おわりに
今日は、 SvelteKitでのパッケージングについて解説しました。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)


コメント