How San CLI works

Introduction: In the last issue, we discussed the use of San CLI. In this issue, we will go deeper and take a look at the implementation principle of San CLI.



1. Core modules and core concepts

In order to facilitate the understanding of the overall workflow (main process) of San CLI below, let's first look at the core modules and core concepts of San CLI.

1. Core module

The core modules of San CLI include:

  • san-cli: Responsible for the main process of San CLI and implement core functions;

  • san-cli-service: Service layer, responsible for the Service process;

  • san-cli-command-initsan init The Command plugin that implements the command;

  • san-cli-plugin-*: Service plugin;

  • san-cli-utils: Tool library, which can also be used directly in plugins;

  • san-cli-webpack: Common logic for webpack build and dev-server, webpack self-developed plug-ins, etc.



2. Core Concepts

The core concepts are mainly processes and plug-ins. Among them, the process is divided into the main process and the Service process, and the plug-in is divided into the Command plug-in and the Service plug-in:

  • Process : The process of San CLI is divided into two parts, the main process and the Service process:

  1. Main processsan-cli/index.js The process is the workflow of the entire San CLI. When we enter San CLI-related commands on the command line, such as  san initsan serve(corresponding  npm start) and  san build(corresponding  npm run build), we will enter the main process, and the main process will execute the corresponding commands  handler. Some commands  handler do not directly contain processing logic, but are introduced  san-cli-service, such as  san serve and  san build, when such commands are input, they will enter the Service process from the main process.
  2. Service processsan-cli-service/Service.js The process mainly deals with the logic related to Webpack construction.



  • Plugins : Used to extend the functionality of San CLI:

  1. Command plug-in : used in the main process. After executing the command defined by the Command plug-in, the main process will execute the corresponding Command plug-in  hanlder;

  2. Service plugin : used in the Service process to handle the logic related to Webpack construction.

 

Second, the overall work process

The overall workflow of San CLI, the main process,  san-cli/index.js is roughly as follows:

  1. check node version;

  2. Check san-cli version;

  3. Call to  san-cli/lib/Commander.js create a command instance:

  4. add global  option;

  5. Add middleware:

  6. set global logLevel;

  7. set  NODE_ENV environment variables;

  8. Add properties and methods such as  argv logging.

  9. Load built-in commands:  initservebuildinspectui etc.;

  10. Loading  package.json and  sanrc.json declaring preset commands (custom commands);

  11. sanrc.jsonIt is the file that configures San CLI, and the san.config.jsdifference is that the latter is the file that configures the project. For details, please refer to the official documentation of San CLI.

  12. When the command is triggered  hanlder, the official execution of San CLI starts.

The main process of combining the core modules is shown in the following figure:

 

3. san init

san initThe command is used to initialize the project. The usage has been introduced in the last issue. In this issue, we will see how the command can initialize a project.

1. Process

san initThe principle of initializing the project, in simple terms, is to remotely pull the code base of the project scaffolding template to the local through the git command, or directly use the local code base of the project scaffolding template, and then use vinyl-fs to pull the code base of the pulled code base. The files are processed in sequence, and an initialized project is obtained after the processing is completed.

vinyl-fs is the core of gulp.

 

san initIt mainly consists of four-step serial tasks:

  1. Check the catalog and offline package status: check whether the local path of the project scaffolding template and the offline package are available;

  2. Download the project scaffolding template: Download the project scaffolding template from a remote repository such as Github to the template cache directory;

  3. Generate project directory structure: use  vinyl-fs the project scaffolding template to traverse from the cache directory to the project directory specified by the developer;

  4. Install project dependencies: Ask the developer whether to install  package.json the dependencies.



The corresponding flowchart is shown in the following figure:



Among them, the flow chart for checking the status of the catalog and offline packages is as follows:

2. Design ideas

san initThe specific implementation is in the san-cli-command-initmodule, the san-cli-command-init module is a Command plug-in, the core of which is a TaskListclass, san initand the essence of the execution process is: pass in the array composed of the above four tasks to instantiate TaskListand call the runmethod of the instance.

Let's take a look at  TaskList the internal implementation.

When  TaskList the method of the instance is  called,  the first task of the task list passed in when the run instantiation is executed  is processed first.TaskList

Because these tasks are essentially functions, first add some methods to the first task, such as a method indicating that the task has been completed  complete , and then call the first task function after adding the method.

Calling the first task function means that the first task starts to execute. When all the things that the first task should do are done, the  complete method added to the task function before will be called in the task function. .

completeThe method does one thing, and lets the  TaskList instance start processing the next task, in the same way as above, but simply repeating.

Finally, the  TaskList instance finds that there is no next task, and it stops work.



3. TaskList source code simplified version

We use the simplified version of the source code to see  TaskList the use and implementation.

 

TaskListusage of:

As an  checkStatus example, look at the implementation of the task function:

TaskList Implementation of:

We can see that  san init the design pattern of , is still relatively good. For example, if we want to  add one more task, we only need to pay attention to the implementation of the task itself, and put  it into the task list passed in during san init instantiation after the implementation is completed  . TaskList, you can, the scalability is very good.



Fourth, the plug-in mechanism

San CLI's plug-ins are divided into Command plug-ins and Service plug-ins. In the last issue, we discussed how to develop a Command plug-in or Service plug-in with practical examples. In this issue, we will take a look at the plug-in mechanism of San CLI.

