第一篇: vscode原始碼分析【一】從原始碼執行vscode
第二篇:vscode原始碼分析【二】程式的啟動邏輯,第一個視窗是如何建立的
第三篇:vscode原始碼分析【三】程式的啟動邏輯,效能問題的追蹤
第四篇:vscode原始碼分析【四】程式啟動的邏輯,最初建立的服務
第五篇:vscode原始碼分析【五】事件分發機制
第六篇:vscode原始碼分析【六】服務例項化和單例的實現
第七篇:vscode原始碼分析【七】主程式啟動訊息通訊服務
先複習一下!
在第一節中,我們提到:
app.ts(src\vs\code\electron-main\app.ts)的openFirstWindow方法中,
有個WindowsMainService
const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); // TODO@Joao: unfold this
//...
windowsMainService.open({
context,
cli: args,
forceNewWindow: args['new-window'] || (!hasCliArgs && args['unity-launch']),
diffMode: args.diff,
noRecentEntry,
waitMarkerFileURI,
initialStartup: true
});
這個WindowsMainService
(介面檔案:src\vs\platform\windows\electron-main\windows.ts)
(例項檔案:src\vs\code\electron-main\windows.ts)
介面和例項的關係,是在這裡做成的(407行):
services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, [machineId, this.userEnv]));
例項的open方法最關鍵的一句話是:
const usedWindows = this.doOpen(openConfig, workspacesToOpen, foldersToOpen, emptyToRestore, emptyToOpen, fileInputs, foldersToAdd);
在doOpen方法裡呼叫了:this.openInBrowserWindow,並把這個視窗儲存到usedWindows裡去了;
(如果已經有開啟的視窗,那麼就用現成的視窗開啟新的內容)
usedWindows.push(this.openInBrowserWindow({
userEnv: openConfig.userEnv,
cli: openConfig.cli,
initialStartup: openConfig.initialStartup,
fileInputs: fileInputsForWindow,
remoteAuthority,
forceNewWindow: true,
forceNewTabbedWindow: openConfig.forceNewTabbedWindow,
emptyWindowBackupInfo
}));
我們接下來去看看openInBrowserWindow做了什麼
其中最關鍵的一句:
window = this.instantiationService.createInstance(CodeWindow, {
state,
extensionDevelopmentPath: configuration.extensionDevelopmentPath,
isExtensionTestHost: !!configuration.extensionTestsPath
});
CodeWindow的建構函式裡,呼叫了createBrowserWindow方法,在這個方法裡建立了我們的Electron的BrowserWindow
(src\vs\code\electron-main\window.ts)
this._win = new BrowserWindow(options);
好!視窗建立出來了,那麼視窗中的內容呢?按道理來說應該載入一個頁面用於展現UI的呀?
複習結束,下面是新的內容
我們接著去看openInBrowserWindow方法的後面的內容,發現有這麼一句:
if (window.isReady) {
this.lifecycleService.unload(window, UnloadReason.LOAD).then(veto => {
if (!veto) {
this.doOpenInBrowserWindow(window!, configuration, options);
}
});
} else {
this.doOpenInBrowserWindow(window, configuration, options);
}
在doOpenInBrowserWindow裡,呼叫了
window.load(configuration);
OK!我們再回到CodeWindow的型別裡去,看看load方法做了什麼
我們看到了這一句:
this._win.loadURL(this.getUrl(configuration));
他們在getUrl方法裡做了一堆跟URL一點關係也沒有的事情
比如說:設定視窗的縮放級別,設定全屏、設定視窗ID之類的
做完這些無關的事情,有跳進了另一個函式:
let configUrl = this.doGetUrl(config);
return configUrl;
在這個doGetUrl裡只有一句話:
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
這個require.toUrl方法採用通用的模組ID路徑轉化規則,將模組ID字元解析成URL路徑;
注意:file:///協議開頭的URL路徑;
至此,這個視窗總算顯示出了一個畫面!
這個頁面body裡並沒有任何東西;只載入了一個js檔案
<script src="workbench.js"></script>
後面我們再繼續聊這個js檔案的邏輯!