Skip to content

Latest commit

 

History

History
178 lines (117 loc) · 12.3 KB

application-architecture.md

File metadata and controls

178 lines (117 loc) · 12.3 KB

Application Architecture

Web Template Studio is a Visual Studio Code Extension that has three major components. All of them are included in Web Template Studio vsix:

  1. The extension's backend (referred to as the extension). Written in Typescript.
  2. The frontend wizard (referred to as the client). Written in React and Typescript.
  3. The generation engine (referred to as Core Template Studio) written in .NET Core.

Architecture Diagram


Extension

The extension is the main part of Web Template Studio. It has been built using the Visual Studio Code Extensibility API to build extensions. It is responsible for launching the client in a Visual Studio Code tab and for communication between the wizard client and the Core Template Studio CLI. It is also responsible for creating the Azure Services (App Service and CosmosDB Service) and the deployment of the generated applications.

It contains several commands that can be called from Visual Studio Code:

  • webTemplateStudioExtension.commands.web.createApp and webTemplateStudioExtension.commands.reactNative.createApp: This command is executed when we launch the Web Template Studio: Create Web App or Web Template Studio: Create React Native App command from Visual Studio Code. It is responsible to start the Core Template Studio CLI in a child_process, synchronizing the templates and opening the wizard in a Visual Studio Code tab. While the wizard is open, it is also responsible for maintaining communication between the wizard client and the Core Template Studio CLI to obtain templates and generate projects. Specifically Web Template Studio: Create Web App would use the Web templates and open the wizard to create a full-stack web application while the Web Template Studio: Create React Native App would open the wizard to create a React Native application.
    Note: Currently only one wizard can be open per instance of vscode.

  • webTemplateStudioExtension.deployApp: This command is executed when we launch the Web Template Studio: Deploy Web App command from Visual Studio Code. It is responsible for deploying a generated application in Azure.
    Note: For this command to work properly, we need a web application generated with Web Template Studio opened and configured with an App Service.

Client

The wizard client is the visual component of the extension. It is a React app that is compiled into JavaScript that gets injected into html, which then gets served using VSCode's Webview API. It is shown in a Visual Studio Code tab when the user executes the Web Template Studio: [command name] extension command.

You can check available commands here.

It is responsible for the interaction with the user and is responsible for collecting the name and route of the project, the selected frameworks, pages and services and sending them to the extension for processing with Core Template Studio.

The wizard client keeps track of the state using Redux.

Color Themes

Web Template Studio supports Visual Studio Code's light, dark, and high contrast theme. You can press Ctrl + K then Ctrl + T in Windows/Linux or Command ⌘ + K then Command ⌘ + T in Mac to choose different color themes in Visual Studio Code.

Example of Light Theme:

image

Example of Dark Theme:

image

To support different color themes, VSCode CSS theme variables are used so that the webview matches the look and feel of a developer’s VSCode. VSCode's documentation on theme color can be found here. You can also look at the VSCode CSS variables for each theme by pressing Ctrl + Shift ⇧ + P in Windows/Linux or Command ⌘ + Shift ⇧ + P in Mac and then running the Developer: Generate Color Theme From Current Settings command.

If you want to use these variables in the client, you have to follow a certain format. For example, if you want to apply VSCode's "editor.background": "#252526", you would convert it to var(--vscode-editor-background) in the CSS file. More documentation can be found on the webview API docs.

When the app is being run in the browser imitates these VSCode themes using themes.css and themeslight.css for dark and light mode respectively. Otherwise, if it is being ran in the extension, the CSS variables will map to VSCode directly.

Core Template Studio

The Generation Engine is responsible for template synchronisation, get frameworks, get templates and generating projects. It consists of a CLI that receives requests from the extension and get processed by Core Template Studio. Once the request is processed, it returns the response in json format to the extension.

For more Info see Core Template Studio Docs.

Communication

Extension and CLI Core Template Studio communication

