專案開發遇到的問題整理 – 2022/05/05

最近在使用 Vue 3、TypeScript 和 Firebase 開發專案,開發過程中遇到了一些問題,這篇文章主要是作為問題記錄以及回顧。

最近在使用 Vue 3、TypeScript 和 Firebase 開發專案,開發過程中遇到了一些問題,這篇文章主要是作為問題記錄以及回顧。

問題一:當 tsconfig 的compilerOptions.isolatedModules 選項為 true 時,vue-tsc 對程式碼的型別檢查過程中,遇到 vue core 會報錯。

使用 Vite 建立 Vue 3 + TypeScript 專案時,package.json 中的 build 行為會先使用 vue-tsc 對程式碼進行檢查,檢查通過後在跑 vite 進行 build,而在 vue-tsc 檢查時,遇到 vue core 會報錯,導致檢查不通過,進而無法完成 build。

參照 Vite 官方的文件[1]TypeScript Compiler Options,還有 Vue 的 Github issue [2](reactivity) Type check fails when ‘–isolatedModules’ flag is provided上的討論,因為 vue-tsc 是使用 esbuild 來將 TypeScript 轉譯成 JavaScript,而 esbuild 官方建議 tsconfig 中 compilerOptions 底下的 isolatedModules 應當開啟[3]Files are compiled independently,在該選項開啟的情況下,vue core 恰巧是會出問題的。對於這個問題的解決方法,是暫時開啟skipLibCheck 的選項,然後等待 vue core 那邊的修正。

問題二:在 recursive component 的情況下,Props 在 vue-tsc 檢查時,會無法被辨認出來。

recursive component 就是在元件中,引入自己並且使用的情況,例如:

<template>
  <Node></Node>
</template>

<script setup lang="ts">
import Node from '@/componets/Node.vue'
</script>

在這種情況下,template 上的 props 引用會無法被 vue-tsc 給辨識出來,參考 Github issue 上的討論[4]Props are not recognized if there are bindings with a type that refers to SFC itself[5]Circular references between Vue 3 components cannot be resolved,其實這是 TypeScript 預期的行為與限制,而解決方式是引入自己的寫法改用 defineAsyncComponent 的方法,依照上面的例子來修改,結果就會是:

<template>
  <Node></Node>
</template>

<script setup lang="ts">
import { defineAsyncComponent, DefineComponent } from "vue";
interface Props {
  ...
}

const Node defineAsyncComponent<DefineComponent<Props>>(() => import('@/componets/Node.vue') as any);
</script>

問題三:在使用 ts-node 的情況下,無法對 path alias 做出正確的解析

因為 ts-node 在實作上,參考 TypeScript 中對於 paths 的描述進行解讀[6]Why is this not built-in to ts-node?,然後認定實作上不須修改既有 Node.js 載入檔案的行為,所以無法對 path alias 做出反應。解決方式是安裝並且載入 tsconfig-paths/register 套件。

問題四:無法在 defineProps、defineEmits 和 defineExpos 這類 marco 中使用 import 載入的 type definition。

參考了 Github issue[7]How to import interface for defineProps,目前這個問題還沒解決,在程式碼上,只能暫時讓這些重複的 type definition 存在於各自的 component,等待解決後,才可以抽離出來到特定檔案上進行管理。

問題五:針對 Firestore 的資料,要在前端頁面建立 pagination 的顯示

依照 Firestore 的官方文件[8]Paginate data with query cursors,是可以使用 query cursor 來達成上一頁和下一頁的功能,但無法達成在特定分頁載入屬於該頁內容的功能,於是,實作上,只能把整個 collection 載入前端,然後由前端處理實際的 pagination 操作,這個實作方式會導致初次載入會耗時且每次讀取時,會消耗大量的 read 的資源,為了改善 read 資源被大量消耗的問題,對 firestore instance 使用 enableIndexedDBPersistence,將已經從 firestore backend 載入的資料存放在瀏覽器的 IndexedDB,讓對 firestore query 時,可以先去使用 IndexedDB 裡面的資料,進而降低未來在 firestore read 資源上的消耗。

Last Updated on 2022 年 5 月 5 日 by Tsuki

發表迴響