前一篇文章簡單的介紹了一下vscode源碼結構.此次咱們來了解一下vscode的運行流程. 下一篇文章咱們則切換主題的小案例來深刻了解vscode.html
首先入口文件是main.js,這個相信大部分人都知道.那麼咱們來看看main.js的源碼.這裏至關於運行的是electron的主進程. 這裏作了一些初始化操做之後(設置schemes, 初始化一些全局配置好比編輯器工做路徑)就調用startup函數來loading vs/code/electron-main/main.tsgit
function startup(cachedDataDir, nlsConfig) { nlsConfig._languagePackSupport = true; process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || ''; // Load main in AMD perf.mark('willLoadMainBundle'); require('./bootstrap-amd').load('vs/code/electron-main/main', () => { perf.mark('didLoadMainBundle'); }); }
electron-main/main.ts 則會先初始化一些基礎服務github
private createServices(args: ParsedArgs, bufferLogService: BufferLogService): [IInstantiationService, IProcessEnvironment] { const services = new ServiceCollection(); const environmentService = new EnvironmentService(args, process.execPath); const instanceEnvironment = this.patchEnvironment(environmentService); // Patch `process.env` with the instance's environment services.set(IEnvironmentService, environmentService); const logService = new MultiplexLogService([new ConsoleLogMainService(getLogLevel(environmentService)), bufferLogService]); process.once('exit', () => logService.dispose()); services.set(ILogService, logService); services.set(IConfigurationService, new ConfigurationService(environmentService.settingsResource)); services.set(ILifecycleMainService, new SyncDescriptor(LifecycleMainService)); services.set(IStateService, new SyncDescriptor(StateService)); services.set(IRequestService, new SyncDescriptor(RequestMainService)); services.set(IThemeMainService, new SyncDescriptor(ThemeMainService)); services.set(ISignService, new SyncDescriptor(SignService)); return [new InstantiationService(services, true), instanceEnvironment]; }
而後建立ipcServer把接力棒交給 app.tstypescript
// Startup await instantiationService.invokeFunction(async accessor => { const environmentService = accessor.get(IEnvironmentService); const logService = accessor.get(ILogService); const lifecycleMainService = accessor.get(ILifecycleMainService); const configurationService = accessor.get(IConfigurationService); const mainIpcServer = await this.doStartup(logService, environmentService, lifecycleMainService, instantiationService, true); bufferLogService.logger = new SpdLogService('main', environmentService.logsPath, bufferLogService.getLevel()); once(lifecycleMainService.onWillShutdown)(() => (configurationService as ConfigurationService).dispose()); return instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnvironment).startup(); });
這裏咱們先了解到instantiationService. 後續咱們就常常接觸整個服務. 這能夠理解成是vscode實現DI的容器. 經過調用instantiationService.createInstance建立的對象, 對象constructor內使用裝飾器聲明瞭須要注入的service類型.則instantistionService會自動將已有的service注入bootstrap
main.tssegmentfault
return instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnvironment).startup();
app.ts constructorapp
constructor( private readonly mainIpcServer: Server, private readonly userEnv: IProcessEnvironment, @IInstantiationService private readonly instantiationService: IInstantiationService, @ILogService private readonly logService: ILogService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @IConfigurationService private readonly configurationService: IConfigurationService, @IStateService private readonly stateService: IStateService ) { super(); this.registerListeners(); }
app.ts 在最後會調用window.ts 中的 open 函數來打開一個vscode窗口. 每一個window窗口都會打開workbench.html用來渲染咱們所看到的整個vscode界面.electron
private doGetUrl(config: object): string { return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; }
今天的分享就到這裏. 明天咱們就來經過實現切換主題(dark mode)來深刻了解 workbench 的邏輯。async