The communication between the extension and the Core Template Studio CLI is defined in the coreTemplateStudio.ts file. This static class is responsible for starting/stopping the Core Template Studio CLI in a child_process, and managing the Core Template Studio CLI requests and responses (including notifications and errors).

It also exposes public functions to call the Core Template Studio CLI commands. Some of the main functions offered by the coreTemplateStudio class are:

- sync(payload: ICommandPayload): Promise<any>
- getProjectTypes(): Promise<any>
- getFrameworks(projectType: string): Promise<any>
- getPages(projectType: string, frontendFramework: string, backendFramework: string): Promise<any>
- getFeatures(projectType: string, frontendFramework: string, backendFramework: string): Promise<any>
- getAllLicenses(payload: ICommandPayload): Promise<any>
- generate(payload: ICommandPayload): Promise<any>

To execute a Core Template Studio CLI command from the extension we have to instantiate the coreTemplateStudio class and execute the function that has the command we want to execute.

Example:

async getPages(): Promise<void> {
    const coreTS = CoreTemplateStudio.GetExistingInstance();
    const pages = await coreTS.getPages("projectType", "frontendFramework", "backendFramework");
    ...
    };
  }

To see the Core Template Studio CLI available commands visit Core Template Studio Docs.

Extension and client communication

Client send to extension

When the client wants to execute an extension command, it will call vscode.postMessage() function, passing through parameters an object with the following properties:

  • module: extension module that should process this request.
  • command: extension command that should process the request.
  • payload: data that we send in the request.

Example:

vscode.postMessage({
        module: "extension-module",
        command: "get-pages",
        payload: {
          projectType: "project type",
          frontendFramework: "frontend framework",
          backendFramework: "backend framework"
        }
      });

When the extension create the webview (that includes the client), the routingMessageReceieverDelegate() function found in controller.ts is passed by parameters. This function is responsible for receiving client requests and locating the module that processes the request. All modules that can process customer requests are registered in Controller.extensionModuleMap.

The modules inherit from WizardServant which is the class responsible for executing the function associated with each command, controlling errors and recording telemetry if necessary.

Note: In the development environment - when you run the app in the browser, the Visual Studio Code extension is not available for the client. The communication is mocked using the mockVsCodeAPI.ts, which uses the native window.postMessage() command to send messages to the application.

Client receive from extension

Messages sent from the extension are received in the messageEventsFromExtension() function in App.tsx. This function configures an addEventListener to listen all messages sent from the extension and through a switch executes the necessary instructions according to the command received.

Example:

 function messageEventsFromExtension(){
    window.addEventListener("message", event => {
      const message = event.data;
      switch (message.command) {
        ...
        case "get-pages":
          // set pages in redux store
          break;
        ...
      }
    }
 }

Note: The extensionService.ts file handle communication between the client and extension through promises and offers a simple and centralized way to call extension commands and receive responses.

Extension send to client

When the extension needs to send a request to the client, it will call postMessageWebview() function in reactPanel.ts. This function communicates with the webview that contains the client, passing through parameters an object with the following properties:

  • command: extension command that processed the request.
  • payload: data that we send in the request.

Example:

reactPanelContext.postMessageWebview({
      command: "get-template-info",
      payload: {
        templatesVersion:"1.0.0.0",
        wizardVersion: "1.0.0.0",
        itemNameValidationConfig: [],
        projectNameValidationConfig: []
      }

Separating the UI from the Logic:

One of our main concerns is increasing the speed of the wizard and making it as light as possible.
Therefore, the wizard does not perform any expensive computations, and does not make any API requests. Most of these actions are done in the extension.
So as the user navigates through the wizard, the selections are validated in the wizard and stored. When the user clicks generate, these selections will then be sent to the extension, which will deal with them synchronously.
The extension starts with the templates, which will get sent to the Engine.
Once it´s generated, the extension will use the Azure SDK to deploy the resources if the user selected any while creating their application.

Learn more