哈囉,大家好,我是韋恩,今天我們來了解一下在vscode裡的data storage,今天介紹的內容也都非常實務。
當我們為用戶開發應用程式時,通常都會讓使用者儲存一些個人化設定與本地資料,如前面所提的configuration就很方便地提供了user settings的介面讓使用者設置個人設定。但User Settings雖然方便,若是要滿足extension的各種使用情境,還是力有未逮。為此,VSCode提供了多種可以儲存使用者資料的api跟方法,讓extension可以像一般的桌面程式一樣儲存本地資料。
在官方的教學文件中,主要介紹了四種Data Storage的選擇,主要為兩大類:
ExtensionContext.workspaceState
: 透過extension的memento物件,儲存workspace scope特定的資料,menento物件會以使用key/value的方式儲存資料,如同前端的localStorage。當同一個workspace再次被打開時,vscode會還原(restore)上一次儲存在memento物件的資料讓使用者取得設定。
ExtensionContext.globalState
:提供如同user settings scope的memento物件,讓使用者以key/value方式儲存資料。當同一個extension在vscode中active時,vscod即會還原(restore)上一次儲存在memento物件的資料讓使用者取得設定。
Memento物件的使用方法如下:
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
/*
* 設定、更新memento的資料
*/
context.workspaceState.update('keyA', 'keyAValue');
/*
* 取得memento的資料,可設定初始預設值
*/
context.workspaceState.get('keyB', 'defaultValue');
}
ExtensionContext.storagePath
: 提供workspace scope級別的storagePath,讓使用者在這個路徑的資料夾下設置database或任意型態的資料,extension可以讀寫這個路徑下面的檔案,並且這個地方的資料不會隨著extension卸載後消失,再次裝回亦可讀取。ExtensionContext.globalStoragePath
: 如上所述,差別在於其storagePath適用於user settings scope,為全域的儲存範圍。在extension需要儲存大型檔案或大量資料時,於storagePath下配置檔案特別有用。
註:storagePath、globalStoragePath在新版的vscode已經列為
deprecated
,應使用storageUri
、globalStorageUri
來取得storage的路徑配置本地儲存的資料庫或檔案。
在上面的說明裡,我們可以看到這些api或路徑都是於ExtensionContext
下取得,這個ExtensionContext
是什麼呢?在哪裡取得呢?我們在extension.ts
中的active function中取得的context
參數,即為上面提及的ExtensionContext
,因此我們可以在context參數中使用這些api跟路徑,並且vscode中透過自動補全取得一系列可以使用的api清單。
Ok,現在我們點開context了,我們赫然發現storagePath以及globalStorage path在現在版本已經列為deprecated
了,筆者實際過ExtensionContext.storagePath
,當前版本仍可以取得對應路徑,但強烈建議讀者改用ExtensionContext.storageUri
下面的path路徑,如下所示:
const storagePath = context.storageUri?.path;
const storagePathCast = (context.storageUri as vscode.Uri).path;
const globalStoragePath = context.globalStorageUri.path;
註: 此處的storagePath因為有可能回傳undefined,故需轉變型態為
vscode.Uri
,或使用optional chaining
(storagePath後面的?)的語法,才能避免編譯器提示的錯誤。
好的,現在我們已經了解storageUri的用法,現在我會再介紹兩種在開發中會有幫助的api,分別是:
ExtensionContext.logUri
: 提供當天的log儲存的資料夾的位置,可配合Log4js
、winstonjs
等流行的logger library使用。為什麼我們需要本地儲存的Log檔案呢?當我們的應用程式在斷網的客戶端執行時,我們沒辦法直接透過api傳回當下出錯的紀錄,此時的log檔案就是不可缺少而且必需的。
ExtensionContext.environmentVariableCollection
: 提供extension的環境變數設定,可以讓我們在extension中設置環境變數,並且可以讓terminal讀取到。環境變數的collection物件提供一系列方法,我們可以在自動補全中看到:
collection提供了一系列用於新增、修改、刪除、清空的api,讓我們方便的管理這些變數,用法如下:
/*
* 新增環境變數: append->往尾部追加,prepend->往頭部追加
*/
context.environmentVariableCollection.append('TestEnv', 'TestEnvValue');
context.environmentVariableCollection.prepend('Test2Env', 'Test2EnvValue');
相同的環境變數會被覆蓋,只會被讀取一個,請務必注意。
/*
* 刪除單一環境變數
*/
context.environmentVariableCollection.delete('Test2Env');
/*
* 清空所有環境變數
*/
context.environmentVariableCollection.clear();
/*
* 更新單一環境變數
*/
context.environmentVariableCollection.replace('TestEnv', 'UpdatedEnvValue');
/*
* 操作所有環境變數
*/
context.environmentVariableCollection.forEach((variable, mutator, collection) => {
console.log(variable, mutator);
});
// 執行結果:
// variable: TestEnv
// mutator: {
// value:"UpdatedEnvValue"
// type:1
// }
我們可以在terminal中使用環境變數,做個小測試吧!
$ echo ${TestEnv}
以上面的範例為例,terminal會輸出得到UpdatedEnvValue。
現在,我們已經了解了可以在data storage中儲存本地資料,那麼什麼時候使用configuration比較方便,什麼時候用data storage呢?
vscode.workspace.onDidChangeConfiguration((e) => {
const newConfig = vscode.workspace.getConfiguration('extension-namespace');
...
});
workspace可以覆蓋使用者設定確實很方便,但如果我們有多個workspace需要同一個workspace設定,這些設定又偏偏跟user settings中的有些差異呢?此時,我們可以將多個設定存入storagePath中我們準備的jsonfile或資料庫,讓使用者儲存自訂個人化設定,並透過某個key或自訂的type,讓使用者在workspace settings一鍵引用重複的設定。
vscode的storagePath可以讓我們自由選擇要將資料儲存於檔案或資料庫,我們可以搭配jsonFile
這個library儲存json檔案,也可以選擇輕量的nedb
或者是leveldb
儲存結構化的資料,並進行增刪改查。
今天我們介紹了data storage與一些文件在教學中沒有特別提的小細節,這些細節我們可以透過VSCode的自動補全發現,其實就是因為vscode有完善的api類型定義檔。因此除了查看自動補全後的說明,我們也可以直接查閱官方網站Reference一節vscode api下面的說明,這個頁面會自動讀取VSCode類型檔的定義,並用美觀的UI呈現出來,因此當我們要查閱最新的api說明時,也請儘量多加利用這一個api文件的資源喔!當然,最後也最重要的還是要動手練習並加以實踐這些文件裡提及的api,我們才會有自己的東西,實踐出真知!
好的,今天介紹就到此為止了,今天介紹的內容都非常實務,希望大家了解學習後,能夠開發更多元多樣的extension出來,我們明天見,掰掰!