VueのCDN版を使いつつ、TypeScriptの型定義も反映させたい
- 既存のTypeScriptプロジェクトにnpmのvueいれて
import {createApp} from 'vue'
でimport createApp({}).mount("#app")
でマウント
➡ #app
の中身が空っぽになってしまう。
CDN版だとDOMの中身を保ったままVueアプリ化されるんだけど…挙動が違った。
もともとCDN版を使おうとするも型定義どうしたらよいのかわからず諦めて、npmのvueいれた…という経緯があったが…。 なにか足りない手順とか、読み込むもの間違っているとかあるんだろうか。
結局CDN版をつかいつつ、どうにか型定義読み込む形でいくことに。
解決手順
あまりTS+Vue CDN版で一部だけVue化したい…というニーズはないのか、情報少なくかなり悩んだ。
- 型定義のためにnpmパッケージのvueをインストールして変数にimport
- interface WindowにVueを追加し、importしたvueの変数からtypeofを用いて型を指定
import * as vueProps from 'vue' declare global { interface Window { Vue: typeof vueProps } } export const fetchVueCDN = (): Promise<typeof window.Vue> => new Promise((resolve, reject) => { if (window.Vue) resolve(window.Vue) const prod = typeof env !== 'undefined' && env === 'prod' ? '.prod' : '' const s = Object.assign(document.createElement('script'), { src: `https://cdn.jsdelivr.net/npm/vue@3.2.20/dist/vue.global${prod}.js`, }) s.addEventListener('load', () => { resolve(window.Vue) }) document.body.append(s) setTimeout(() => { reject('Vueの読み込みがタイムアウトしました。') }, 30000) })
あとはこれで、CDN版使いつつ補完もきくようになった
;(async () => { const Vue = await fetchVueCDN() Vue.createApp({template:'msg:{{msg}}',setup(){return {msg:"テキストが入ります。"}}}).mount('#app') })()
参考:
TypeScript - TypescriptでimportせずにVue.jsを使う方法|teratail
余談
気軽にCDN版つかお~と思っても、TypeScriptプロジェクトではそうはいかないということに気付かされた…。
Vueの用途はこれまでjQueryでちょこちょこやってた処理の置き換え、程度にとどまっていて
vue-cliでのプロジェクト生成などはまだ試したことない。知識も浅い。.vue
使うの気が進まないんだよななんとなく…。
フルでjsフレームワークのSPAつくるというのなら、どっちかというとReactが気になるしね。
途中解決法がわからずReactいれたら、そちらはシンプルにReact,ReactDOM+その型定義をいれるだけで思った通りに動いたので、このままReact使用に移行しようと思ってた。
気持ち悪くて結局解消するまで調査していたけど…。
Reactやろうと思えるきっかけができたのはよかった。
いちいちつまづいて大変だ。フロントエンド学習身に余るなあ…。