React と Svelte を比べて感じたこと

フロントエンドエンジニアの氏家です。

最近、JavaScriptフレームワークであるSvelteに関する記事を多く見かけるようになりました。 僕の中で「何か新しいフレームワークが出てるなぁ」から「面白そうだし触ってみよう」という気持ちに変わったので、vivit の数多くのプロダクトで採用している React と新進気鋭な Svelte を比べてみて、何がどう違うのか体系的に学んでいこうと思います。

f:id:ijimakenta:20220116231353p:plain

そもそも Svelte とは

https://svelte.jp/ では以下のように説明されています。

Svelte はユーザーインタフェースを構築する先鋭的で新しいアプローチです。React や Vue のような 従来のフレームワークがその作業の大部分を ブラウザ で行うのに対し、 Svelte はその作業を アプリをビルドする際の コンパイル時 に行います。

Svelte は仮想 DOM による差分検出のようなテクニックを使用する代わりに、 アプリケーションの状態が変化したときに DOM を外科的に更新するコードを生成します。

Svelteコンパイラである」とも言われており、記述したコードをプレーンな (vanilla) JavaScriptコンパイルします。そのため、バンドルサイズやメモリ使用量が最低限で済み、アプリケーションのロードや実行を高速化してくれます。

React と Svelte のコードの違い

百聞は一見にしかず、 React のコードと Svelte のコードを比べてみましょう。

作成するのは<Button name="hoge" />で呼び出して使うことができる、クリックするたびにカウントされるボタンコンポーネントです。

f:id:rugk:20220106171635p:plain
レンダリングされるもの

React

まずは React のコードを書いてみます。 今回は vivit のプロダクトでも採用している、@Takepepeさんの経年劣化に耐える ReactComponent の書き方に習い記述していきます。

qiita.com

/Button.tsx

import { useState } from "react";
import styled from "styled-components";

export type ContainerProps = {
  name: string;
};

type Props = {
  className?: string;
  count: number;
  handleClick: () => void;
} & ContainerProps;

const Component = ({
  name,
  className,
  count,
  handleClick,
}: Props): JSX.Element => (
  <div className={className}>
    <button className="button" onClick={handleClick}>
      {name}{count}</button>
  </div>
);

const StyledComponent = styled(Component)`
  padding: 10px;
  .button {
    color: #333;
  }
`;

export const Button = (props: ContainerProps): JSX.Element => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };
  return <StyledComponent {...props} count={count} handleClick={handleClick} />;
};

このぐらい単純だと分かりやすいですね。 それぞれの層で何が行われているかもすぐに理解することができます。

Svelte

次にこれを Svelte で書いてみます。

/Button.svelte

<script lang="ts">
  export let name: string = "";
  let count: number = 0;
  const handleClick = () => {
    count++;
  };
</script>

<div class="wrapper">
  <button class="button" on:click="{handleClick}">{name}が{count}匹</button>
</div>

<style lang="scss">
  .wrapper {
    padding: 10px;
    .button {
      color: #333;
    }
  }
</style>

コード量が React の半分になりました。 さらに、 Svelte のコードを見慣れない方でもこのコードが何をやっているか一目瞭然です。 書き方は Vue.js に似ているかもしれません。

もう少し詳しく見ていきます。

Script

<script lang="ts">
  export let name: string = "";
  let count: number = 0;
  const handleClick = () => {
    count++;
  };
</script>

ここではモジュールやコンポーネントを import したり、コンポーネントの props を定義したり、 React でいう hooks を使用したりします。 props の定義をexportと書くのは違和感があるかもしれませんが、すぐに慣れてしまいます。

コードから分かると思いますが、状態管理を単なる変数で行っているのも Svelte の特徴の一つですね。

また、 Svelte は正式に TypeScript をサポートしているので、開発体験が損なわれることもありません。

DOM

<div class="wrapper">
  <button class="button" on:click="{handleClick}">{name}が{count}匹</button>
</div>

ここでは DOM(HTML テンプレート)を定義しています。 初めからロジックや状態管理のコードが分離されているので、レイアウトのみの Stateless なレイヤーになっています。

Style

<style lang="scss">
  .wrapper {
    padding: 10px;
    .button {
      color: #333;
    }
  }
</style>

SvelteSCSS もサポートしており、 ReactStyledComponents を使用して開発していた方は同じようにスタイリングすることができます。

ここで書いたスタイルは完全にコンポーネントに閉じており、例えば以下のように、

div {
  padding: 10px;
}

と書いたとしても、親コンポーネント(や子コンポーネント)で定義されたdivタグにpadding: 10pxが適用されることはありません。

比べて感じたこと

まずはじめに感じたのは、最近のモダンなフレームワークの中では学習コストが低いということです。 私はフロントエンドエンジニアとして開発に携わる際に、様々な技術や知識を勉強しました。 特に React では JSXhooksCSS in JS などの概念を覚えるのに苦戦した記憶があります。

それに比べて Svelte は、<script>で囲まれた単純な JavaScript<style>で囲まれた単純なCSS、レイアウトをつくるHTMLのみで構成されており、状態管理の方法について覚える必要も、複雑なライブラリを導入する必要もありません。 HTML、CSSJavaScriptさえ書ければ、すぐにでも Svelte で開発できます。

もう1つ感じたのは、開発体験が抜群に良いということです。 主に以下の点が挙げられます。

特にコードの記述量を減らせる点はとても大きかったです。 Svelte 独自の記法などはあるものの、シンプルで分かりやすいため可読性が大幅に上がり、実装コストも下がります。

まとめ

ここまで ReactSvelte の違いについて書きましたが、どちらが優れいている、というわけではありません。 どちらのフレームワークにもメリット、デメリットが存在しており、プロダクトやチームで行われる技術選定によって適切なものを使用すべきだと思います。

しかし、個人的な感想としては Svelte による開発の方が、 React に比べて「分かりやすくて、楽しい」と感じました。

実際、State of JS 2020で満足度・関心のランキングで Svelte が1位を獲得しています。

2020.stateofjs.com

おわりに

vivitではまだ Svelte を使用した開発は行っておりませんが、ちょっとしたLPなどの制作であれば積極的に採用していきたいです。

また、SvelteKitが正式にリリースされればより大規模なアプリケーション開発に採用していけると思うので楽しみです。

今は逸る気持ちを抑えて、個人で Svelte 開発を楽しみたいと思います。


vivit株式会社ではモダンな環境でアウトドア事業を成長させていくエンジニアを募集しています。 また、23卒の新卒エンジニア採用も行っていますので、詳しくは下記をご覧下さい。

www.wantedly.com