search
LoginSignup
6

posted at

updated at

SvelteKitを使ってコンポーネントライブラリを作成してみよう!

はじめに

この記事は 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

スクリーンショット 2021-11-22 15.46.09.png

上記のように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.jstsconfig.jsonをそれぞれ設定します。

svelte.config.js
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で型定義もしておきます。

src/lib/Button.svelte
<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>
src/lib/index.js
export { default as Button } from './Button.svelte';

5. 実際に表示して試す

src/routes/index.svelteで呼び出して動くか試します。

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で起動して確認します。

スクリーンショット 2021-11-29 19.00.09.png

正常に動作していることが確認できました!

6. パッケージング機能を使ってパッケージングする

コンポーネントライブラリが完成したのでSvelteKitのパッケージング機能を使ってnpmにpublishできるようにパッケージングします。

型定義を自動生成させるにはsvelte2tsxtypescriptをインストールしておく必要があります。

今回はtypescriptは既にインストールしているのでsvelte2tsxをインストールします。

npm install -D svelte2tsx

これで準備ができたのでnpm run packageコマンドを実行するとプロジェクト直下にpackageフォルダが生成されます!

packageフォルダの中を見てみると、型定義ファイルが生成されていたり、Tailwind CSSで書いたスタイルがCSSとして出力されていたりして、ライブラリとしてこのままリリースできるようになっています。

package/Button.svelte
<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>
package/Button.svelte.d.ts
/** @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でコンポーネントライブラリ作れるって知らなかった!と思ってくださった方がいれば嬉しいです!

参考資料

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6