{"id":10006482,"date":"2022-09-14T23:17:07","date_gmt":"2022-09-14T15:17:07","guid":{"rendered":"https:\/\/ityet.com\/?p=10006482"},"modified":"2022-09-14T23:17:07","modified_gmt":"2022-09-14T15:17:07","slug":"taro%e6%ba%90%e7%a0%81-cli%e9%a1%b9%e7%9b%ae%e5%88%9b%e5%bb%ba%e7%9a%84%e8%bf%87%e7%a8%8b","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006482","title":{"rendered":"Taro\u6e90\u7801-cli\u9879\u76ee\u521b\u5efa\u7684\u8fc7\u7a0b"},"content":{"rendered":"<h3>\u5165\u53e3<\/h3>\n<p><strong><code>\u57fa\u4e8eTaro3.5.5<\/code><\/strong><br \/>\u627e\u5230\u521b\u5efa<code>taro<\/code>\u9879\u76ee\u7684\u5165\u53e3\u6587\u4ef6\uff08packages\/taro-cli\/bin\/taro\uff09<\/p>\n<pre><code class=\"javascript\">\/\/ packages\/taro-cli\/bin\/taro\nrequire('..\/dist\/util').printPkgVersion()\n\nconst CLI = require('..\/dist\/cli').default\nnew CLI().run()<\/code><\/pre>\n<hr>\n<h3>Cli<\/h3>\n<p>packages\/taro-cli\/src\/cli.ts<br \/>\u8fd9\u4e2a\u6587\u4ef6\u7684\u4f5c\u7528\u5c31\u662f<strong>\u63a5\u53d7\u5185\u7f6e\u547d\u4ee4<\/strong>\u3001<strong>\u5206\u89e3\u5185\u7f6e\u547d\u4ee4<\/strong>\u3001<strong>\u9488\u5bf9\u4e0d\u540c\u7684\u5185\u7f6e\u547d\u4ee4\u6ce8\u518c\u5bf9\u5e94\u7684\u547d\u4ee4\u63d2\u4ef6<\/strong>\u3002<\/p>\n<p>\u9996\u5148\u521d\u59cb\u5316\u7684\u65f6\u5019\u83b7\u53d6\u6211\u4eec\u7684\u9879\u76ee\u8def\u52b2<\/p>\n<pre><code class=\"javascript\">  \/\/ packages\/taro-cli\/src\/cli.ts\n  constructor (appPath) {\n    this.appPath = appPath || process.cwd()\n  }<\/code><\/pre>\n<p>\u5728bin\/taro\u6587\u4ef6\u91cc\u6267\u884c<code>new CLI().run()<\/code>\u5728cli\u4e2d\u770b\u5230<code>run<\/code>\u65b9\u6cd5\u6267\u884c\u4e86<code>this.parseArgs()<\/code>\u5728<code>parseArgs<\/code>\u65b9\u6cd5\u91cc\u505a\u7684\u7b2c\u4e00\u4ef6\u662f\u5c31\u662f<strong>\u63a5\u53d7\u5185\u7f6e\u547d\u4ee4\u4ee5\u53ca\u5206\u89e3\u5185\u7f6e\u547d\u4ee4<\/strong><\/p>\n<pre><code class=\"javascript\">    \/\/ packages\/taro-cli\/src\/cli.ts\n    const args = minimist(process.argv.slice(2), {\n      alias: {\n        version: ['v'],\n        help: ['h'],\n        port: ['p'],\n        resetCache: ['reset-cache'], \/\/ specially for rn, Removes cached files.\n        publicPath: ['public-path'], \/\/ specially for rn, assets public path.\n        bundleOutput: ['bundle-output'], \/\/ specially for rn, File name where to store the resulting bundle.\n        sourcemapOutput: ['sourcemap-output'], \/\/ specially for rn, File name where to store the sourcemap file for resulting bundle.\n        sourceMapUrl: ['sourcemap-use-absolute-path'], \/\/ specially for rn, Report SourceMapURL using its full path.\n        sourcemapSourcesRoot: ['sourcemap-sources-root'], \/\/ specially for rn, Path to make sourcemaps sources entries relative to.\n        assetsDest: ['assets-dest'] \/\/ specially for rn, Directory name where to store assets referenced in the bundle.\n      },\n      boolean: ['version', 'help']\n    })<\/code><\/pre>\n<p>\u6253\u5370args\u7684\u7ed3\u679c\u53ef\u5f97<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2nQ9\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><br \/><code>args._<\/code>\u91cc\u5c31\u662f\u6211\u4eec\u7684\u547d\u4ee4\u8fd9\u91cc\u7684<code>aaaaa<\/code>\u53ef\u4ee5\u66ff\u6362\u6210\u4e3a<code>init\u3001build\u3001inspect<\/code>\u8fd9\u4e9btaro\u8ba4\u8bc6\u7684\u547d\u4ee4<\/p>\n<pre><code class=\"typescript\">    \/\/ packages\/taro-cli\/src\/cli.ts\n    const _ = args._\n    const command = _[0]<\/code><\/pre>\n<pre><code class=\"typescript\">    switch (command) {\n        case 'inspect':\n        case 'build': {...} \/\/ \u6784\u5efa\u9879\u76ee\n        case 'init': {...} \/\/ \u521b\u5efa\u9879\u76ee\n        ...\n      }<\/code><\/pre>\n<p><code>bbbbb<\/code>\u5c31\u662f\u66ff\u6362\u6211\u4eec\u7684\u9879\u76ee\u540d\u79f0\uff0c\u5177\u4f53\u7684cli\u547d\u4ee4\u53ef\u4ee5\u53c2\u8003\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=28cFnvddSDQNahZ3ZNyH8g%3D%3D.eKb2vhrMDRxw7vf8E5IUHc1U%2B%2Bk6XHSX9Pn8%2Fyx7I7TlMMEVTqnASr6bx71BkuqH\" rel=\"nofollow\">https:\/\/taro-docs.jd.com\/taro\/docs\/cli<\/a><\/p>\n<p>\u5f53\u9879\u76ee\u80fd\u83b7\u53d6\u7684command\u65f6<br \/>\u83b7\u53d6\u4e00\u4e9b\u6587\u4ef6\u7684\u8def\u5f84\uff08\u5982\u56fe\u5df2\u52a0\u4e0a\u8def\u5f84\u5907\u6ce8\uff09<\/p>\n<pre><code class=\"typescript\">      \/\/ packages\/taro-cli\/src\/cli.ts\n      \/\/ \u9879\u76ee\u8def\u5f84\n      const appPath = this.appPath\n      \/\/ \u63d2\u4ef6\u96c6\u8def\u5f84 taro-cli\/src\/presets\n      const presetsPath = path.resolve(__dirname, 'presets')\n      \/\/ \u63d2\u4ef6\u96c6\u8def\u5f84\u4e0b\u7684commands taro-cli\/src\/presets\/commands\n      const commandsPath = path.resolve(presetsPath, 'commands')\n      \/\/ \u63d2\u4ef6\u96c6\u8def\u5f84\u4e0b\u7684platforms taro-cli\/src\/presets\/platforms\n      const platformsPath = path.resolve(presetsPath, 'platforms')<\/code><\/pre>\n<p>\u83b7\u53d6commands\u6587\u4ef6\u5939\u4e0b\u7684\u6587\u4ef6<\/p>\n<pre><code class=\"typescript\">   \/\/ packages\/taro-cli\/src\/cli.ts\n   const commandPlugins = fs.readdirSync(commandsPath)\n   const targetPlugin = `${command}.js`<\/code><\/pre>\n<p>\u6253\u5370commandPlugins\u662f<code>presets\/commands<\/code>\u6587\u4ef6\u540d\u6570\u7ec4\uff0c\u6570\u7ec4\u7684\u5404\u4e2a\u6587\u4ef6\u5bf9\u5e94\u4e0d\u540c\u7684taro\u547d\u4ee4\u63d2\u4ef6<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2nXa\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<p>\u6839\u636e\u547d\u4ee4\u627e\u5230\u5bf9\u5e94\u7684\u547d\u4ee4\u63d2\u4ef6\uff0c\u5c31\u5c06\u63d2\u4ef6\u653e\u5230<strong>kernel<\/strong>\uff08\u7b2c\u4e8c\u4e2a\u91cd\u8981\u7684\u6587\u4ef6Kernel\u7c7b\uff09<\/p>\n<pre><code class=\"typescript\">      \/\/ packages\/taro-cli\/src\/cli.ts\n      \/\/ \u9488\u5bf9\u4e0d\u540c\u7684\u5185\u7f6e\u547d\u4ee4\u6ce8\u518c\u5bf9\u5e94\u7684\u547d\u4ee4\u63d2\u4ef6\n      if (commandPlugins.includes(targetPlugin)) {\n        kernel.optsPlugins.push(path.resolve(commandsPath, targetPlugin))\n      }<\/code><\/pre>\n<p>\u5f53\u7136\u5728\u5c06\u547d\u4ee4\u63d2\u4ef6\u653e\u5230<code>kernel<\/code>\u4e4b\u524d\u8fd8\u6709<strong>\u8bbe\u7f6e\u73af\u5883\u53d8\u91cf\u3001\u5b9e\u4f8b\u5316Kernel\u7c7b<\/strong><\/p>\n<p>\u4e4b\u540e\u5c31\u662f\u653e\u5165\u5230 <strong><code>customCommand<\/code><\/strong> \u6267\u884c <strong><code>kernel.run<\/code><\/strong> \uff08\u4ee5init\u4e3a\u4f8b\uff09<code>customCommand<\/code>\u51fd\u6570\u4e3b\u8981\u4f5c\u7528\u5c31\u662f\u6574\u7406\u914d\u7f6e\u6267\u884c<code>kernel.run<\/code>\u65b9\u6cd5<\/p>\n<pre><code class=\"typescript\">        \/\/ packages\/taro-cli\/src\/cli.ts\n        case 'init': {\n          \/\/ \u521d\u59cb\u5316\u521b\u5efa\n          customCommand(command, kernel, {\n            _,\n            appPath,\n            projectName: _[1] || args.name,\n            description: args.description,\n            typescript: args.typescript,\n            templateSource: args['template-source'],\n            clone: !!args.clone,\n            template: args.template,\n            css: args.css,\n            h: args.h\n          })\n          break\n        }<\/code><\/pre>\n<hr>\n<h3>Kernel<\/h3>\n<p>packages\/taro-service\/src\/Kernel.ts<br \/><code>Kernel<\/code>\u7c7b\u7ee7\u627f\u81ea\u7ee7\u627f<code>EventEmitter<\/code>\uff0c\u662f<code>Taro-Cli<\/code>\u7684\u6838\u5fc3\u7c7b\u4e4b\u4e00\uff0c\u4e3b\u8981\u7684\u4f5c\u7528\u662f<strong>\u521d\u59cb\u5316\u9879\u76ee\u914d\u7f6e\u3001\u53c2\u6570\uff1b\u6536\u96c6\u9879\u76ee\u7684\u63d2\u4ef6\u96c6\u548c\u63d2\u4ef6\uff08\u63d2\u4ef6\u5316\u673a\u5236\uff09\uff1b\u4fee\u6539webpack\uff1b\u6267\u884c\u94a9\u5b50\u51fd\u6570<\/strong>\u3002<\/p>\n<p>\u5728cli\u4e2dKernel\u5b9e\u4f8b\u5316\u65f6\u9996\u5148\u5c31\u662f\u521d\u59cb\u5316\u9879\u76ee\u914d\u7f6e\uff0c\u4e5f\u5c31\u662f\u4f60config\u76ee\u5f55\u914d\u7f6e\u7684\u90a3\u4e9b\uff0c\u521d\u59cb\u5316\u9879\u76ee\u8d44\u6e90\u76ee\u5f55\uff0c\u4f8b\u5982\uff1a\u8f93\u51fa\u76ee\u5f55\u3001\u4f9d\u8d56\u76ee\u5f55\uff0csrc\u3001config\u914d\u7f6e\u76ee\u5f55\u7b49\uff0c\u90e8\u5206\u914d\u7f6e\u662f\u5728\u4f60\u9879\u76ee\u7684config\/index.js\u4e2d\u7684config\u4e2d\u914d\u7f6e\u7684\u4e1c\u897f\uff0c\u5982sourcePath\u548coutputPath<br \/><a href=\"https:\/\/link.segmentfault.com\/?enc=psjnC8pdfnQjtZ3x0bf59A%3D%3D.xkF9WuIu9%2FX0jLZnjlFhP%2FKNv2wZAUBdNqbKr9Zpt%2FED676y6KEkgEBLZSBoSXf%2B\" rel=\"nofollow\">https:\/\/taro-docs.jd.com\/taro\/docs\/plugin<\/a> \u63d2\u4ef6\u73af\u5883\u53d8\u91cf<\/p>\n<pre><code class=\"typescript\">   \/\/ packages\/taro-service\/src\/Kernel.ts\n  const kernel = new Kernel({\n        appPath,\n        presets: [\n          path.resolve(__dirname, '.', 'presets', 'index.js')\n        ],\n        plugins: []\n      })\n      kernel.optsPlugins ||= []<\/code><\/pre>\n<p>1.\u6838\u5fc3\u7684\u65b9\u6cd5<code>run<\/code>\u65b9\u6cd5\u5927\u81f4\u7684\u6267\u884c\u6d41\u7a0b<\/p>\n<pre><code class=\"typescript\">\/\/ packages\/taro-service\/src\/Kernel.ts\nasync run (args: string | { name: string, opts?: any }) {\n    ...\n    \/\/ \u8bbe\u7f6e\u53c2\u6570\uff0c\u524d\u9762cli.ts\u4e2d\u4f20\u5165\u7684\u4e00\u4e9b\u9879\u76ee\u914d\u7f6e\u4fe1\u606f\u53c2\u6570\uff0c\u4f8b\u5982isWatch\u7b49\n    this.setRunOpts(opts)\n    \/\/ \u91cd\u70b9\uff1a\u521d\u59cb\u5316\u63d2\u4ef6\u96c6\u548c\u63d2\u4ef6\n    this.initPresetsAndPlugins()\n    \/\/ \u6ce8\u610f\uff1aKernel \u7684\u524d\u4e24\u4e2a\u751f\u547d\u5468\u671f\u94a9\u5b50\u662f onReady \u548c onStart\uff0c\u5e76\u6ca1\u6709\u6267\u884c\u64cd\u4f5c\uff0c\u5f00\u53d1\u8005\u5728\u81ea\u5df1\u7f16\u5199\u63d2\u4ef6\u65f6\u53ef\u4ee5\u6ce8\u518c\u5bf9\u5e94\u7684\u94a9\u5b50\n    \/\/ \u6267\u884conStart\u94a9\u5b50\n    await this.applyPlugins('onReady')\n    await this.applyPlugins('onStart')\n    \/\/ \u5904\u7406 --help \u7684\u65e5\u5fd7\u8f93\u51fa \u4f8b\u5982\uff1ataro build --help\n    if (opts?.isHelp) {\n      return this.runHelp(name)\n    }\n    \/\/ \u83b7\u53d6\u5e73\u53f0\u914d\u7f6e\n    if (opts?.options?.platform) {\n      opts.config = this.runWithPlatform(opts.options.platform)\n      \/\/ \u6267\u884c\u94a9\u5b50\u51fd\u6570 modifyRunnerOpts\n      \/\/ \u4f5c\u7528\uff1a\u4fee\u6539webpack\u53c2\u6570\uff0c\u4f8b\u5982\u4fee\u6539 H5 postcss options\n      await this.applyPlugins({\n        name: 'modifyRunnerOpts',\n        opts: {\n          opts: opts?.config\n        }\n      })\n    }\n    \/\/ \u6267\u884c\u4f20\u5165\u7684\u547d\u4ee4\u8fd9\u91cc\u662finit\n    await this.applyPlugins({\n      name,\n      opts\n    })\n  }\n<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4e2d\u63d0\u53ca\u4e86\u4e09\u4e2a\u94a9\u5b50\u65b9\u6cd5\uff0c\u6253\u5370\u51fa\u6765\u53ef\u4ee5\u77e5\u9053\u94a9\u5b50\u65b9\u6cd5\u6709\u5f88\u591a<\/p>\n<pre><code>Map(15) {\n  'onReady' =&gt; [ [Function: bound ] ],\n  'onStart' =&gt; [ [Function: bound ] ],\n  'modifyWebpackChain' =&gt; [ [Function: bound ] ],\n  'modifyBuildAssets' =&gt; [ [Function: bound ] ],\n  'modifyMiniConfigs' =&gt; [ [Function: bound ] ],\n  'modifyComponentConfig' =&gt; [ [Function: bound ] ],\n  'onCompilerMake' =&gt; [ [Function: bound ] ],\n  'onParseCreateElement' =&gt; [ [Function: bound ] ],\n  'onBuildStart' =&gt; [ [Function: bound ] ],\n  'onBuildFinish' =&gt; [ [Function: bound ] ],\n  'onBuildComplete' =&gt; [ [Function: bound ] ],\n  'modifyRunnerOpts' =&gt; [ [Function: bound ] ],\n  'writeFileToDist' =&gt; [ [Function (anonymous)] ],\n  'generateProjectConfig' =&gt; [ [Function (anonymous)] ],\n  'generateFrameworkInfo' =&gt; [ [Function (anonymous)] ]\n}<\/code><\/pre>\n<p>2.\u521d\u59cb\u5316<code>initPresetsAndPlugins<\/code>\u65b9\u6cd5\uff08\u5b98\u65b9\u7684\u5907\u6ce8\u4e5f\u5f88\u8be6\u7ec6\uff09<\/p>\n<pre><code class=\"typescript\">  \/\/ packages\/taro-service\/src\/Kernel.ts\n  initPresetsAndPlugins () {\n    const initialConfig = this.initialConfig\n    \/\/ \u6536\u96c6\u4e86\u6240\u6709\u7684\u63d2\u4ef6\u96c6\u548c\u63d2\u4ef6\u96c6\u5408\u3002\n    const allConfigPresets = mergePlugins(this.optsPresets || [], initialConfig.presets || [])()\n    const allConfigPlugins = mergePlugins(this.optsPlugins || [], initialConfig.plugins || [])()\n    ...\n    process.env.NODE_ENV !== 'test' &amp;&amp; createSwcRegister({\n      only: [...Object.keys(allConfigPresets), ...Object.keys(allConfigPlugins)]\n    }) \/\/ babel\u8f6c\u5316\n\n    this.plugins = new Map()\n    this.extraPlugins = {}\n\n    \/\/ \u52a0\u8f7d\u63d2\u4ef6\u96c6\u548c\u63d2\u4ef6\u5bfc\u51fa\u5bf9\u5e94\u7684\u6bcf\u4e00\u4e2a plugin \u90fd\u5305\u542b\u4e86\u4e00\u4e2a apply \u51fd\u6570\uff0c\u6267\u884c\u8be5\u8be5\u51fd\u6570\u53ef\u4ee5\u5bfc\u51fa\u5bf9\u5e94\u7684 Plugin \u6a21\u5757\n    this.resolvePresets(allConfigPresets)\n    this.resolvePlugins(allConfigPlugins)\n  }<\/code><\/pre>\n<p>\u6253\u5370 <code>this.plugin<\/code> \u6267\u884c\u4e86<code>apply<\/code>\u5c31\u80fd\u5bfc\u51fa\u5bf9\u5e94\u7684<code>Plugin<\/code>\u6a21\u5757<\/p>\n<pre><code>Map(6) {\n  '...\/taro\/packages\/taro-cli\/dist\/presets\/index.js' =&gt; {\n    id: '...\/taro\/packages\/taro-cli\/dist\/presets\/index.js',\n    path: '...\/taro\/packages\/taro-cli\/dist\/presets\/index.js',\n    type: 'Preset',\n    opts: {},\n    apply: [Function: apply]\n  },\n  ...\n}<\/code><\/pre>\n<p>3.\u6267\u884c\u94a9\u5b50\u51fd\u6570<code>applyPlugins<\/code><\/p>\n<pre><code class=\"typescript\">\/\/ packages\/taro-service\/src\/Kernel.ts\nasync applyPlugins (args: string | { name: string, initialVal?: any, opts?: any }) {\n    let name\n    let initialVal\n    let opts\n    if (typeof args === 'string') {\n      name = args\n    } else {\n      name = args.name\n      initialVal = args.initialVal\n      opts = args.opts\n    }\n...\n    \/\/ \u6b64\u5904\u6253\u5370this.hooks\n    const hooks = this.hooks.get(name) || []\n    if (!hooks.length) {\n      return await initialVal\n    }\n    const waterfall = new AsyncSeriesWaterfallHook(['arg'])\n    if (hooks.length) {\n...\n    }\n    return await waterfall.promise(initialVal)\n  }<\/code><\/pre>\n<p><code>onReady<\/code> \u548c <code>onStart<\/code>\u662f\u4e0d\u6267\u884c\u7684\u6211\u6ca1\u53ef\u4ee5\u5728<code>applyPlugins<\/code>\u65b9\u6cd5\u91cc\u6253\u5370<code>this.hooks<\/code>\uff0c\u6253\u5370\u7684\u7ed3\u679c\u662f\u51fa\u73b0\u4e09\u6b21\u5982\u4e0b\uff0c\u56e0\u4e3a\u6211\u4eec\u5728<code>initPresetsAndPlugins<\/code>\u8c03\u7528\u4e86\u4e09\u6b21\uff08\u6211\u4eec\u8fd9\u91cc\u6ca1\u6709\u6dfb\u52a0\u5e73\u53f0\u914d\u7f6e\u6240\u4ee5\u662f\u4e09\u6b21\uff09<\/p>\n<pre><code>Map(1) {\n  'init' =&gt; [\n    {\n      name: 'init',\n      optionsMap: [Object],\n      fn: [Function: fn],\n      plugin: '....\/taro\/packages\/taro-cli\/dist\/presets\/commands\/init.js'\n    }\n  ]\n}\n* 3<\/code><\/pre>\n<p>\u901a\u8fc7<code>get<\/code>\u65b9\u6cd5\uff0c<code>name<\/code>\u7b2c\u4e00\u6b21\u548c\u7b2c\u4e8c\u6b21\u5206\u522b\u4f20\u7684\u662f<code>onReady<\/code>\u548c<code>onStart<\/code>\uff0c\u6240\u4ee5\u662f\u76f4\u63a5\u8fd4\u56de<code>initialVal<\/code>\uff0c\u7b2c\u4e09\u6b21\u4f20\u5165\u4e86<code>init<\/code>\uff0c\u5339\u914d\u4e0a\u6211\u4eec\u4e4b\u524d\u6302\u8f7d\u5230\u4e86<code>kernel<\/code>\u4e0a\u7684<code>init<\/code><\/p>\n<pre><code class=\"typescript\">    \/\/ packages\/taro-service\/src\/Kernel.ts\n    const hooks = this.hooks.get(name) || []\n    if (!hooks.length) {\n      return await initialVal\n    }<\/code><\/pre>\n<pre><code class=\"typescript\">      \/\/ packages\/taro-cli\/src\/cli.ts \uff08\u8fd9\u91cc\u662f\u6302\u8f7dinit\u5230kernel\uff09\n      \/\/ \u9488\u5bf9\u4e0d\u540c\u7684\u5185\u7f6e\u547d\u4ee4\u6ce8\u518c\u5bf9\u5e94\u7684\u547d\u4ee4\u63d2\u4ef6\n      if (commandPlugins.includes(targetPlugin)) {\n        kernel.optsPlugins.push(path.resolve(commandsPath, targetPlugin))\n      }<\/code><\/pre>\n<p>\u5339\u914d\u5230\u4e4b\u540e\u5728<code>applyPlugins<\/code>\u65b9\u6cd5\u7684\u540e\u534a\u6bb5\u7ee7\u7eed\u6267\u884c\u5982\u4e0b<\/p>\n<pre><code class=\"typescript\">   \/\/ packages\/taro-service\/src\/Kernel.ts\n   \/\/ \u5b9e\u4f8b\u5316AsyncSeriesWaterfallHook\u5b9e\u4f8b\u4e00\u4e2a\u5f02\u6b65\u94a9\u5b50\uff0c\u4f1a\u4f20\u9012\u8fd4\u56de\u7684\u53c2\u6570\n   const waterfall = new AsyncSeriesWaterfallHook(['arg'])\n   if (hooks.length) {\n      const resArr: any[] = []\n      for (const hook of hooks) {\n        waterfall.tapPromise({\n          name: hook.plugin!,\n          stage: hook.stage || 0,\n          \/\/ @ts-ignore\n          before: hook.before\n        }, async arg =&gt; {\n          \/\/ \u5728\u8fd9\u91cc\u628a\u6211\u4eec\u7684\u63d2\u4ef6\u65b9\u6cd5\u7ed9\u6267\u884c\u4e86\uff0c\u4e5f\u5c31\u662f\u6267\u884c\u4e86\u4e0a\u9762\u6253\u5370\u7684init\u91cc\u7684fn\n          \/\/ init\u63d2\u4ef6\u6240\u5728\u7684\u4f4d\u7f6epackages\/taro-cli\/src\/presets\/commonds\/init.ts\n          const res = await hook.fn(opts, arg)\n          \n          if (IS_MODIFY_HOOK.test(name) &amp;&amp; IS_EVENT_HOOK.test(name)) {\n            return res\n          }\n          if (IS_ADD_HOOK.test(name)) {\n            resArr.push(res)\n            return resArr\n          }\n          return null\n        })\n      }\n   }\n   return await waterfall.promise(initialVal)<\/code><\/pre>\n<p>\u8fd9\u662f\u6211\u4eec\u5185\u7f6e\u547d\u4ee4\u8f93\u5165<code>init<\/code>\uff0c\u5f53\u6211\u8f93\u5165<code>help\u3001build...<\/code>\u4e5f\u662f\u4e00\u6837\u7684\u4e00\u4e2a\u8fc7\u7a0b\uff0c\u90fd\u662f<code>\u521d\u59cb\u5316\u9879\u76ee\u914d\u7f6e\u3001\u53c2\u6570<\/code>=&gt;<code>\u6536\u96c6\u9879\u76ee\u7684\u63d2\u4ef6\u96c6\u548c\u63d2\u4ef6<\/code>=&gt;<code>\u6267\u884c\u94a9\u5b50<\/code>\u3002<\/p>\n<hr>\n<h3>init<\/h3>\n<p>packages\/taro-cli\/src\/presets\/commonds\/init.ts<\/p>\n<p>\u901a\u8fc7<a href=\"https:\/\/link.segmentfault.com\/?enc=LsEynv%2B%2B51AxGx2blczPLw%3D%3D.2lnuOFNR1DW01xVqM25uZOZ%2FKmscjqdPFHaH6rtcmo18tG3%2Bsh9ax3krHTlNxIzM\" rel=\"nofollow\">\u63d2\u4ef6\u673a\u5236<\/a>\u628a<code>init<\/code>\u6302\u8f7d\u5230<code>kernel<\/code>\u5728<code>applyPlugins<\/code>\u6267\u884c<code>fn<\/code>\uff0c\u5728init\u91cc\u4e3b\u8981\u7684\u4f5c\u7528\u5c31\u662f<strong>\u5f15\u5165\u548c\u5b9e\u4f8b\u5316Project<\/strong>\u3001<strong>\u6267\u884ccreate<\/strong><\/p>\n<pre><code class=\"typescript\">\/\/ packages\/taro-cli\/src\/presets\/commonds\/init.ts\nimport { IPluginContext } from '@tarojs\/service'\n\nexport default (ctx: IPluginContext) =&gt; {\n  ctx.registerCommand({\n    name: 'init',\n    optionsMap: {\n        ...\n    },\n    async fn (opts) {\n      \/\/ init project\n      const { appPath } = ctx.paths\n      const { options } = opts\n      const { projectName, templateSource, clone, template, description, typescript, css, npm } = options\n      \/\/ \u5f15\u5165\u548c\u5b9e\u4f8b\u5316Project\n      const Project = require('..\/..\/create\/project').default\n      const project = new Project({\n         ...\n      })\n      \/\/ \u6267\u884ccreate\n      project.create()\n    }\n  })\n}<\/code><\/pre>\n<hr>\n<h3>Project<\/h3>\n<p>packages\/taro-cli\/src\/create\/project.ts<br \/><code>Project<\/code>\u7ee7\u627f<code>Creator<\/code>\uff0c\u5728<code>init<\/code>\u63d2\u4ef6\u4e2d\u88ab\u5b9e\u4f8b\u5316\u5e76\u8c03\u7528\u4e86<code>create<\/code>\u65b9\u6cd5\uff0c\u4e3b\u8981\u7684\u4f5c\u7528\u5c31\u662f<strong>Taro\u9879\u76ee\u521b\u5efa\u524d\u7684\u9879\u76ee\u4fe1\u606f\u586b\u5199\uff0c\u4e4b\u540e\u5c31\u662f\u6267\u884ccreateApp<\/strong><br \/>Project\u7684\u6838\u5fc3\u65b9\u6cd5\u5c31\u662f<code>create<\/code><\/p>\n<pre><code class=\"typescript\">  async create () {\n    try {\n      \/\/ \u586b\u5199\u9879\u76ee\u540d\u79f0\u3001\u4ecb\u7ecd\u3001\u9009\u62e9\u6846\u67b6\u7b49\n      const answers = await this.ask()\n      const date = new Date()\n      this.conf = Object.assign(this.conf, answers)\n      this.conf.date = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`\n      \/\/ \u5f53\u6240\u6709\u7684\u90fd\u5df2\u7ecf\u5728\u63a7\u5236\u53f0\u8be2\u95ee\u5b8c\u6210\u540e\u6267\u884cwrite\n      this.write()\n    } catch (error) {\n      console.log(chalk.red('\u521b\u5efa\u9879\u76ee\u5931\u8d25: ', error))\n    }\n  }<\/code><\/pre>\n<pre><code class=\"typescript\">  write (cb?: () =&gt; void) {\n    this.conf.src = SOURCE_DIR\n    \/\/ \u521b\u5efa\u9879\u76ee\n    createApp(this, this.conf, cb).catch(err =&gt; console.log(err))\n  }<\/code><\/pre>\n<hr>\n<h3>createApp<\/h3>\n<p>packages\/taro-cli\/src\/create\/init.ts<br \/>\u4e3b\u8981\u4f5c\u7528<strong>\u9009\u62e9\u6a21\u677f\u521b\u5efa\u9879\u76ee<\/strong><br \/>1.\u9009\u62e9\u6a21\u677f<\/p>\n<pre><code class=\"typescript\">const templatePath = creator.templatePath(template)<\/code><\/pre>\n<p>\u6a21\u677f\u7684\u4f4d\u7f6e\u5c31<strong>packages\/taro-cli\/templates<\/strong>\u5927\u6982\u6709\u5341\u51e0\u79cd\u6a21\u677f<\/p>\n<p>2.\u521b\u5efa\u6587\u4ef6<\/p>\n<pre><code class=\"typescript\">  \/\/ npm &amp; yarn\n  const version = getPkgVersion()\n\n  \/\/ \u904d\u5386\u51fa\u6a21\u677f\u4e2d\u6240\u6709\u6587\u4ef6\n  const files = await getAllFilesInFolder(templatePath, doNotCopyFiles)\n\n  \/\/ \u5f15\u5165\u6a21\u677f\u7f16\u5199\u8005\u7684\u81ea\u5b9a\u4e49\u903b\u8f91\n  const handlerPath = path.join(templatePath, TEMPLATE_CREATOR)\n  const handler = fs.existsSync(handlerPath) ? require(handlerPath).handler : null\n\n  \/\/ \u4e3a\u6240\u6709\u6587\u4ef6\u8fdb\u884c\u521b\u5efa\n  logs.push(\n    ...createFiles(creator, files, handler, {\n      ...params,\n      framework,\n      version,\n      templatePath,\n      projectPath,\n      pageName: 'index',\n      period: 'createApp'\n    })\n  )<\/code><\/pre>\n<p>\u4e3b\u8981\u7684\u6587\u4ef6\u521b\u5efa\u5b8c\u6210\u4e4b\u540e\u8fd8\u6709git\u548crn\u90e8\u5206<\/p>\n<hr>\n<p><strong>\u8fd9\u4e00\u4e2a\u6d41\u7a0b\u4e0b\u6765\u4ee5\u540e\u4e00\u4e2aTaro\u9879\u76ee\u5c31\u521b\u5efa\u5b8c\u6210\u4e86<\/strong><br \/>\u521b\u5efa\u7684\u9879\u76ee\u5c31\u5728bin\u6587\u4ef6\u4e0b<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2pem\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042478842\">https:\/\/segmentfault.com\/a\/1190000042478842<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5165\u53e3 \u57fa\u4e8eTaro3.5.5\u627e\u5230\u521b\u5efataro\u9879\u76ee\u7684\u5165\u53e3\u6587\u4ef6\uff08packages\/taro-cli\/bin\/tar [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006482","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006482","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006482"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006482\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}