Open4

Svelte+Typescript+UIKit+Vite

PotewoPotewo

Svelte + Typescript + UIKit + Viteでの組み合わせ方がよくわからなかったのでメモ。基本的に自分用のメモなので雑に書いています。

こういう方法を使うともっと楽をできるだとか、こっちのほうが簡単だというコメントは大歓迎です。

目標

上の組み合わせで簡単にちょっとしたGUIツールとかを作れるようになりたい。
ガチのフロントエンドをやりたいわけではなくてほしいツールをほしいときにサクッと作れるようになりたい。

Typescriptを使う理由

GoとかC++とか型がある言語をLSPの機能で型を見たり定義にジャンプするのが気持ち良くてなんとなく効率が良さそうなので型がほしかった。
Typescriptは人権だと聞いたから。なんか流行っているから。

Svelteを使う理由

better vueと聞いたので。コードが短く書けるのはうれしい。
VueだとVue2の情報とVue3の情報が入り混じってたりTypescriptとJavascriptの情報が入り混じってたりしてほしいものを探すのが大変そうな気がした。Reactはサクッと作るには大げさな気がした。ただSvelteをしばらくやってみてやはり情報が少ない傾向は否めないので素直にVueを使ったほうが良かったかもしれないとは思っている。

UIKitを使う理由

ガチのフロントエンドをやりたいわけではないので、ボタンとかのデザインもこだわりはしないけど最低限きれいにしたい。
UIKitはボタンとかヘッダー(Navbar)とかの基本的な部品以外にも色々デザインがそろっていた。
ReactだとMaterial UIとかが楽そうだけどMaterial UIのSvelte版は色々と面倒そうな気がした。

Viteを使う理由

設定なしに簡単に動かせるところまで持っていける。ホットリロードが早い。

PotewoPotewo

Vite+Svelte+Typescript

yarn create
して、テンプレートにsvelte-tsを選べば一通り必要なものを揃えてくれる。

失敗したUIkitの読み込み方

loaduikit.scss

@import "uikit/src/scss/variables-theme.scss";
@import "uikit/src/scss/mixins-theme.scss";

@import "uikit/src/scss/uikit-theme.scss";

index.html

    <link rel="stylesheet" href="loaduikit.scss"/>
    <script src="/node_modules/uikit/dist/js/uikit.min.js"></script>
    <script src="/node_modules/uikit/dist/js/uikit-icons.min.js"></script>

最初は上のようにしていたが、localhost:3000/でアクセスするときちんと表示されたが、localhost:3000/newなどからアクセスするとUIkitのクラスがうまく読み込まれなかった。

このとき、svelte-routingをルーティングに使っていた。
src/App.svelte

<Header2 />
<main>
  <Router>
    <Route path="new">
      <New on:send={handleSend} bind:tags={tags} />
    </Route>
    <Route path="/" component="{NoteList}" bind:notes="{notes}" />
    <Route path="notes/:id" let:params>
      <Note note="{notes.find(obj => obj.uuid == params.id)}"/>
    </Route>
    <Route path="edit/:id" let:params>
      <Note note="{notes.find(obj => obj.uuid == params.id)}" isEditMode={true} />
    </Route>
  </Router>
</main>

解決した方法

How to setup global bootstrap via scss in Svelte? - Stack Overflowを参考にした。
src/main.ts

import App from './App.svelte'
import "../loaduikit.scss"
import "../node_modules/uikit/dist/js/uikit.min.js"
import "../node_modules/uikit/dist/js/uikit-icons.min.js"

const app = new App({
  target: document.getElementById('app')
})

export default app

index.htmlで読み込むやり方からmain.tsですべて読み込むように変えた。
どのパスでもきちんとUIkitが読み込まれていそう。

PotewoPotewo

エイリアスの設定

tsconfig.json

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "baseUrl": "./src",
    "paths": {
      "@utils/*": ["./utils/*"]
    },
    /**
     * Typecheck JS in `.svelte` and `.js` files by default.
     * Disable checkJs if you'd like to use dynamic types in JS.
     * Note that setting allowJs false does not prevent the use
     * of JS in `.svelte` files.
     */
    "allowJs": true,
    "checkJs": true
  },
  "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "**/*.ts"],
  "strict": true
}

vite.config.ts

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { join } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [svelte()],
  resolve: {
    extensions: [".svelte", ".ts"],
    alias: [
      {find: "lib", replacement: join(__dirname, "src/lib/")},
      {find: "routes", replacement: join(__dirname, "src/routes/")},
      {find: "@utils", replacement: join(__dirname, "src/utils/")}
    ]
  }
})

最初はvite.config.tsだけを編集したが、エディタでエイリアスで書いた.tsファイルだけ解決できずエラーが出ていたのでtsconfig.jsonも編集したらうまくいった。

PotewoPotewo

vite.config.tsextensionsが必要かどうかはわからない。