前一篇文章简单的介绍了一下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