Svelte ベースのフレームワーク「Sapper」を使ってみる・TypeScript + SCSS 対応する

昨日 Svelte を TypeScript + SCSS 対応したが、今度はこの Svelte をベースとしたフレームワーク「Sapper」を使ってみて、コイツも TypeScript + SCSS 化してみる。

目次

成果物

先に成果物のソースコード全量を紹介。コチラをコピーして使い回してもらえば、すぐに TypeScript 化できるであろう。

以下はまっさらな状態から TypeScript 化・SCSS 化していく手順。

Sapper プロジェクトを作成する

まずは Sapper プロジェクトを作成する。公式で紹介されているとおり、degit を使っていく。

$ npx degit 'sveltejs/sapper-template#rollup' practice-sapper
$ cd practice-sapper/

# Git 管理したかったので以下のように作業した
$ git init
$ git commit --allow-empty -m 'Init'
$ git remote add origin https://github.com/Neos21/practice-sapper.git

TypeScript 対応する

TypeScript 化の手順は以下のサイトを参考にした。

上の文献は rollup-plugin-typescript2 を使っているが、Svelte 公式が TypeScript 化する際に利用している @rollup/plugin-typescript を代わりに利用することにした。

$ npm i -D @rollup/plugin-typescript svelte-preprocess typescript tslib

以降、いくつかファイルを変更していく。

tsconfig.json を新規で作る

{
  "include": ["src/**/*", "types/@sapper/index.d.ts"],
  "exclude": ["node_modules/*"],
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "types": ["svelte", "node", "@sapper"],
    "typeRoots": ["typings"]
  }
}

rollup.config.js を編集する

ココが面倒臭い。編集を入れた行だけ説明していく。

// 以下2つを追加する
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';

module.exports = {
  client: {
    input: config.client.input().replace((/\.js$/u), '.ts'),  // ← 拡張子 .ts を認識させる
    // …
    plugins: [
      // …
      svelte({
        preprocess: sveltePreprocess(),  // ← svelte() の最初に追加する
        // …
      }),
      // …
      commonjs(),
      typescript(),  // ← commonjs() の直後に入れる
    // …
  },
  
  server: {
    input: config.server.input().server.replace((/\.js$/u), '.ts'),  // ← ココだけ「.server.」が入るので注意
    plugins: [
      // …
      svelte({
        preprocess: sveltePreprocess(),  // ← 追加
        // …
      }),
      // …
      commonjs(),
      typescript(),  // ← 追加
    // …
  },
  
  serviceworker: {
    input: config.serviceworker.input().replace((/\.js$/u), '.ts'),  // ← 変更
    plugins: [
      // …
      commonjs(),
      typescript(),  // ← 追加
    // …
  }
};

Svelte に svelte-preprocess をかませるのと、commonjs() の直後に typescript() を入れるのが主。あと input を書き換えて .ts ファイルを読み込むようにする。

typings/@sapper/index.d.ts を作る

型定義ファイル。

$ mkdir -p ./typings/@sapper/
$ cat <<EOL > ./typings/@sapper/index.d.ts
declare module '@sapper/app';
declare module '@sapper/server';
declare module '@sapper/service-worker';
EOL

.js ファイルを .ts ファイルに変更する

ココまでの対応で、src/ 配下にある拡張子 .js のファイルは、全て拡張子 .ts に変更できるようになった。

$ mv ./src/client.js ./src/client.ts
$ mv ./src/server.js ./src/server.ts
$ mv ./src/service-worker.js ./src/service-worker.ts

これらのファイルで TypeScript が使えているか確認したければ、適当な変数に : string とか : boolean とか型宣言を入れてやれば良いだろう。

src/routes/blog/ 配下の .js ファイルたちも .ts に変更可能だが、_posts.jsimport しているところがあるので、import から拡張子を消すこと。

.svelte<script>lang="ts" を追加する

最後に .svelte ファイルたちを編集する。

部分を

に変更する。

こうすれば TypeScript が書けるようになる。

SCSS 対応する

ここまでの対応ができていれば、SCSS 対応は簡単。svelte-preprocess が既に入っているので、sass パッケージをインストールするだけで良い。

$ npm i -D sass

そしたら全ての .svelte ファイルで、

部分を

に書き換えてやれば、SCSS が書けるようになる。

Cypress 関連のファイルを消す

Sapper にはデフォルトで Cypress を利用したテストコードが用意されているが、肝心の Cypress 自体が devDependencies に存在しない。使ってみようとしたらうまく動かず、変にパーミッションが変更されて鬱陶しかったので、消してしまった。

$ rm cypress.json
$ rm -rf ./cypress/

package.json の npm-scripts に書かれている

は削除してしまおう。コレで他に使っている箇所もなくなったので、npm-run-all を依存パッケージから外して大丈夫。

以上

コレで

が動作するようになっているはずだ。

Svelte 単体にはないルーティングや SSR の機構が備わっており、開発はより行いやすそうな印象。

一方で、ボイラープレートのコードは汚く、Rollup の設定などまだまだお手製感が強い感じ。Svelte は大規模開発には向かないかなー。