In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to look at large-scale IDE technical architecture from VSCode". In daily operation, I believe many people have doubts about how to see large-scale IDE technical architecture from VSCode. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts of "how to see large-scale IDE technical architecture from VSCode". Next, please follow the editor to study!
What is the official definition of VSCode
Https://code.visualstudio.com/
Key words:
Code editing (tool properties)
Cross-platform operation, open source
Core functions:
IntelliSense (Code hint), debugging (Code debugging), and git (Code Management) are all core links around code editing.
Extensions (plug-in) shoulders the responsibility of creating an open ecology.
Comments:
For tools, you need to be able to figure out the boundaries. What you should focus on and which can be spilled over to third-party extensions to satisfy.
The course of development
Released in 2015-04 (4 years ago)
2015-11 (half a year after release) open source
Release VSCode Remote Development in 2019-05
Team leader: Erich Gamma. One of the authors of JUnit, one of the authors of Design patterns, the architect of Eclipse. 2011 joined Microsoft and formed a team in Zurich, Switzerland to develop an editor based on web technology, later known as monaco-editor. The VSCode development team starts with about 10 individuals, and most of the early members have a background of the Eclipse development team.
What are the engineering highlights of Visual Studio Code what is the experience of maintaining a large open source project? "Shape Up" is a way of working for small and medium-sized teams.
Erich Gamma gave a speech on the theme "The journey of visual studio code: Building an App Using JS/TypeScript, Node, Electron & 2016 OSS Components" at GOTO 2016, detailing the development of the project:
Those who don't have time to watch the video can download the full PDF.
On the first page of PPT, Erich Gamma intercepts emails describing the job content he received after joining Microsoft:
"explore a new online development tool model that is as successful as desktop IDE."
The whole team starts with about 10 people, mixing the old, middle and new generations of programmers of different levels. It is not easy to have such a grand vision in Microsoft, a giant commercial company. At the beginning, the team set the idea of working like start up, asking for ship every month.
At the same time, he also proposed that in the early days, he would frantically look for landing scenarios within the company, such as Visual Studio Online's online Code DIff page, TypeScript's official website Playground editor, OneDrive code files, Edge Dev Tool code browsing, and so on.
An important turning point is the great changes that have taken place at Microsoft itself:
With the whole open source cross-platform trend of Microsoft, Erich Gamma keenly decided to move the product from Browser Based IDE to cross-platform Desktop IDE, but still used Web technology, so electron appeared on the scene, VSCode open source these things happened one after another, and the VSCode team spent six months using Electron to desktop the Web editor and another six months to plug in the entire IDE.
Product positioning
Erich Gamma has a share of VSCode on 2017 SpringOne Platform, explaining many ideas and decisions for top-level design of VSCode based on his past experience in developing Eclipse, including product positioning for VSCode:
You can see from the figure that the VSCode positioning is halfway between the editor and the IDE and is biased towards the lightweight editor side.
The core of VSCode is "editor + code understanding + debugging", which revolves around this critical path, everything else is very restrained, and the product remains lightweight and high performance.
Comments:
Productivity tools software must stick to the main line, otherwise it is likely to become an amusement park without tickets. There must be a strong team behind the powerful products. For example, Microsoft dug up Anders Hejlsberg, created C# and TypeScript one after another, dug up Erich Gamma, and successively gave birth to pearls such as monaco and vscode.
What is Electron?
As mentioned above, one feature of VSCode is cross-platform, and its cross-platform nature is implemented through electron. So we need to have a brief understanding of electron first.
Official definition
Core technology
Use Web technology to write UI and run it with chrome browser kernel
Use NodeJS to manipulate the file system and initiate network requests
Use NodeJS C++ Addon to call the native API of the operating system
Application architecture
Https://electronjs.org/docs/tutorial/application-architecture
1 main process: an Electron App starts only one main process, which runs the script specified in the main field of the package.json
N rendering processes: the main process code can call Chromium API to create any number of web pages, while Chromium itself is a multi-process architecture, and each web page runs in its own rendering process.
Interprocess communication:
Communication between Render processes is essentially the same as communication between multiple Web pages, and various browser capabilities such as localStorage can be used.
Render processes and Main processes can also communicate with each other through API (ipcRenderer/ipcMain)
Comments:
Ordinary web pages cannot call native api, so the Render process in which the web page of electron is located can forward tasks to the Main process running in NodeJS environment, thus implementing native API. This architecture greatly expands the capability richness of electron app compared with web app, but at the same time retains the fast and smooth development experience of web, coupled with the cross-platform advantages of web itself, make electron a very cost-effective solution.
Third, VSCode technology architecture, multi-process architecture
Main process: the entry process of VSCode, which is responsible for some global tasks such as window management, inter-process communication, automatic update, etc.
Rendering process: responsible for rendering a Web page
Plug-in hosting process: the code of each plug-in runs in a host process that belongs to its own NodeJS environment, and plug-ins are not allowed to access UI
Debug process: Debugger is specialized compared to normal plug-ins
Search process: search is a kind of computing-intensive task. A single process ensures the overall experience and performance of the software.
# check out code git clone git@github.com:microsoft/vscode.gitcd vscode# installation depends on yarn# launch web version yarn watch & & yarn web# launch desktop version yarn watch & &. / scripts/code.sh# package yarn run gulp vscode- [platform] yarn run gulp vscode- [platform]-min# platforms: win32-ia32 | win32-x64 | darwin | linux-ia32 | linux-x64 | linux-arm source code organization
Https://github.com/microsoft/vscode/wiki/Source-Code-Organization
Here are some top-level key folders for the entire VSCode project, which will focus on src and extensions later:
├── build # build script ├── extensions # built-in plug-in ├── scripts # tool script ├── out # Product Directory ├── src # Source Code Directory ├── test # Test Code
The code architecture of VSCode also changes with the evolution of the product:
The following article will share some highlights and features of the entire VScode source organization:
1. Isolation of kernel (src) and plug-in (extensions), kernel layering and modularization
/ src/vs: hierarchical and modular core
/ src/vs/base: common public methods and public view components
/ src/vs/code: main entry of VSCode application
/ src/vs/platform: various pure services that can be injected by dependency
/ src/vs/editor: text editor
/ src/vs/workbench: overall view framework
/ src/typings: common foundation type
/ extensions: built-in plug-in
two。 Each floor is isolated by environment.
Each layer of code in the kernel complies with the electron specification and subdivides folders by environment:
Common: a public js method that can be run anywhere
Browser: only use the code of the browser API, you can call common
Node: use only NodeJS API code, you can call common
Electron-browser: code that uses the electron rendering thread and browser API to call common,browser,node
Electron-main: using electron main thread and NodeJS API code, you can call common, node
Test: test code
Comments:
Similar problems have been encountered in the actual development. As a low code + visual R & D platform, many functional modules need to be implemented across the edited state and the running state. If the code is not restricted and differentiated, it can easily lead to incorrect dependencies and unexpected bug, so it is finally decided to adopt a similar isolation architecture (editor/runtime/common).
3. The kernel code itself uses an extension mechanism: Contrib
You can see that there are a lot of small functional units of VSCode in the / src/vs/workbench/contrib directory:
├── backup ├── callHierarchy ├── cli ├── codeActions ├── codeEditor ├── comments ├── configExporter ├── customEditor ├── debug ├── emmet ├──.... Numerous omissions in the middle.... ├── watermark ├── webview └── welcome
Contrib has some features:
All code in the Contrib directory is not allowed to rely on any files outside this folder
Contrib mainly uses some extension points exposed by Core to do things.
If each Contrib is to be exposed, export API to eg: contrib/search/common/search.ts in an export file
If a Contrib is to be called with another Contrib, it is not allowed to use files other than export API files.
To follow up, even if Contrib can call the exit API of another Contrib, you should consider carefully and try to avoid the interdependence of the two Contrib.
I guess the purpose of the VSCode development team to do this design is that there are too many function points for heavy tool software. If the functional code is aggregated and bottled directly by the original module reference, it is a top-down architecture and a greater challenge to maintainability.
By exposing the extension point, the dependency relationship can be reversed, attached to the extension point protocol, the core functions and non-core functions can be separated, and the code implementations of independent small functions can be aggregated separately to reduce information density and improve maintainability.
However, the specific business code organization of VSCode Contrib does not seem to have many paradigms, and the extension mechanism of the kernel code, Contrib, is different from the plug-in mechanism extension, which VSCode is open to the outside world, which makes it a headache to read.
Through the communication with my classmate wood farmer developed by CloudIDE, I got two main differences:
Each extension runs in its own independent host process, while the function of contrib is basically run in the main process.
Extension can only live on core's open extension points, but contrib can get all class implemented within core through dependency injection (although not officially recommended)
4. Dependency injection
The previous section mentioned that VSCode code makes extensive use of dependency injection. This article will not elaborate on the details of the implementation of this technology. If you are interested, you can read some good implementations:
Power-di written by a classmate of the team Yangyuan
Powerful http://inversify.io for open source in the community
The common implementation principle of TS dependency injection is to use reflect-metadata to set and obtain meta-information, so that you can get the meta-information of TypeScript type that originally belongs to the edited state at runtime, specifically, the following API:
Reflect.getMetadata ("design:type", target, key): get class attribute type meta information
Reflect.getMetadata ("design:paramtypes", target, key): get the meta-information of class method parameters
Reflect.getMetadata ("design:returntype", target, key): gets the meta-information returned by the class method
Reflect.defineMetadata (metadataKey, metadataValue, target, propertyKey): setting meta-information
Reflect.getMetadata (metadataKey, target, propertyKey): get meta information
However, specific to VSCode dependency injection, it does not use reflect-metadata, but uses decorator to label meta-information, and implements its own dependency injection method. For more information, please refer to the article vscode source code parsing-dependency injection, which roughly includes the following types of roles:
Service: the implementation logic of services
Interface: interface description of the service
Client: service user
Manger: service Manager
For example, a large number of service are defined in / src/core/platform, and consumer Client can be used in other places by dependency injection. The pseudo code is as follows:
Class Client {/ / Constructor parameter injection (one of the dependency injection methods) constructor (/ / required @ IModelService modelService: IModelService, / / optional @ optional (IEditorService) editorService: IEditorService) {/ / use services}} / / instantiate instantiationService.createInstance (Client); 5. Absolute path import
Comments: absolute path import is a skill worth learning, the specific way is to configure TypeScript compilerOptions.paths
The relative path import has a high burden on the reader's brain. It relies on the current file location context information to understand the refactoring code when moving the file location. The relative path needs to modify all the import of this file, but the absolute path does not need to.
6. Command system
Both VSCode and monaco-editor have their own command systems, and students of the Ant CloudIDE team have also summarized the advantages of command systems:
The traditional module call is a mesh, so it is not easy to find an aspect to understand or govern:
On the other hand, the command system is centralized, and the end of each function becomes a flat structure:
7. TypeScript
Start the process (TLDR)
The above preliminary understanding of the technical architecture and source code organization of vscode, itchy students may be a little can not wait to try to go through the startup process of vscode.
Then before the official departure, I need to give you a little friendly reminder, if you do not have the patience to read the following VSCode start-up process, you should know that life is muddling along (╥ muddle ╥) o
Overall, VSCode startup code really show shows us how complex client software code will be engineered, which is mixed with a large number of TypeScript-based OOP-style code organization, a variety of boundaries, hosting environment, context processing, the original simple start APP rendering a page process becomes extremely complex.
Let's take a look at the following files and methods for streamlining the core startup link:
Entry: package.json {"main": ". / out/main"}: the standard startup entry for electron
/ out/main.js': is the entry file of the build product, which corresponds to the source code / src/main.js'
/ / src/main.js 's reduced core link const {app, protocol} = require ('electron'); app.once (' ready', function () {/ / electron is started, call vscode's entry onReady ();}); async function onReady () {/ / get the cache file directory address and language configuration, and launch const [cachedDataDir, nlsConfig] = await Promise.all ([nodeCachedDataDir.ensureExists (), resolveNlsConfiguration ()]) Startup (cachedDataDir, nlsConfig);} function startup (cachedDataDir, nlsConfig) {/ / load vscode's own open source AMD Loader https://github.com/Microsoft/vscode-loader/ then use this loader to load VSCode's main entry file require ('. / bootstrap-amd'). Load ('vs/code/electron-main/main') } / / src/vs/code/electron-main/main.ts streamlined core link / / initialize the main class const code = new CodeMain (); / / execute the main entry function code.main (); the class public entry of class CodeMain {main () {/ / vscode is generally an empty shell, which is really in the private logic this.startUp () } private async startup () {/ / first create dependent initialization service const [instantiationService, instanceEnvironment] = this.createServices (); / / create an editor instance and call the startUp method return instantiationService.createInstance (CodeApplication). Startup ();}} / src/vs/code/electron-main/app.tsexport class CodeApplication extends Disposable {async startup (): Promise {/ / IPCServer const electronIpcServer = new ElectronIPCServer () / / SharedProcess const sharedProcess = this.instantiationService.createInstance (SharedProcess, machineId, this.userEnv); / / create a bunch of dependent service / / IUpdateService IWindowsMainService IDialogMainService IMenubarService IStorageMainService. Const appInstantiationService = await this.createServices (machineId, trueMachineId, sharedProcess, sharedProcessClient); / / Open a window const windows = appInstantiationService.invokeFunction (accessor = > this.openFirstWindow (accessor, electronIpcServer, sharedProcessClient);} private openFirstWindow () {const windowsMainService = this.windowsMainService = accessor.get (IWindowsMainService); return windowsMainService.open () }} / src/vs/platform/windows/electron-main/windowsMainService.tsexport class WindowsMainService extends Disposable implements IWindowsMainService {open () {/ / execute open this.doOpen ();} private doOpen () {/ / Open browser window this.openInBrowserWindow () } private openInBrowserWindow () {/ / create window const createdWindow = window = this.instantiationService.createInstance (CodeWindow, {state, extensionDevelopmentPath: configuration.extensionDevelopmentPath, isExtensionTestHost:!! configuration.extensionTestsPath});} private doOpenInBrowserWindow () {/ / load page window.load (configuration) }} / / src/vs/code/electron-main/window.tsexport class CodeWindow extends Disposable implements ICodeWindow {load () {/ / call api of electron to load a url html page this._win.loadURL (this.getUrl (configuration));} private getUrl () {/ / get url let configUrl = this.doGetUrl (config) to open; return configUrl } private doGetUrl (config: object): string {/ / finally sees html! Tearful face "▽" / / Open the VSCode workbench, that is, workbench return `$ {require.toUrl ('vs/code/electron-browser/workbench/workbench.html')}? config=$ {encodeURIComponent (JSON.stringify (config))} `;}} Code Editor Technology
Because the focus of this article is not on the real code editor technology but on the engineering of large-scale software, this article will only briefly introduce some core technologies related to code editing:
Monaco-editor text editor, a very deep field, without talking, you can look at some interesting details:
Text Buffer performance optimization
MVVM architecture
Language server protocol language hint is also a major initiative of vscode:
Instead of focusing on AST and Parser, focus on Document and Position, thus achieving language independence.
The language prompt is transformed into a CS architecture, and the core is abstracted into a simple model of what response the server needs when clicking on the position of the line and column of the document. Based on the JSON RPC protocol, each language can implement a general back-end based on the protocol.
Debug Adaptor Prototal: debugging protocol
Comments:
Monaco-editor can see the domain accumulation of experts, and the design of language server protocol and Debug Adaptor Prototal, which belongs to the core competitiveness of VSCode, belongs to a strategically advantageous position, we can see the level of thinking, make our own things into standards, make ecology, and open up and win-win.
Fourth, the concept difference of VSCode plug-in system.
Compare several major IDE:
Visual Studio / IntelliJ: no plug-ins required, all in one (not open enough)
Eclipse: everything is plug-in (bloated, slow, unstable, poor experience)
VSCode: the golden mean
Strong isolation of VSCode plug-ins
Stand-alone process: VSCode plugin code runs in a separate Extension Host host process of its own
Logic and view isolation: plug-ins do not have access to DOM or operate UI at all, and plug-ins can only respond to extension points exposed by VSCode Core
View scalability is very weak: VSCode has very stable interaction and visual design, and the component slot on the UI provided to the plug-in is very small and stable
Can only be extended with limited components: VSCode has a very strong limitation on the ability to extend views. The UI in the hole cannot be drawn at will, and can only use some officially provided built-in components, such as TreeView.
What are the scalability capabilities of vscode? Https://code.visualstudio.com/api/extension-capabilities/overview
Comments:
The restraint of view extension brings a unified visual and interactive style, brings a good user experience, facilitates the establishment of a stable independent process of user mental plug-ins, is isolated from the view, and ensures the quality, performance and security of the overall software.
Workbench view structure
Https://code.visualstudio.com/docs/getstarted/userinterface
Title block: Title Bar
Activity bar: Activity Bar
Sidebar: Side Bar
Panel: Panal
Editor: Editor
Status bar: Status Bar
What is extensible in this view structure? For more information, see extending workbench:
Plug-in API injection
Plug-in developers need to introduce a npm module named vscode when calling core capabilities
Import * as vscode from 'vscode'
In fact, this is just a vscode.d.ts type declaration file, which declares the API types available to all plug-ins.
The specific implementation of these API is in src/vs/workbench/api/common/extHost.api.impl.ts createApiFactoryAndRegisterActors
So when exactly did these API be injected in the plugin execution context? In fact, it tampered with the execution of the plug-in import statement.
/ / src/vs/workbench/api/common/extHostRequireInterceptor.tsclass VSCodeNodeModuleFactory implements INodeModuleFactory {public load (_ request: string, parent: URI): any {/ / get extension id from filename and api for extension const ext = this._extensionPaths.findSubstr (parent.fsPath); if (ext) {let apiImpl = this._extApiImpl.get (ExtensionIdentifier.toKey (ext.identifier)) If (! apiImpl) {apiImpl = this._apiFactory (ext, this._extensionRegistry, this._configProvider); this._extApiImpl.set (ExtensionIdentifier.toKey (ext.identifier), apiImpl);} return apiImpl;} / / fall back to a default implementation if (! this._defaultApiImpl) {let extensionPathsPretty ='' This._extensionPaths.forEach ((value, index) = > extensionPathsPretty + = `\ t$ {index}-> ${value.identifier.value}\ n`); this._logService.warn (`Could not identify extension for 'vscode' require call from ${parent.fsPath}. These are the extension path mappings:\ n$ {extensionPathsPretty} `); this._defaultApiImpl = this._apiFactory (nullExtensionDescription, this._extensionRegistry, this._configProvider);} return this._defaultApiImpl;}}
The require of vscode plugin is all hijacked by Microsoft/vscode-loader, and the plug-in API is injected into the runtime through the hack of require.
Plug-in development and configuration
Scaffolding: https://github.com/Microsoft/vscode-generator-code
Official demo: https://github.com/Microsoft/vscode-eslint
Npm install-g yo generator-codeyo code
A plug-in core is a configuration file: Extension Manifest JSON (a field in package.json)
Https://code.visualstudio.com/api/references/extension-manifest
Some key configurations are as follows:
Main: the main file entry, such as exporting an activate method, can accept ctx to do something
Main: ". / src/extension.js"
/ / extension.jsconst vscode = require ("vscode"); function activate (context) {console.log ('Congratulations, your extension "helloworld" is now activating'); let disposable = vscode.commands.registerCommand ("extension.helloWorld", function () {vscode.window.showInformationMessage ("Hello World!");}); context.subscriptions.push (disposable);} exports.activate = activate;Activation Events activation time
OnLanguage: the file containing the language type is opened
OnLanguage:json
OnCommand: a command
OnCommand:extension.sayHello
OnDebug: start debugging
OnDebugInitialConfigurations
OnDebugResolve
WorkspaceContains: files with matching rules are opened
WorkspaceContains:**/.editorconfig
OnFileSystem: open a file for a special protocol
OnFileSystem:sftp
OnView: the view of an id is displayed
OnView:nodeDependencies
OnUri: schema registered with the operating system
Vscode://vscode.git/init
OnWebviewPanel: when the webview of some kind of viewType is opened
OnWebviewPanel:catCoding
*: open immediately as soon as you start
Contribution Points extension point
Contributes.configuration: what are the options available for users to configure this plug-in
Contributes.configurationDefaults: overrides some of vscode's default editor configurations
Contributes.commands: register some commands that can be called by users with the command system of vscode
Contributes.menus: extended menu
...
At this point, the study on "how to look at the large-scale IDE technical architecture from VSCode" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.