1. Command plugin

Compared with the Service plugin, the Command plugin has a simpler mechanism.

The Command plugin is actually an extension of the yargs plugin system, yargs is an npm package with which we can define our own command line commands.

Review the Command plugin we created in the last issue:

It's written this way because it's a yargs requirement to define a command. After defining the command,  package.json declare the command in the project.

When we execute any san command—note, any one—before actually executing the command, San CLI will first read  package.json the command declared in it, then find the definition of the command and pass in yargs, at this time, yargs knows what commands are there. After that, San CLI passes the name and parameters of the command we execute to yargs. After yargs gets the name and parameters of the command, it goes back to execute the corresponding command. hanlder。

This is how the Command plugin works.

It is also worth noting that  san-cli/lib/commander.js a class named Command is defined in it. This class has made some customizations to the yargs plugin, such as adding common methods and properties to the  argv object through the middleware mechanism, which is convenient for downstream  handler use.



2. Service plugin

San CLI's Service plugin mechanism borrows from Vue CLI's Service plugin mechanism, but with some differences:

  • Vue CLI registers a new command through the Service plug-in, which is implemented by using the registerCommandAPI method of the Service plug-in; while San CLI separates the logic of registering a new command from the Service plug-in and becomes an independent part. It is the Command plug-in introduced earlier.

  • A Vue CLI command corresponds to one or more Service plugins, that is, the implementation of a command is completed by one or more Service plugins; while a San CLI command corresponds to zero or all Service plugins (introduced), one When there are zero commands, the command is a pure Command plug-in, and when one command corresponds to all Service plug-ins, the command triggers the Service process in the logic of its corresponding Command plug-in, and the Service process will register and execute all service plugin.

Next, we will take the san serve command as an example to look at the Service process, the design idea of ​​the Service plug-in, and the simplified source code of the Service class.

1) Service process

The Service process, that is, the entire workflow of the Service:

  1. San CLI parses the  commands entered  in the  command line in the main process san serve , and enters  ;san-cli/commands/servehandler

  2. san serve The main purpose of the command  handler is to instantiate,  Serviceand the instantiation will process the configuration item and the Service plug-in;

  3. Execute  service.run(callback), enter the Service process, the implementation of the Service process is mainly in  service.run :

  4. loadEnv: load the env file;

  5. loadProjectOptions:load  san.config.js;

  6. init:service start:

  7. Initialize the plugin, that is, execute the plugin in sequence;

  8. Execute the webpackChain callback stack in turn;

  9. Execute the webpackConfig callback stack in turn;

  10. execute  callback.



The corresponding flow chart is as follows:



The specific execution timing of our custom Service plug-in is in the step 3-1-1 "Initialize the plug-in, that is, execute the plug-in in sequence", which corresponds to the step of "Initialize the plug-in (plug-in.apply)" in the figure above.

The steps of "initialize the plugin variable and load the incoming plugin" and "load the plugin set in the plugins in config" in the above figure are actually loading the Service plugin, but the former is loading the built-in plugin and  sanrc.json the pre- installed plugin. The plug-in is designed, and the latter is mainly  san.config.json the plug-in in the load.



The flowchart for loading the Service plugin is as follows:



2) Design ideas

Enter  san serve the command to trigger the corresponding  handlerhandler It mainly does two things: one is to instantiate the Service, and the other is to call the  run method of the Service instance.

When a Service is instantiated, the built-in Service plug-in and  sanrc.json the preset Service plug-in are loaded. If our custom Service plugin is preset  sanrc.json , such as the last issue  san-cli-plugin-get-entry, it will be loaded at this time.

After instantiating the Service, the  run methods of the Service instance are called.

When the method is called  , the Service plug-in in run it will be loaded first  , and of course  the custom Service plug-in san.config.js we put  in it will be loaded; then, the loaded Service plug-ins will be loaded, and then they are ready to be executed in sequence.san.config.js

Before each Service plug-in is executed, it is instantiated  PluginAPIPluginAPI The instance provides the Service plug-in with a method for processing the logic related to Webpack construction. For example  configWebpack, through this method, we can obtain and modify the Webpack configuration in the Service plug-in. For example, in the Service plug-in example we wrote in the previous issue, we used this method to obtain The entry filename of the website.

Finally,  PluginAPI calling the function defined by the Service plug-in with the instance as an input parameter  apply officially starts the execution of the Service plug-in.



3) Simplified version of Service source code

Serviceusage of:

Service Implementation of:

PluginAPI Implementation of:

5. Finally

Thank you for reading this, and that's all for San CLI Implementation Principles. If you understand, please take my knee:



In 2021, San-CLI will continue to develop and optimize, such as whether to separate the eject function, CLI and Service. If you want to know about subsequent updates, you can follow San CLI's GitHub, welcome star, welcome issues, welcome pr.

Address: https://github.com/ecomfe/san-cli



Original link: https://mp.weixin.qq.com/s/-yhs_86CAMnsCxIYwrmMeQ






Baidu Architect

Baidu's official technical public account is online!

Technical dry goods · Industry information · Online salon · Industry conference

Recruitment information · Internal push information · Technical books · Baidu peripherals

All students are welcome to pay attention!

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324145222&siteId=291194637