はじめに
この記事は Svelte Advent Calendar 2021 の1日目の記事です。
SvelteKitおよび、本記事で紹介するパッケージング機能は執筆時点(2021/12/1)ではバージョン1.0に到達しておらず、β版の状態となっていますので今後変更される可能性があります。
SvelteKitとは
SvelteでハイパフォーマンスなWebアプリを構築するためのフレームワーク。
ReactでいうNext、VueでいうNuxtの立ち位置と考えてもらうとわかりやすいと思います。
コンポーネントライブラリを作成する
SvelteKitは主にWebアプリを作成するフレームワークですが、コンポーネントライブラリも作成することができます。
実際に簡単なコンポーネントライブラリを作って一連の流れを説明していきます。
1.環境を構築する
npm init svelte my-component-library
上記のコマンドを使ってSvelteKitの環境を構築することができます。
✔ Which Svelte app template? › Skeleton project
✔ Add type checking? › TypeScript
✔ Add ESLint for code linting? … Yes
✔ Add Prettier for code formatting? … Yes
✔ Add Playwright for browser testing? … Yes
どのテンプレートを使うか聞かれるのでSkeleton project
を選択
TypeScriptやESLint、Prettierを使うかどうかも聞かれるので今回はすべてYesで作成していきます。
npm install
npm run dev
上記のようにWelcome to SvelteKit
と表示されれば環境構築完了です!
2.ディレクトリ構成を確認する
src
配下にroutes
フォルダがあります。ここに.svelte
ファイルを置くとそれがページになります。
コンポーネントライブラリを作る際はsrc/routes
をドキュメントサイトやデモサイトとして公開してもいいですし、開発に使用するサンドボックスとして使用することができます。
コンポーネントライブラリ自体のファイルはsrc/lib
に置きます。
3.Tailwind CSSとエイリアスの設定をする
※この章の設定に関してはSvelteKitでコンポーネントライブラリを作成する為に必須な設定ではありませんので不必要な方は飛ばしても大丈夫です。
今回はTailwind CSSを使用したいのでインストールと、エイリアスの設定をしたいと思います。
1.Tailwind CSSをインストールする
今回スタイルはTailwind CSSを使用します。
Tailwind CSSをSvelteKitで使うためには本来いろいろと面倒な設定が必要ですが、Svelte Addというものを利用することで1つコマンドを叩くだけで自動で設定できます。
npx svelte-add@latest tailwindcss
PostCSS
✅ successfully set up!
Create or find an existing issue at https://github.com/svelte-add/svelte-add/issues if this is wrong.
Tailwind CSS
✅ successfully set up!
Create or find an existing issue at https://github.com/svelte-add/svelte-add/issues if this is wrong.
このように表示されれば設定完です。
設定された新しい依存関係アップデートするためにnpm install
をしてください。
2.エイリアスを設定する
routes
配下を開発中のサンドボックスとして使いたいので実際のライブラリと同様のかたちで呼び出せるように設定します。この設定をすることで以下のエイリアス設定あり
のように呼び出すことができます。
import { Button } from '$lib/Button.svelte';
import { Button } from 'my-component-library';
エイリアスを設定するにはsvelte.config.js
とtsconfig.json
をそれぞれ設定します。
import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: [
preprocess({
postcss: true
})
],
kit: {
adapter: adapter(),
+ alias: {
+ 'my-component-library': 'src/lib'
+ }
}
};
export default config;
4.コンポーネントを作成する
準備ができたのでsrc/lib
配下にコンポーネントを作っていきます。
今回は簡単にButtonコンポーネントを作成したいと思います。
JSDocで型定義もしておきます。
<script>
/** @type {'default' | 'pill' | 'outline'} */
export let style = 'default';
/** @type {string} */
export let href = null;
</script>
{#if href}
<a {href}>
<button class={style}>リンクボタン</button>
</a>
{:else}
<button class={style}>ボタン</button>
{/if}
<style>
.default {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}
.pill {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full;
}
.outline {
@apply bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded;
}
</style>
export { default as Button } from './Button.svelte';
5. 実際に表示して試す
src/routes/index.svelte
で呼び出して動くか試します。
<script>
import { Button } from 'my-component-library';
</script>
<Button />
<Button style="pill" />
<Button style="outline" />
<Button href="https://www.google.com/" />
上記のようにindex.svelte
でButtonコンポーネントを呼び出して、npm run dev
で起動して確認します。
正常に動作していることが確認できました!
6. パッケージング機能を使ってパッケージングする
コンポーネントライブラリが完成したのでSvelteKitのパッケージング機能を使ってnpmにpublishできるようにパッケージングします。
型定義を自動生成させるにはsvelte2tsx
とtypescript
をインストールしておく必要があります。
今回はtypescript
は既にインストールしているのでsvelte2tsx
をインストールします。
npm install -D svelte2tsx
これで準備ができたのでnpm run package
コマンドを実行するとプロジェクト直下にpackage
フォルダが生成されます!
package
フォルダの中を見てみると、型定義ファイルが生成されていたり、Tailwind CSSで書いたスタイルがCSSとして出力されていたりして、ライブラリとしてこのままリリースできるようになっています。
<script>
/** @type {'default' | 'pill' | 'outline'} */
export let style = 'default';
/** @type {string} */
export let href = null;
</script>
{#if href}
<a {href}> <button class={style}> ボタン </button></a>
{:else}
<button class={style}> ボタン </button>
{/if}
<style>
.default {
border-radius: 0.25rem;
--tw-bg-opacity: 1;
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
.default:hover {
--tw-bg-opacity: 1;
background-color: rgba(29, 78, 216, var(--tw-bg-opacity))
}
.pill {
border-radius: 9999px;
--tw-bg-opacity: 1;
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
.pill:hover {
--tw-bg-opacity: 1;
background-color: rgba(29, 78, 216, var(--tw-bg-opacity))
}
.outline {
border-radius: 0.25rem;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgba(59, 130, 246, var(--tw-border-opacity));
background-color: transparent;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
font-weight: 600;
--tw-text-opacity: 1;
color: rgba(29, 78, 216, var(--tw-text-opacity))
}
.outline:hover {
border-color: transparent;
--tw-bg-opacity: 1;
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}</style>
/** @typedef {typeof __propDef.props} ButtonProps */
/** @typedef {typeof __propDef.events} ButtonEvents */
/** @typedef {typeof __propDef.slots} ButtonSlots */
export default class Button extends SvelteComponentTyped<{
style?: "default" | "pill" | "outline";
href?: string;
}, {
[evt: string]: CustomEvent<any>;
}, {}> {
}
export type ButtonProps = typeof __propDef.props;
export type ButtonEvents = typeof __propDef.events;
export type ButtonSlots = typeof __propDef.slots;
import { SvelteComponentTyped } from "svelte";
declare const __propDef: {
props: {
style?: 'default' | 'pill' | 'outline';
href?: string;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {};
};
export {};
これでコンポーネントライブラリが作成できました!
npm publish ./package
でnpmにpublishしたり、煮るなり焼くなりしてください!
おわりに
駆け足ではありましたが、SvelteKitを使ってコンポーネントライブラリを作成する流れを説明してきました!
Svelteでコンポーネントライブラリを作成するのって意外と簡単!とかSvelteKitでコンポーネントライブラリ作れるって知らなかった!と思ってくださった方がいれば嬉しいです!