開発日誌

開発した時に躓いたこととかの記録

Svelteの書き方の特徴をざっくり語る

コンポーネントのファイルの構成

  • HTML、CSSJavaScriptを1ファイルにまとめるタイプ
    • このタイプ、CSSを書く場所に悩まなくて良いので好き
<script lang="ts">
   export let value: number = 0;
   export let text: string;
   export let min: number = 0;
   export let max: number = 255;
   export let step: number = 1;
</script>

<div class="root">
    <div class="label">{text}</div>
    <div class="slider"><input type="range" bind:value {min} {max} {step} /></div>
    <div class="num"><input type="number" bind:value {min} {max} {step} /></div>
</div>

<style lang="scss">
    .root {
        display: flex;
        .label {
            width: 5rem;
        }
        .num {
            width: 7rem;
        }
        .slider {
            width: 10rem;
        }
        div {
            margin: 0.25rem 0;
        }
        input {
            border-radius: 8px;
        }
    }
</style>

コンポーネントの引数定義

  • 下記のexportしているものがSvelteのコンポーネントの引数。
    • 初期値ないものがrequired。
export let value: number = 0;
export let text: string;
export let min: number = 0;
export let max: number = 255;
export let step: number = 1;
  • これ以上なくシンプル。Svelteのwrite less codeの思想を表現している点のひとつだと思う。
  • typeとして定義してる方がまとまってて好みという印象があるが、慣れかも。

jsの変数をCSSに渡したい時

  • JavaScript -> HTMLのstyleでCSS variableを定義 -> CSS という形になる
  • JavaScriptの変数を利用したい部分が少なければstyleにスタイル書くのもアリかもしれない
<script lang="ts">
   import type { ImgOptions } from './type';

   export let imgSrc: string;
   export let text: ImgOptions;
   export let mask: ImgOptions;
</script>

<div
    class="root"
    style="
  --text-blend-mode: {text.blendMode}; 
  --text-top: {text.top}px; --text-left: {text.left}px; 
  --text-red: {text.red}; --text-green: {text.green}; --text-blue: {text.blue}; --text-alpha: {text.alpha}; 
  --text-z-index: {text.layer};
  --mask-blend-mode: {mask.blendMode}; 
  --mask-top: {mask.top}px; --mask-left: {mask.left}px; 
  --mask-red: {mask.red}; --mask-green: {mask.green}; --mask-blue: {mask.blue}; --mask-alpha: {mask.alpha};
  --mask-z-index: {mask.layer};"
>
    <div class="imgWrapper">
        <p class="text">Welcome</p>
        <img src={`https://source.unsplash.com/${imgSrc ? imgSrc : 'Ak81Vc-kCf4'}`} alt="画像" />
    </div>
</div>

<style lang="scss">
    .root {
        display: flex;
        justify-content: center;
        margin: 48px;
        margin-bottom: 500px;
        .imgWrapper {
            position: relative;
            margin: 24px;
            img {
                width: 500px;
            }
            .text {
                display: block;
                position: absolute;
                font-size: 88px;
                font-weight: 700;
                top: var(--text-top);
                left: var(--text-left);
                margin: 0;
                z-index: var(--text-z-index);
                line-height: 1;
                color: rgba(var(--text-red), var(--text-green), var(--text-blue), var(--text-alpha));
                mix-blend-mode: var(--text-blend-mode);
            }

            &::before {
                position: absolute;
                display: block;
                width: calc(100% + 48px);
                height: calc(100% + 48px);
                content: '';
                top: var(--mask-top);
                left: var(--mask-left);
                background: rgba(var(--mask-red), var(--mask-green), var(--mask-blue), var(--mask-alpha));
                z-index: var(--mask-z-index);
                mix-blend-mode: var(--mask-blend-mode);
            }
        }
    }
</style>
  • Reactはcss in jsを使えばいい。CSS modules使ってる時はちょっと大変そう。
  • Astroは未調査だけどぱっと調べた感じだとSvelteと同じようなことをすることになりそう
    • Astro(.astro)はあまり動的なコンテンツ向けではない感があるので、jsを多用する場合はAstroのアイランドアーキテクチャを利用してReactとかVue.jsを利用した方がいいかも
  • Vue.jsはv-bindでjsの変数をCSS内にバインドすることができるらしい

headの書き換え方

  • <svelte:head>という独自タグを使う
  • 地味にフレームワークごとに書き方が違って面白い点だと思う
<script lang="ts">
   export let title: string;
</script>

<svelte:head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <link rel="icon" type="image/svg+xml" href="/mylogo.ico" />
    <meta name="description" content="=まなさすが作ったツール集" />
    <meta property="og:site_name" content="manasandbox" />
    <meta property="og:title" content={title} />
    <meta property="og:url" content="https://tools.manasas.dev" />
    <meta property="og:description" content="まなさすが作ったツール集" />
    <meta property="og:image" content="https://tools.manasas.dev/aza166.png" />
    <title>{title}</title>
</svelte:head>

<body>
    <header>
        <h1><a href="/">Mana's tools</a></h1>
    </header>
    <main>
        <slot />
    </main>
    <footer><a href="https://manasas.dev/" rel="me">© 2022 Manami SASAKI</a></footer>
</body>
  • app.html%sveltekit.head%に反映されるのだろうな、と思う
    • app.htmlが存在するフレームワークもなんか珍しい気がする。Next.jsやastroはこういう類はないのでなんか懐かしい印象がある。
<!DOCTYPE html>
<html lang="ja">
    <head>
       <meta charset="utf-8" />
       <link rel="icon" href="%sveltekit.assets%/mylogo.ico" />
       <meta name="viewport" content="width=device-width" />
       %sveltekit.head%
   </head>
    <body data-sveltekit-preload-data="hover">
        <div style="display: contents">%sveltekit.body%</div>
    </body>
</html>

学習用コンテンツ

  • Svelteは公式から下記のような書き換えて実行して学べるサンプルがたくさん用意されていて学びやすい
  • REPLという『コード片を実行できる仕組み』らしい。プログラミング入門にはかなりよさそう。
  • Svelteの公式、ちょっと重くて中々遷移できない時があるのは私だけだろうか。

おわりに

  • lessさは確かなのでプロトタイプにはかなり良さそう
  • 先の通りjsからCSSに渡すのはやや面倒なので、jsとcssが密接な場合は別フレームワークを検討した方が良さそう
  • 本番プロダクトに使うかは自分はまだちょっと保留。