概要
Svelteでcomponentを書く時に、中身をJSからTypescriptでかけるようにしました。
今回はデフォルトでできるプロジェクトに対して、最低限何があればTypescriptにできるかを重視してます。
なお、デフォルトに乗っ取りrollup
を使用するのでwebpack
とかでのやり方は対象外です。
手順
tsconfig.json追加
TypescriptのConfigファイルです。
こちらは手動での追加になります。
{
"compilerOptions": {
"target": "es6",
"baseUrl": "./"
},
"include": [
"./src"
]
}
追加パッケージ
yarn add -D svelte-preprocess typescript rollup-plugin-typescript2 rollup-plugin-postcss
package.jsonの修正
"main": "src/index.ts",
を追加
"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に変更
import App from './App.svelte';
new App({
target: document.body,
props: {
name: 'world'
}
})
svelte.d.tsの追加
これがないと、main.ts
がApp.svelte
を読み込まない
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の追加
import typescript from "rollup-plugin-typescript2"
import typescriptCompiler from "typescript"
import sveltePreprocessor from "svelte-preprocess"
inputの修正
main.js
をmain.ts
に変更
input: 'src/main.ts',
svelte()の修正
svelte
内に以下の3行を追加
extensions: [".svelte"]
preprocess: sveltePreprocessor()
emitCss: true
追加後のsvelte
svelte({
dev: !production,
css: css => {
css.write('public/build/bundle.css');
},
extensions: [".svelte"],
preprocess: sveltePreprocessor(),
emitCss: true,
}),
postcss()とtypescript()の追加
Typescriptのトランスパイラと、Typescriptで書いた.svelte
にCSSを適用させるpostcss
を追加
postcss({
extract: true
}),
typescript({ typescript: typescriptCompiler }),
最終的な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
にすることをこだわらなければ更に楽に書けると思います。