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-init
:san 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:
- Main process :
san-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 assan init
,san serve
(correspondingnpm start
) andsan build
(correspondingnpm run build
), we will enter the main process, and the main process will execute the corresponding commandshandler
. Some commandshandler
do not directly contain processing logic, but are introducedsan-cli-service
, such assan serve
andsan build
, when such commands are input, they will enter the Service process from the main process. - Service process :
san-cli-service/Service.js
The process mainly deals with the logic related to Webpack construction.
-
Plugins : Used to extend the functionality of San CLI:
-
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
; -
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:
-
check node version;
-
Check san-cli version;
-
Call to
san-cli/lib/Commander.js
create a command instance: -
add global
option
; -
Add middleware:
-
set global
logLevel;
-
set
NODE_ENV
environment variables; -
Add properties and methods such as
argv
logging. -
Load built-in commands:
init
,serve
,build
,inspect
,ui
etc.; -
Loading
package.json
andsanrc.json
declaring preset commands (custom commands); -
sanrc.json
It is the file that configures San CLI, and thesan.config.js
difference is that the latter is the file that configures the project. For details, please refer to the official documentation of San CLI. -
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 init
The 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 init
The 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 init
It mainly consists of four-step serial tasks:
-
Check the catalog and offline package status: check whether the local path of the project scaffolding template and the offline package are available;
-
Download the project scaffolding template: Download the project scaffolding template from a remote repository such as Github to the template cache directory;
-
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; -
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 init
The specific implementation is in the san-cli-command-init
module, the san-cli-command-init
module is a Command plug-in, the core of which is a TaskList
class, san init
and the essence of the execution process is: pass in the array composed of the above four tasks to instantiate TaskList
and call the run
method 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. .
complete
The 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.
TaskList
usage 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:
-
San CLI parses the commands entered in the command line in the main process
san serve
, and enters ;san-cli/commands/serve
handler
-
san serve
The main purpose of the commandhandler
is to instantiate,Service
and the instantiation will process the configuration item and the Service plug-in; -
Execute
service.run(callback)
, enter the Service process, the implementation of the Service process is mainly inservice.run
: -
loadEnv
: load the env file; -
loadProjectOptions
:loadsan.config.js
; -
init
:service start: -
Initialize the plugin, that is, execute the plugin in sequence;
-
Execute the webpackChain callback stack in turn;
-
Execute the webpackConfig callback stack in turn;
-
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 handler
. handler
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 PluginAPI
. PluginAPI
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
Service
usage 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!