LoginSignup
8
8

More than 3 years have passed since last update.

【Svelte】最低限の修正でTypeScript対応してみました【初期設定】

Last updated at Posted at 2020-03-06

概要

Svelteでcomponentを書く時に、中身をJSからTypescriptでかけるようにしました。
今回はデフォルトでできるプロジェクトに対して、最低限何があればTypescriptにできるかを重視してます。

なお、デフォルトに乗っ取りrollupを使用するのでwebpackとかでのやり方は対象外です。

手順

tsconfig.json追加

TypescriptのConfigファイルです。
こちらは手動での追加になります。

tsconfig.json
{
    "compilerOptions": {
      "target": "es6",
      "baseUrl": "./"
    },
    "include": [
      "./src"
    ]
  }

追加パッケージ

console
yarn add -D svelte-preprocess typescript rollup-plugin-typescript2 rollup-plugin-postcss

package.jsonの修正

"main": "src/index.ts",を追加

package.json
  "name": "svelte-app",
  "version": "1.0.0",
  "main": "src/index.ts",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "start": "sirv public"
  },

main.jsをmain.tsに変更

main.ts
import App from './App.svelte';

new App({
    target: document.body,
    props: {
        name: 'world'
    }
  })

svelte.d.tsの追加

これがないと、main.tsApp.svelteを読み込まない

svelte.d.ts
declare module "*.svelte" {
    interface ComponentOptions<Props> {
      target: HTMLElement;
      anchor?: HTMLElement;
      props?: Props;
      hydrate?: boolean;
      intro?: boolean;
    }

    interface Component<Props> {
      new (options: ComponentOptions<Props>): any;
      $set: (props: {}) => any;
      $on: (event: string, callback: (event: CustomEvent) => any) => any;
      $destroy: () => any;
      render: (props?: {}) => {
        html: string;
        css: { code: string; map?: string };
        head?: string;
      };
    }

    const component: Component<{}>;

    export default component;
}

rollup.config.jsの修正

importの追加

3種類のImportの追加

rollup.config.js
import typescript from "rollup-plugin-typescript2"
import typescriptCompiler from "typescript"
import sveltePreprocessor from "svelte-preprocess"

inputの修正

main.jsmain.tsに変更

rollup.config.js
input: 'src/main.ts',

svelte()の修正

svelte内に以下の3行を追加

rollup.config.js
extensions: [".svelte"]
preprocess: sveltePreprocessor()
emitCss: true

追加後のsvelte

rollup.config.js
        svelte({
            dev: !production,
            css: css => {
                css.write('public/build/bundle.css');
            },
            extensions: [".svelte"],
            preprocess: sveltePreprocessor(),
            emitCss: true,
        }),

postcss()とtypescript()の追加

Typescriptのトランスパイラと、Typescriptで書いた.svelteにCSSを適用させるpostcssを追加

rollup.config.js
        postcss({
            extract: true
        }),
        typescript({ typescript: typescriptCompiler }),

最終的なrollup.config.js

rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from "rollup-plugin-postcss"
import typescript from "rollup-plugin-typescript2"
import typescriptCompiler from "typescript"
import sveltePreprocessor from "svelte-preprocess"

const production = !process.env.ROLLUP_WATCH;

export default {
    input: 'src/main.ts',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/build/bundle.js'
    },
    plugins: [
        svelte({
            dev: !production,
            css: css => {
                css.write('public/build/bundle.css');
            },
            extensions: [".svelte"],
            preprocess: sveltePreprocessor(),
            emitCss: true,
        }),
        resolve({
            browser: true,
            dedupe: ['svelte']
        }),
        postcss({
            extract: true
        }),
        typescript({ typescript: typescriptCompiler }),
        commonjs(),
        !production && serve(),
        !production && livereload('public'),
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};

function serve() {
    let started = false;

    return {
        writeBundle() {
            if (!started) {
                started = true;

                require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
                    stdio: ['ignore', 'inherit', 'inherit'],
                    shell: true
                });
            }
        }
    };
}

まとめ

冒頭にあったとおり最低限の修正なので、使いやすさを考えたらrollupをもう少しplugin追加したほうがよいです。
main.jsのTypescript化で詰まったり、CSS読み込みで詰まったりとありましたが
とりあえずそのあたりもクリアしてTypeScriptでSvelteが書けるようになりました。

追加 2020/03/09

恐らく、main.tsではなくmain.jsのままであれば、追加パッケージのtypescriptがいらないです。
rollupのtypescript({ typescript: typescriptCompiler }),この行もいらなくなります。

理由としては、. svelteファイルののts部分についてはsvelte-preprocessがトランスパイルしちゃうので使わないですね。
なのでmain.jsを極力コード量減らして、.tsにすることをこだわらなければ更に楽に書けると思います。

8
8
0

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
  3. You can use dark theme
What you can do with signing up
8
8