package.json

{
  "name": "@tarojs/cli"."version": "3.3.17"."description": "cli tool for taro"."main": "index.js"."scripts": {
    // ...
    "build": "npm run clean && npm run prod"."dev": "tsc -w"."prod": "tsc".// ...
  },
  / /...
  "bin": {
    "taro": "bin/taro"
  },
  // ...
}
Copy the code

The @tarojs/cli module registers an executable named taro in the directory bin/taro.

@tarojs/cli/bin/taro.js

#! /usr/bin/env noderequire('.. /dist/util').printPkgVersion() // Each time run the taro command output version confidence ----> for example: 👽 taro v3.3.16/ / run.. /dist/cli exposes the run method in the CLI class, where.. /dist/cli refers to the file compiled by the TSC command @tarojs/cli/ SRC /cli.ts
const CLI = require('.. /dist/cli').default
new CLI().run()
Copy the code

#! Called shebang in Linux or Unix, it declares @tarojs/cli/bin/taro to be an executable. /usr/bin/env node means running the executable from node in /usr/bin/env.

@tarojs/cli/src/cli.ts

import * as path from 'path'import * as minimist from 'minimist' / / a command parameter parsing library at https://github.com/substack/minimist
import { Kernel } from '@tarojs/service'import init from './commands/init'
import customCommand from './commands/customCommand'
import { getPkgVersion } from './util'export default class CLI {
  appPath: string
  constructor (appPath) {
    this.appPath = appPath || process.cwd() // process.cwd() refers to the current path where the command is run
  }
​
  // The tarojs command is executed by @tarojs/cli/bin/taro.js
  run () {
    this.parseArgs()
  }
  
  parseArgs () {
    // Parse command arguments ----> for example: taro --version retrieves the value of --version
    const args = minimist(process.argv.slice(2), {
      
      // Declare an alias for the command for subsequent logic
      alias: {
        version: ['v'].help: ['h'].port: ['p'].resetCache: ['reset-cache'].// specially for rn, Removes cached files.
        publicPath: ['public-path'].// specially for rn, assets public path.
        bundleOutput: ['bundle-output'].// specially for rn, File name where to store the resulting bundle.
        sourcemapOutput: ['sourcemap-output'].// specially for rn, File name where to store the sourcemap file for resulting bundle.
        sourceMapUrl: ['sourcemap-use-absolute-path'].// specially for rn, Report SourceMapURL using its full path.
        sourcemapSourcesRoot: ['sourcemap-sources-root'].// specially for rn, Path to make sourcemaps sources entries relative to.
        assetsDest: ['assets-dest'] // specially for rn, Directory name where to store assets referenced in the bundle.
      },
      
      // Declare version and help as Boolean values
      boolean: ['version'.'help']})const _ = args._
    const command = _[0] // Specific commands to execute ----> For example, taro run... The value of command here is run
    if (command) {
      const kernel = new Kernel({
        appPath: this.appPath,
        presets: [
          path.resolve(__dirname, '. '.'presets'.'index.js')]})switch (command) {
        
        // Implement taro build... The logic executed after a command is executed
        case 'build': {
          let plugin
          let platform = args.type // If you run taro run --type appellate P, the value of platform is appellate P
          const { publicPath, bundleOutput, sourcemapOutput, sourceMapUrl, sourcemapSourcesRoot, assetsDest } = args
          
          // Taro build --plugin [typeName]... Change the value of Platform to Plugin and save the compilation platform of plugin
          if (typeof args.plugin === 'string') {
            plugin = args.plugin
            platform = 'plugin'
          }
          kernel.optsPlugins = [
            '@tarojs/plugin-platform-weapp'.'@tarojs/plugin-platform-alipay'.'@tarojs/plugin-platform-swan'.'@tarojs/plugin-platform-tt'.'@tarojs/plugin-platform-qq'.'@tarojs/plugin-platform-jd'
          ]
          customCommand('build', kernel, {
            // A list of parameters, omitted here
          })
          break
        }
          
        // execute taro init... The logic executed after a command is executed
        case 'init': {
          const projectName = _[1] || args.name
          init(kernel, {
            // A list of parameters, omitted here
          })
          break
        }
        default:
          customCommand(command, kernel, args)
          break}}else {
      if (args.h) {
        // Run taro --help to output help information
      } else if (args.v) {
        // Run taro --version to output version information}}}Copy the code

CustomCommand, Kernel, init are involved in @tarojs/ CLI, but we don’t know what they do yet. Kernels are implemented in another module, @tarojs/ Service.

@tarojs/cli/src/commands/customCommand.ts

import { Kernel } from '@tarojs/service'
export default function init (kernel: Kernel,{
  //A series of parameters, omitted here because they are not important :{//A series of parameter type definitions, omitted here){
  kernel.run({
    name: 'init'.opts: {
      // a list of omitted arguments}})}Copy the code

@tarojs/cli/src/commands/init.ts

import { Kernel } from '@tarojs/service'export default function customCommand (
  command: string,
  kernel: Kernel,
  args: { _: string[], [key: string] :any }
) {
  
  / /...
  
  // Omit a series of argument processing logic
  
  // ...
  
  kernel.run({
    name: command,
    opts: {
     // A list of parameters, omitted here}})}Copy the code

As you can see from the code, both the customCommand and init methods execute kernel.run. At this point we can see that Kernels are the key logic in the @tarojs/ CLI module. At this point we should go to the @tarojs/service module and see what Kernels actually do.