{"id":10020622,"date":"2025-01-16T00:16:23","date_gmt":"2025-01-15T16:16:23","guid":{"rendered":"https:\/\/itmax.cn\/?p=10020622"},"modified":"2025-01-16T00:16:23","modified_gmt":"2025-01-15T16:16:23","slug":"taro-%e6%ba%90%e7%a0%81%e6%8f%ad%e7%a7%98%ef%bc%9a3-%e6%af%8f%e6%ac%a1%e5%88%9b%e5%bb%ba%e6%96%b0%e7%9a%84-taro-%e9%a1%b9%e7%9b%ae%ef%bc%88taro-init%ef%bc%89%e7%9a%84%e8%83%8c%e5%90%8e%e5%8e%9f","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10020622","title":{"rendered":"Taro \u6e90\u7801\u63ed\u79d8\uff1a3. \u6bcf\u6b21\u521b\u5efa\u65b0\u7684 taro \u9879\u76ee\uff08taro init\uff09\u7684\u80cc\u540e\u539f\u7406\u662f\u4ec0\u4e48"},"content":{"rendered":"<h2>1. \u524d\u8a00<\/h2>\n<p>\u5927\u5bb6\u597d\uff0c\u6211\u662f<a href=\"https:\/\/link.segmentfault.com\/?enc=VZHrCSxJX%2FhN79VDMyrFKA%3D%3D.5eXA0FuyW%2F7koXcqJAar%2FbldGltSlQA%2BqpOwNXiLt0BSDOHaRGOHs4m2eV57wB52\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u82e5\u5ddd<\/a>\uff0c\u6b22\u8fce\u5173\u6ce8\u6211\u7684<a href=\"https:\/\/link.segmentfault.com\/?enc=X0iwJTaKHNv0K4PadZW0wg%3D%3D.vtUOAmD7AnO61CnWuv6cbdj7mZ521FjxTTVrBhZYHd9sR4n66Lqj81BP0%2B3Z4tpI4JFO9cMXQHDi%2Bo814IIZFQ%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u516c\u4f17\u53f7\uff1a\u82e5\u5ddd\u89c6\u91ce<\/a>\u3002\u6211\u503e\u529b\u6301\u7eed\u7ec4\u7ec7\u4e86 3 \u5e74\u591a<a href=\"https:\/\/link.segmentfault.com\/?enc=T5aAeLNlL57yFDk0vt0YLg%3D%3D.Yidbz%2BwDKWmnU0Zzuo15PV0hbhVNBWaFmkUCN3TTd6RxBY21tKY7hKCqgQKZFdu5\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u6bcf\u5468\u5927\u5bb6\u4e00\u8d77\u5b66\u4e60 200 \u884c\u5de6\u53f3\u7684\u6e90\u7801\u5171\u8bfb\u6d3b\u52a8<\/a>\uff0c\u611f\u5174\u8da3\u7684\u53ef\u4ee5<a href=\"https:\/\/link.segmentfault.com\/?enc=%2FovTg4pwtua%2B61%2BeVodSLQ%3D%3D.pM%2FPxz1fasEDJx0kRUPDfsL4GKFzA2pug5Iq4%2FVPTVghALWvs%2BWK39tSwM3mp%2BbO\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u70b9\u6b64\u626b\u7801\u52a0\u6211\u5fae\u4fe1 <code>ruochuan02<\/code> \u53c2\u4e0e<\/a>\u3002\u53e6\u5916\uff0c\u60f3\u5b66\u6e90\u7801\uff0c\u6781\u529b\u63a8\u8350\u5173\u6ce8\u6211\u5199\u7684\u4e13\u680f<a href=\"https:\/\/link.segmentfault.com\/?enc=VFee5ZaIJigBTcQ5AzVwAA%3D%3D.nW%2BXap7dn5COyQps8K1cOqWqvSNhJdn8MmpuJpYIgvnyJK8MwagaizIFgvebWreI\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u300a\u5b66\u4e60\u6e90\u7801\u6574\u4f53\u67b6\u6784\u7cfb\u5217\u300b<\/a>\uff0c\u76ee\u524d\u662f\u6398\u91d1\u5173\u6ce8\u4eba\u6570\uff086k+\u4eba\uff09\u7b2c\u4e00\u7684\u4e13\u680f\uff0c\u5199\u6709\u51e0\u5341\u7bc7\u6e90\u7801\u6587\u7ae0\u3002<\/p>\n<p>\u622a\u81f3\u76ee\u524d\uff08<code>2024-07-17<\/code>\uff09\uff0c<code>taro<\/code> \u6b63\u5f0f\u7248\u662f <code>3.6.34<\/code>\uff0c<a href=\"https:\/\/link.segmentfault.com\/?enc=F8YV7Q5rS5yIp9VWYGldgw%3D%3D.InfCIo%2B6Q3cNyzobivJjRV0mdxYOQsfTKhMX5mEwcMth6sQ0%2BiDCCzqs9lWRKp71\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Taro 4.0 Beta \u53d1\u5e03\uff1a\u652f\u6301\u5f00\u53d1\u9e3f\u8499\u5e94\u7528\u3001\u5c0f\u7a0b\u5e8f\u7f16\u8bd1\u6a21\u5f0f\u3001Vite \u7f16\u8bd1\u7b49<\/a>\u3002\u6587\u7ae0\u63d0\u5230\u5c06\u4e8e 2024 \u5e74\u7b2c\u4e8c\u5b63\u5ea6\uff0c\u53d1\u5e03 <code>4.x<\/code>\u3002\u76ee\u524d\u5df2\u7ecf\u53d1\u5e03 <code>4.x<\/code>\u3002\u6240\u4ee5\u6211\u4eec\u76f4\u63a5\u5b66\u4e60 <code>main<\/code> \u5206\u652f\u6700\u65b0\u7248\u672c\u662f <code>4.0.2<\/code>\u3002<\/p>\n<p>\u8ba1\u5212\u5199\u4e00\u4e2a Taro \u6e90\u7801\u63ed\u79d8\u7cfb\u5217\uff0c\u535a\u5ba2\u5730\u5740\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=iOVh91PenW1vHWhe0RgdVg%3D%3D.XtPeEbdFQAyVy%2BP5SzUTYwnXljWtQoaea1XT2tOSr4vsReYZ0%2F5dNC78m4tUBIB8\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">https:\/\/ruochuan12.github.io\/taro<\/a> \u53ef\u4ee5\u52a0\u5165\u4e66\u7b7e\uff0c\u6301\u7eed\u5173\u6ce8<a href=\"https:\/\/link.segmentfault.com\/?enc=2nMuACqbejD2gFKeKSUfug%3D%3D.thmx980bnD6kFP6dA61N%2FjHqtmNYJgOEN9K%2Fbf%2BquMVNipqUns6IrmEHzS34ZCal\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u82e5\u5ddd<\/a>\u3002<\/p>\n<ul>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=FYVMEdiXL%2BokOaWZ8cDJqQ%3D%3D.L1HCXOYuGOEctoQQPBuoZKYWfScBHAOZNnbLhu4A5QRDrkW3zTAp%2BEVAwP%2FMO6Go\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">1. \u63ed\u5f00\u6574\u4e2a\u67b6\u6784\u7684\u5165\u53e3 CLI =&gt; taro init \u521d\u59cb\u5316\u9879\u76ee\u7684\u79d8\u5bc6<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=p0kdnJ7orbTw1eY7SVl0hw%3D%3D.Zox0zOPT4aYsEARQ80iM7ECAy99ic7zeEYSDriCC56CCjTPaB5E9lFqGnHON7P1e\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">2. \u63ed\u5f00\u6574\u4e2a\u67b6\u6784\u7684\u63d2\u4ef6\u7cfb\u7edf\u7684\u79d8\u5bc6<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=%2BWErB%2BlO587l72OHAyzfiA%3D%3D.Xgdf2wk1xUyXZRmr4FbvZJLRDfLWr%2BaM%2FeJRpkoUwdRSKYuH5QoOfs1FJxb04y%2F2\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">3. \u6bcf\u6b21\u521b\u5efa\u65b0\u7684 taro \u9879\u76ee\uff08taro init\uff09\u7684\u80cc\u540e\u539f\u7406\u662f\u4ec0\u4e48<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=lHf4WY2qUOySU7elDPptAg%3D%3D.Z79HR9m%2FUgq5R6t3veHW4iRJONQgu3MamEx4Om0O1%2BlxL385frWeR0ra3epFGmGt\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">4. \u6bcf\u6b21 npm run dev:weapp \u5f00\u53d1\u5c0f\u7a0b\u5e8f\uff0cbuild \u7f16\u8bd1\u6253\u5305\u662f\u5982\u4f55\u5b9e\u73b0\u7684\uff1f<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=ZaExvjPrGMyi8Mhnquo%2BIQ%3D%3D.4Wa08dTrDJMe0dRSZm%2BQGzU2gkVJhnG31iUFRkEt0SCx9wT3ia4p3AaVbKpS3xKY\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">5. \u9ad8\u624b\u90fd\u5728\u7528\u7684\u53d1\u5e03\u8ba2\u9605\u673a\u5236 Events \u5728 Taro \u4e2d\u662f\u5982\u4f55\u5b9e\u73b0\u7684\uff1f<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=R4iMcG1ypI3HS0as0JWIdg%3D%3D.KOOCSUmVWThoj6EqMznCKEnF%2BWVf85%2BTSpcqQ7Y9nAqVJHH7hSgfddDinKRJI0xt\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">6. \u4e3a\u4ec0\u4e48\u901a\u8fc7 Taro.xxx \u80fd\u8c03\u7528\u5404\u4e2a\u5c0f\u7a0b\u5e8f\u5e73\u53f0\u7684 API\uff0c\u5982\u4f55\u8bbe\u8ba1\u5b9e\u73b0\u7684?<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=S7%2BPb27tvQkGx6wJ42QmWg%3D%3D.EgdRzeB1Ug%2BHE%2F7VYg87Dzq3OxzppJrYoe4XrMhOvfAcncpvPL9WNnZ3PktBH2L4\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">7. Taro.request \u548c\u8bf7\u6c42\u54cd\u5e94\u62e6\u622a\u5668\u662f\u5982\u4f55\u5b9e\u73b0\u7684<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=NBJA77GuIXvhZMFN%2B4BoTg%3D%3D.bAwVrGmrsj1yd1Uxp9ORfgnt90HLKSCycYhHvimnSO%2FYBPsWQkTyOdZZIxxGpfTM\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">8. Taro \u662f\u5982\u4f55\u4f7f\u7528 webpack \u6253\u5305\u6784\u5efa\u5c0f\u7a0b\u5e8f\u7684\uff1f<\/a><\/li>\n<li>[x] <a href=\"https:\/\/link.segmentfault.com\/?enc=umcXHQSJZSx6MHm1xOHiqg%3D%3D.NF5uTcM8mT1guvE%2FDG1m1KyDv2Ty%2BQmggaNdtwszP801lU%2F0jbsMvtrknQI2NFeB\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">9. Taro \u662f\u5982\u4f55\u751f\u6210 webpack \u914d\u7f6e\u8fdb\u884c\u6784\u5efa\u5c0f\u7a0b\u5e8f\u7684\uff1f<\/a><\/li>\n<li>[ ] \u7b49\u7b49<\/li>\n<\/ul>\n<p>\u5b66\u5b8c\u672c\u6587\uff0c\u4f60\u5c06\u5b66\u5230\uff1a<\/p>\n<pre><code class=\"bash\">1. taro init \u521d\u59cb\u5316\u9879\u76ee\uff0c\u80cc\u540e\u539f\u7406\u662f\u4ec0\u4e48\uff1f\n2. \u5982\u4f55\u8c03\u8bd5 taro cli init \u6e90\u7801\n3. nodejs \u5982\u4f55\u8c03\u7528 rust \u4ee3\u7801\uff1f\n4. \u5982\u4f55\u8c03\u8bd5 rust \u4ee3\u7801\n5. \u5982\u4f55\u4f7f\u7528 handlebars \u6a21\u677f\u5f15\u64ce\n\u7b49\u7b49<\/code><\/pre>\n<p>\u5173\u4e8e\u514b\u9686\u9879\u76ee\u3001\u73af\u5883\u51c6\u5907\u3001\u5982\u4f55\u8c03\u8bd5\u4ee3\u7801\u7b49\uff0c\u53c2\u8003<a href=\"https:\/\/link.segmentfault.com\/?enc=yP3IunaQalJTS18fSuhfnA%3D%3D.%2F%2F6JNMw1etroLaa2Ezx0Q71osFLfn57p2oLKglN6RX7%2BjOn4BoLLJhiUh80vOyIpLDXrtbybwR68l%2BK2YARAIQ%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u7b2c\u4e00\u7bc7\u6587\u7ae0-\u51c6\u5907\u5de5\u4f5c\u3001\u8c03\u8bd5<\/a>\u3002\u540e\u7eed\u6587\u7ae0\u57fa\u672c\u4e0d\u518d\u8fc7\u591a\u8d58\u8ff0\u3002<\/p>\n<blockquote><p>\u6587\u7ae0\u4e2d\u57fa\u672c\u662f\u5148\u653e\u6e90\u7801\uff0c\u6e90\u7801\u4e2d\u4e0d\u505a\u8fc7\u591a\u89e3\u91ca\u3002\u6e90\u7801\u540e\u9762\u518d\u505a\u7b80\u5355\u8bb2\u8ff0\u3002<\/p><\/blockquote>\n<p>\u4f17\u6240\u5468\u77e5\uff0c\u6211\u4eec\u6700\u5f00\u59cb\u521d\u59cb\u5316\u9879\u76ee\u65f6\u90fd\u662f\u4f7f\u7528 <code>taro init<\/code> \u547d\u4ee4\uff0c\u672c\u6587\u6211\u4eec\u7ee7\u7eed\u6765\u5b66\u4e60\u8fd9\u4e2a\u547d\u4ee4\u662f\u5982\u4f55\u5b9e\u73b0\u7684\u3002<\/p>\n<p>\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 <a href=\"https:\/\/link.segmentfault.com\/?enc=qq7z7%2FX0ttdl31TUDmRAGA%3D%3D.m%2Bvo%2FABn9HcctScFRJfF6W8hjlojM0JRY0PNEBiRyPXhNmZv%2BYtLEc5bQojgpT8gS%2FLTGevp%2FtEZGcFIICfQGA%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">npm-dist-tag \u6587\u6863<\/a> \u547d\u4ee4\u6765\u67e5\u770b <code>@tarojs\/cli<\/code> \u5305\u7684\u6240\u6709 <code>tag<\/code> \u7248\u672c\u3002<\/p>\n<pre><code class=\"bash\">npm dist-tag @tarojs\/cli<\/code><\/pre>\n<p>\u5982\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025876\" alt=\"taro-cli-npm-dist-tag.png\" title=\"taro-cli-npm-dist-tag.png\"><\/p>\n<p>\u76ee\u524d <code>latest<\/code> \u6807\u7b7e\uff08\u9ed8\u8ba4\u7248\u672c\uff09\u662f <code>3.6.34<\/code>\uff0c<code>next<\/code> \u6807\u7b7e\u662f <code>4.0.0<\/code>\u3002\u540e\u7eed <code>latest<\/code> \u6807\u7b7e\u4f1a\u8bbe\u7f6e\u4e3a <code>4.x<\/code> \u7248\u672c\u3002<\/p>\n<p>\u6211\u4eec\u5148\u7528 <code>@tarojs\/cli@next<\/code> \u521d\u59cb\u5316\u4e00\u4e2a\u9879\u76ee\u770b\u770b\u3002\u5168\u5c40\u5b89\u88c5\u76f8\u5bf9\u9ebb\u70e6\uff0c\u6211\u4eec\u4e0d\u5168\u5c40\u5b89\u88c5\uff0c\u4f7f\u7528 <code>npx<\/code> \u6765\u8fd0\u884c <code>next tag<\/code> \u7248\u672c\u3002<\/p>\n<pre><code class=\"bash\">npx @tarojs\/cli@next init taro4-next<\/code><\/pre>\n<p>\u8fd9\u4e2a\u521d\u59cb\u5316\u5b8c\u6574\u7684\u8fc7\u7a0b\uff0c\u6211\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=vUa3PAoYko4554yb27bduw%3D%3D.vNiEugVADQs0hQ7lyHIUtqt929aqnZeR219nQ5c2cWF%2FO5YfmSEIIWh4NSAXJuim\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">GIPHY CAPTURE<\/a> \u5de5\u5177\u5f55\u5236\u4e86\u4e00\u4e2a<code>gif<\/code>\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025877\" alt=\"taro-init-gif-high.gif\" title=\"taro-init-gif-high.gif\" loading=\"lazy\"><\/p>\n<p>\u6211\u4eec\u63a5\u4e0b\u6765\u5c31\u662f\u4e00\u6b65\u6b65\u6765\u5206\u6790\u8fd9\u4e2a <code>gif<\/code> \u4e2d\u7684\u6bcf\u4e00\u4e2a\u6b65\u9aa4\u7684\u5b9e\u73b0\u539f\u7406\u3002<\/p>\n<h2>2. \u8c03\u8bd5 taro init<\/h2>\n<p>\u6211\u4eec\u5728 <code>.vscode\/launch.json<\/code> \u4e2d\u7684\u539f\u6709\u7684 <code>CLI debug<\/code> \u547d\u4ee4\u884c\u8c03\u8bd5\u914d\u7f6e\uff0c\u6dfb\u52a0 <code>init<\/code> \u914d\u7f6e\u5982\u4e0b\uff1a<\/p>\n<pre><code>\/\/ .vscode\/launch.json\n{\n  &quot;version&quot;: &quot;0.2.0&quot;,\n  &quot;configurations&quot;: [{\n      &quot;type&quot;: &quot;node&quot;,\n      &quot;request&quot;: &quot;launch&quot;,\n      &quot;name&quot;: &quot;CLI debug&quot;,\n      &quot;program&quot;: &quot;${workspaceFolder}\/packages\/taro-cli\/bin\/taro&quot;,\n+     &quot;console&quot;: &quot;integratedTerminal&quot;,\n+     &quot;args&quot;: [\n+       &quot;init&quot;,\n+       &quot;taro-init-test&quot;,\n+     ],\n      \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801...\n      &quot;skipFiles&quot;: [&quot;&lt;node_internals&gt;\/**&quot;]\n    }]\n}<\/code><\/pre>\n<p>\u5176\u4e2d <code>&quot;console&quot;: &quot;integratedTerminal&quot;,<\/code> \u914d\u7f6e\u662f\u4e3a\u4e86\u5728\u8c03\u8bd5\u65f6\uff0c\u53ef\u4ee5\u5728\u7ec8\u7aef\u8f93\u5165\u548c\u4ea4\u4e92\u3002<\/p>\n<h2>3. init \u547d\u4ee4\u884c fn \u51fd\u6570<\/h2>\n<p>\u6839\u636e\u524d\u9762\u4e24\u7bc7 <a href=\"https:\/\/link.segmentfault.com\/?enc=fyxVvCjcH1tkCJq9Kfhxow%3D%3D.5xiiQ6%2BYTk5OXBU9DfhJqQhpTd4crmRcZn36vaaYedPFqdKYH%2BF%2FuE6uusM4I4eI\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">1. taro cli init<\/a>\u3001<a href=\"https:\/\/link.segmentfault.com\/?enc=M5TjcBRhR6LVG3CWIkYmaA%3D%3D.JvbcamAKaApCDheichIvkWnaG%2FIbnF9SfVz05wHOD%2F%2BmSuS1yE97CjfsE6fobmXn\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">2. taro \u63d2\u4ef6\u673a\u5236<\/a> \u6587\u7ae0\uff0c\u6211\u4eec\u53ef\u4ee5\u5f97\u77e5\uff1a<code>taro init<\/code> \u521d\u59cb\u5316\u547d\u4ee4\uff0c\u6700\u7ec8\u8c03\u7528\u7684\u662f <code>packages\/taro-cli\/src\/presets\/commands\/init.ts<\/code> \u6587\u4ef6\u4e2d\u7684 <code>ctx.registerCommand<\/code> \u6ce8\u518c\u7684 <code>init<\/code> \u547d\u4ee4\u884c\u7684 <code>fn<\/code> \u51fd\u6570\u3002<\/p>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/presets\/commands\/init.ts\nimport type { IPluginContext } from '@tarojs\/service'\n\nexport default (ctx: IPluginContext) =&gt; {\n  ctx.registerCommand({\n    name: 'init',\n    optionsMap: {\n      '--name [name]': '\u9879\u76ee\u540d\u79f0',\n      '--description [description]': '\u9879\u76ee\u4ecb\u7ecd',\n      '--typescript': '\u4f7f\u7528TypeScript',\n      '--npm [npm]': '\u5305\u7ba1\u7406\u5de5\u5177',\n      '--template-source [templateSource]': '\u9879\u76ee\u6a21\u677f\u6e90',\n      '--clone [clone]': '\u62c9\u53d6\u8fdc\u7a0b\u6a21\u677f\u65f6\u4f7f\u7528git clone',\n      '--template [template]': '\u9879\u76ee\u6a21\u677f',\n      '--css [css]': 'CSS\u9884\u5904\u7406\u5668(sass\/less\/stylus\/none)',\n      '-h, --help': 'output usage information'\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, framework, compiler, hideDefaultTemplate } = options\n      const Project = require('..\/..\/create\/project').default\n      const project = new Project({\n        \/\/ \u7701\u7565\u82e5\u5e72\u53c2\u6570...\n      })\n\n      project.create()\n    }\n  })\n}\n<\/code><\/pre>\n<p><code>fn<\/code> \u51fd\u6570\uff0c\u5176\u4e2d <code>options<\/code> \u53c2\u6570\u662f <code>init<\/code> \u547d\u4ee4\u884c\u4e2d\u7684\u6240\u6709\u53c2\u6570\u3002<br \/>\u4e3b\u8981\u505a\u4e86\u5982\u4e0b\u51e0\u4ef6\u4e8b\uff1a<\/p>\n<ul>\n<li>\u8bfb\u53d6\u7ec4\u5408\u5404\u79cd\u53c2\u6570\uff0c\u521d\u59cb\u5316 <code>project<\/code> \u5bf9\u8c61\uff0c\u5e76\u8c03\u7528 <code>create<\/code> \u65b9\u6cd5\u3002<\/li>\n<\/ul>\n<p>\u6211\u4eec\u91cd\u70b9\u6765\u770b <code>packages\/taro-cli\/src\/create\/project.ts<\/code> \u7684 <code>Project<\/code> \u7c7b\u7684\u5b9e\u73b0\uff0c\u548c <code>create<\/code> \u65b9\u6cd5\u3002<\/p>\n<h2>4. new Project \u6784\u9020\u51fd\u6570<\/h2>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nexport default class Project extends Creator {\n  public rootPath: string\n  public conf: IProjectConfOptions\n\n  constructor (options: IProjectConfOptions) {\n    super(options.sourceRoot)\n    const unSupportedVer = semver.lt(process.version, 'v18.0.0')\n    if (unSupportedVer) {\n      throw new Error('Node.js \u7248\u672c\u8fc7\u4f4e\uff0c\u63a8\u8350\u5347\u7ea7 Node.js \u81f3 v18.0.0+')\n    }\n    this.rootPath = this._rootPath\n\n    this.conf = Object.assign(\n      {\n        projectName: '',\n        projectDir: '',\n        template: '',\n        description: '',\n        npm: ''\n      },\n      options\n    )\n  }\n}<\/code><\/pre>\n<p><code>Project<\/code> \u7ee7\u627f\u4e86 <code>Creator<\/code> \u7c7b\u3002<\/p>\n<p>\u6784\u9020\u51fd\u6570\u4e2d\uff0c\u4f7f\u7528 <code>semver.lt<\/code> \u5224\u65ad\u5f53\u524d <code>node<\/code> \u7248\u672c\u662f\u5426\u4f4e\u4e8e <code>v18.0.0<\/code>\uff0c\u5982\u679c\u4f4e\u4e8e\u5219\u62a5\u9519\u3002<br \/><a href=\"https:\/\/link.segmentfault.com\/?enc=A603Vt1IqA%2BF1QGC%2FYCgQg%3D%3D.nkICa%2Fjhle5aq66vlBbberFM8kKZigxjS64jpBZ2ebAG0X%2BkbPe008nxfIhv06zk\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">semver<\/a> \u662f\u4e00\u4e2a\u7248\u672c\u53f7\u6bd4\u8f83\u5e93\uff0c\u53ef\u4ee5\u7528\u6765\u5224\u65ad <code>node<\/code> \u7248\u672c\u662f\u5426\u7b26\u5408\u8981\u6c42\u3002<\/p>\n<p>\u5176\u6b21\u5c31\u662f\u521d\u59cb\u5316 <code>this.rootPath<\/code> \u548c <code>this.conf<\/code>\u3002<\/p>\n<p>\u6211\u4eec\u7ee7\u7eed\u6765\u770b <code>Creator<\/code> \u7c7b\uff0c\u6784\u9020\u51fd\u6570\u4e2d\u8c03\u7528\u4e86 <code>init<\/code> \u65b9\u6cd5\u3002<\/p>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/creator.ts\nexport default class Creator {\n  protected _rootPath: string\n  public rootPath: string\n\n  constructor (sourceRoot?: string) {\n    this.rootPath = this.sourceRoot(sourceRoot || path.join(getRootPath()))\n    this.init()\n  }\n}<\/code><\/pre>\n<p>\u6240\u4ee5\u7ee7\u7eed\u6765\u770b <code>init<\/code> \u65b9\u6cd5\u3002<\/p>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\ninit () {\n    clearConsole()\n    console.log(chalk.green('Taro \u5373\u5c06\u521b\u5efa\u4e00\u4e2a\u65b0\u9879\u76ee!'))\n    console.log(`Need help? Go and open issue: ${chalk.blueBright('https:\/\/tls.jd.com\/taro-issue-helper')}`)\n    console.log()\n}<\/code><\/pre>\n<p>\u8c03\u8bd5\u622a\u56fe\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025878\" alt=\"\u8c03\u8bd5\u622a\u56fe\" title=\"\u8c03\u8bd5\u622a\u56fe\" loading=\"lazy\"><\/p>\n<p>\u8f93\u51fa\u5c31\u662f\u8fd9\u4e2a\u56fe\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025879\" alt=\"taro-init-0.png\" title=\"taro-init-0.png\" loading=\"lazy\"><\/p>\n<p>\u5176\u4e2d<code>\ud83d\udc7d Taro v4.0.0<\/code> \u8f93\u51fa\u7684\u662f <code>tarojs-cli\/package.json<\/code> \u7684\u7248\u672c\uff0c<a href=\"https:\/\/link.segmentfault.com\/?enc=uPQxzZ7zmfkrST7N93TrYw%3D%3D.ORILYvmPxh%2FytoVYK5GPYvmx9BEJY%2FNja9HMpujd1K1tVKmqs1JAB%2F8FW53DNLD3qc3C7GN670fLwJsU4dtiMw%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u7b2c\u4e00\u7bc7\u6587\u7ae0 4. taro-cli\/src\/utils\/index.ts<\/a> \u4e2d\u6709\u8be6\u7ec6\u8bb2\u8ff0\uff0c\u8fd9\u91cc\u5c31\u4e0d\u518d\u8d58\u8ff0\u4e86\u3002<\/p>\n<p>\u8f93\u51fa<code>\u83b7\u53d6 taro \u5168\u5c40\u914d\u7f6e\u6210\u529f<\/code>\u662f\u6307\u83b7\u53d6 <code>~\/.taro-global-config\/index.json<\/code> \u6587\u4ef6\u7684\u63d2\u4ef6\u96c6 <code>presets<\/code> \u548c\u63d2\u4ef6 <code>plugins<\/code>\u3002<a href=\"https:\/\/link.segmentfault.com\/?enc=GxlNRcbe5WmvpItES%2Bl4kQ%3D%3D.nrRXs6HnYw6zEB7ybsUuZSkbuNtv%2BCFQ8lTzmZW8y5dUCWvny5DFlHmhEX3ufHpeqmFfYDNGQttIodTPxE7pQA%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u7b2c\u4e00\u7bc7\u6587\u7ae0 6.2.2 config.initGlobalConfig \u521d\u59cb\u5316\u5168\u5c40\u914d\u7f6e<\/a>\u4e2d\u6709\u8be6\u7ec6\u8bb2\u8ff0\uff0c<code>spinner.succeed('\u83b7\u53d6 taro \u5168\u5c40\u914d\u7f6e\u6210\u529f')<\/code> \u8fd9\u91cc\u5c31\u4e0d\u518d\u8d58\u8ff0\u4e86\u3002<\/p>\n<p>\u770b\u5b8c\u4e86 <code>Project<\/code> \u6784\u9020\u51fd\u6570\uff0c\u6211\u4eec\u6765\u770b <code>Project<\/code> \u7c7b\u7684 <code>create<\/code> \u65b9\u6cd5\u3002<\/p>\n<h3>4.1 project.create \u521b\u5efa\u9879\u76ee<\/h3>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nasync create () {\n    try {\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        this.write()\n    } catch (error) {\n        console.log(chalk.red('\u521b\u5efa\u9879\u76ee\u5931\u8d25: ', error))\n    }\n}<\/code><\/pre>\n<p><code>create<\/code> \u51fd\u6570\u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\uff1a<\/p>\n<ul>\n<li>\u8c03\u7528 <code>ask<\/code> \u8be2\u95ee\u7528\u6237\u8f93\u5165\u9879\u76ee\u540d\u79f0\u3001\u63cf\u8ff0\u3001CSS\u9884\u5904\u7406\u5668\u3001\u5305\u7ba1\u7406\u5de5\u5177\u7b49\u3002<\/li>\n<li>\u628a\u7528\u6237\u53cd\u9988\u7684\u7ed3\u679c\u548c\u4e4b\u524d\u7684\u914d\u7f6e\u5408\u5e76\u8d77\u6765\uff0c\u5f97\u5230 <code>this.conf<\/code>\u3002<\/li>\n<li>\u8c03\u7528 <code>write<\/code> \u65b9\u6cd5\uff0c\u5199\u5165\u6587\u4ef6\uff0c\u521d\u59cb\u5316\u6a21\u677f\u9879\u76ee\u3002<\/li>\n<\/ul>\n<p>\u8c03\u8bd5\u622a\u56fe\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025880\" alt=\"taro-init-debugger-create.png\" title=\"taro-init-debugger-create.png\" loading=\"lazy\"><\/p>\n<p><code>this.conf<\/code> \u53c2\u6570\u7ed3\u679c\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"ts\">const conf = {\n  projectName: &quot;taro-init-test&quot;,\n  projectDir: &quot;\/Users\/ruochuan\/git-source\/github\/taro&quot;,\n  template: &quot;default&quot;,\n  description: &quot;taro&quot;,\n  npm: &quot;Yarn&quot;,\n  templateSource: &quot;direct:https:\/\/gitee.com\/o2team\/taro-project-templates.git#v4.0&quot;,\n  clone: false,\n  typescript: true,\n  framework: &quot;React&quot;,\n  compiler: &quot;Webpack5&quot;,\n  hideDefaultTemplate: undefined,\n  css: &quot;Sass&quot;,\n  date: &quot;2024-7-12&quot;,\n}<\/code><\/pre>\n<p>\u6211\u4eec\u6765\u770b <code>ask<\/code> \u65b9\u6cd5\u3002<\/p>\n<h2>5. ask \u8be2\u95ee\u7528\u6237\u8f93\u5165\u9879\u76ee\u540d\u79f0\u3001\u63cf\u8ff0\u7b49<\/h2>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nasync ask () {\n    let prompts: Record&lt;string, unknown&gt;[] = []\n    const conf = this.conf\n\n    this.askProjectName(conf, prompts)\n    this.askDescription(conf, prompts)\n    this.askFramework(conf, prompts)\n    this.askTypescript(conf, prompts)\n    this.askCSS(conf, prompts)\n    this.askCompiler(conf, prompts)\n    this.askNpm(conf, prompts)\n    await this.askTemplateSource(conf, prompts)\n\n    const answers = await inquirer.prompt&lt;IProjectConf&gt;(prompts)\n\n    prompts = []\n    const templates = await this.fetchTemplates(answers)\n    await this.askTemplate(conf, prompts, templates)\n    const templateChoiceAnswer = await inquirer.prompt&lt;IProjectConf&gt;(prompts)\n\n    return {\n      ...answers,\n      ...templateChoiceAnswer\n    }\n  }<\/code><\/pre>\n<p>\u7b80\u5355\u6765\u8bf4 <code>ask<\/code> \u65b9\u6cd5\u5c31\u662f\u4e00\u7cfb\u5217\u7684 <code>inquirer<\/code> \u4ea4\u4e92\u3002<\/p>\n<blockquote><p><a href=\"https:\/\/link.segmentfault.com\/?enc=fyTXQIlJkV3wOgO8PiTErQ%3D%3D.oZJ7CGLb6atKkX1iqbcBYV9j85QHotNb0GajXG3J%2FfNGmqCeJ4w51aG0rUGvw5wC\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><code>inquirer<\/code><\/a> \u662f\u4e00\u4e2a\u547d\u4ee4\u884c\u4ea4\u4e92\u5e93\uff0c\u53ef\u4ee5\u7528\u6765\u521b\u5efa\u547d\u4ee4\u884c\u7a0b\u5e8f\u3002<\/p><\/blockquote>\n<p>\u5982\u679c\u53c2\u6570\u4e2d\u6ca1\u6307\u5b9a\u76f8\u5e94\u53c2\u6570\uff0c\u90a3\u4e48\u5c31\u8be2\u95ee\uff1a<\/p>\n<ul>\n<li>\u9879\u76ee\u540d\u79f0<\/li>\n<li>\u9879\u76ee\u4ecb\u7ecd<\/li>\n<li>\u9009\u62e9\u6846\u67b6\uff08<code>React\u3001PReact\u3001Vue3\u3001Solid<\/code>\uff09<\/li>\n<li>\u662f\u5426\u542f\u7528TS<\/li>\n<li>CSS\u9884\u5904\u7406\u5668\uff08<code>Sass\u3001less\u3001Stylus\u3001\u65e0\u7b49<\/code>\uff09<\/li>\n<li>\u7f16\u8bd1\u5de5\u5177\uff08<code>webpack\u3001vite<\/code>\uff09<\/li>\n<li>\u5305\u7ba1\u7406\u5de5\u5177\uff08<code>npm\u3001yarn\u3001pnpm<\/code>\uff09<\/li>\n<li>\u9009\u62e9\u6a21\u677f\u6e90\uff08<code>gitee\u6700\u5feb\u3001github\u6700\u65b0\u3001CLI \u5185\u7f6e\u6a21\u677f\u7b49<\/code>\uff09<\/li>\n<li>\u9009\u62e9\u6a21\u677f\uff08<code>\u9ed8\u8ba4\u6a21\u677f\u7b49<\/code>\uff09<\/li>\n<li>\u7b49\u7b49<\/li>\n<\/ul>\n<p>\u5982\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025881\" alt=\"\u521d\u59cb\u5316\" title=\"\u521d\u59cb\u5316\" loading=\"lazy\"><\/p>\n<p>\u6211\u4eec\u91cd\u70b9\u8bb2\u8ff0\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u6cd5<\/p>\n<ul>\n<li><code>askProjectName<\/code> \u8be2\u95ee\u9879\u76ee\u540d\u79f0<\/li>\n<li><code>askTemplateSource<\/code> \u8be2\u95ee\u6a21\u677f\u6e90<\/li>\n<li><code>fetchTemplates<\/code> \u83b7\u53d6\u6a21\u677f\u5217\u8868<\/li>\n<li><code>askTemplate<\/code> \u8be2\u95ee\u6a21\u677f<\/li>\n<\/ul>\n<p>\u6211\u4eec\u6765\u770b\u7b2c\u4e00\u4e2a <code>askProjectName<\/code> \u65b9\u6cd5\u3002<\/p>\n<h3>5.1 askProjectName \u8be2\u95ee\u9879\u76ee\u540d\u79f0<\/h3>\n<pre><code class=\"ts\">askProjectName: AskMethods = function (conf, prompts) {\n    if ((typeof conf.projectName) !== 'string') {\n      prompts.push({\n        type: 'input',\n        name: 'projectName',\n        message: '\u8bf7\u8f93\u5165\u9879\u76ee\u540d\u79f0\uff01',\n        validate (input) {\n          if (!input) {\n            return '\u9879\u76ee\u540d\u4e0d\u80fd\u4e3a\u7a7a\uff01'\n          }\n          if (fs.existsSync(input)) {\n            return '\u5f53\u524d\u76ee\u5f55\u5df2\u7ecf\u5b58\u5728\u540c\u540d\u9879\u76ee\uff0c\u8bf7\u6362\u4e00\u4e2a\u9879\u76ee\u540d\uff01'\n          }\n          return true\n        }\n      })\n    } else if (fs.existsSync(conf.projectName!)) {\n      prompts.push({\n        type: 'input',\n        name: 'projectName',\n        message: '\u5f53\u524d\u76ee\u5f55\u5df2\u7ecf\u5b58\u5728\u540c\u540d\u9879\u76ee\uff0c\u8bf7\u6362\u4e00\u4e2a\u9879\u76ee\u540d\uff01',\n        validate (input) {\n          if (!input) {\n            return '\u9879\u76ee\u540d\u4e0d\u80fd\u4e3a\u7a7a\uff01'\n          }\n          if (fs.existsSync(input)) {\n            return '\u9879\u76ee\u540d\u4f9d\u7136\u91cd\u590d\uff01'\n          }\n          return true\n        }\n      })\n    }\n  }<\/code><\/pre>\n<p>\u540e\u9762\u7684 <code>askDescription<\/code>\u3001<code>askFramework<\/code>\u3001<code>askFramework<\/code>\u3001<code>askTypescript<\/code>\u3001<code>askCSS<\/code>\u3001<code>askCompiler<\/code>\u3001<code>askNpm<\/code>\uff0c\u90fd\u662f\u7c7b\u4f3c\u65b9\u6cd5\uff0c\u5c31\u4e0d\u518d\u8d58\u8ff0\u4e86\u3002<\/p>\n<h3>5.2 askTemplateSource \u8be2\u95ee\u6a21\u677f\u6e90<\/h3>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nimport {\n  chalk,\n  DEFAULT_TEMPLATE_SRC,\n  DEFAULT_TEMPLATE_SRC_GITEE,\n  fs,\n  getUserHomeDir,\n  SOURCE_DIR,\n  TARO_BASE_CONFIG,\n  TARO_CONFIG_FOLDER\n} from '@tarojs\/helper'<\/code><\/pre>\n<p>\u5bfc\u51fa\u7684\u5c31\u662f\u8fd9\u4e9b\u5e38\u91cf\u3002<\/p>\n<pre><code class=\"ts\">\/\/ packages\/taro-helper\/src\/constants.ts\nexport const DEFAULT_TEMPLATE_SRC = 'github:NervJS\/taro-project-templates#v4.0'\nexport const DEFAULT_TEMPLATE_SRC_GITEE = 'direct:https:\/\/gitee.com\/o2team\/taro-project-templates.git#v4.0'\nexport const TARO_CONFIG_FOLDER = '.taro3.7'\nexport const TARO_BASE_CONFIG = 'index.json'\nexport const TARO_GLOBAL_CONFIG_DIR = '.taro-global-config'\nexport const TARO_GLOBAL_CONFIG_FILE = 'index.json'<\/code><\/pre>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\naskTemplateSource: AskMethods = async function (conf, prompts) {\n    if (conf.template === 'default' || conf.templateSource) return\n\n    const homedir = getUserHomeDir()\n    const taroConfigPath = path.join(homedir, TARO_CONFIG_FOLDER)\n    const taroConfig = path.join(taroConfigPath, TARO_BASE_CONFIG)\n\n    let localTemplateSource: string\n\n    \/\/ \u68c0\u67e5\u672c\u5730\u914d\u7f6e\n    if (fs.existsSync(taroConfig)) {\n      \/\/ \u5b58\u5728\u5219\u628a\u6a21\u677f\u6e90\u8bfb\u51fa\u6765\n      const config = await fs.readJSON(taroConfig)\n      localTemplateSource = config?.templateSource\n    } else {\n      \/\/ \u4e0d\u5b58\u5728\u5219\u521b\u5efa\u914d\u7f6e\n      await fs.createFile(taroConfig)\n      await fs.writeJSON(taroConfig, { templateSource: DEFAULT_TEMPLATE_SRC })\n      localTemplateSource = DEFAULT_TEMPLATE_SRC\n    }\n    const choices = [\n        \/\/ \u7701\u7565\uff0c\u62c6\u5206\u653e\u5230\u4e0b\u65b9\n    ];\n    if (localTemplateSource &amp;&amp; localTemplateSource !== DEFAULT_TEMPLATE_SRC &amp;&amp; localTemplateSource !== DEFAULT_TEMPLATE_SRC_GITEE) {\n      choices.unshift({\n        name: `\u672c\u5730\u6a21\u677f\u6e90\uff1a${localTemplateSource}`,\n        value: localTemplateSource\n      })\n    }\n    \/\/ \u7701\u7565\u90e8\u5206\u4ee3\u7801\uff0c\u62c6\u5206\u653e\u5230\u4e0b\u65b9\n  }<\/code><\/pre>\n<p>\u7b80\u5355\u6765\u8bf4\uff1a<\/p>\n<ul>\n<li>\u5c31\u662f\u5224\u65ad\u672c\u5730\u662f\u5426\u5b58\u5728\u914d\u7f6e <code>~\/.taro3.7\/index.json<\/code>\uff0c\u5982\u679c\u5b58\u5728\u5219\u8bfb\u53d6\u6a21\u677f\u6e90\uff0c\u5982\u679c\u4e0d\u5b58\u5728\u5219\u521b\u5efa\u914d\u7f6e\u3002\u521b\u5efa\u914d\u7f6e\u65f6\uff0c\u9ed8\u8ba4\u6a21\u677f\u6e90\u4e3a <a href=\"https:\/\/link.segmentfault.com\/?enc=pG7sDuarxg7VEQFutFkLmQ%3D%3D.7IqLwIiCxarLvuC7%2Bf2E732leJsXM3m%2BRMsUdBrjbgOnAI7EutCXmPiDiDYJzjUOSimx2tkFZ1pQPg9LEo0%2Biw%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">github:NervJS\/taro-project-templates#v4.0<\/a>\u3002<\/li>\n<li>\u53e6\u5916\uff0c\u5982\u679c\u672c\u5730\u6a21\u677f\u6e90\u4e0d\u662f\u9ed8\u8ba4\u6a21\u677f\u6e90\uff0c\u90a3\u4e48\u5c31\u628a\u672c\u5730\u6a21\u677f\u6e90\u4f5c\u4e3a\u9009\u9879\uff0c\u653e\u5728\u6700\u524d\u9762\uff0c\u4f9b\u7528\u6237\u9009\u62e9\u3002<\/li>\n<\/ul>\n<p>\u5176\u4e2d\uff0c<code>~\/.taro3.7\/index.json<\/code> \u5185\u5bb9\u683c\u5f0f\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"json\">\/\/ ~\/.taro3.7\/index.json\n{\n    &quot;remoteSchemaUrl&quot;: &quot;https:\/\/raw.githubusercontent.com\/NervJS\/taro-doctor\/main\/assets\/config_schema.json&quot;,\n    &quot;useRemoteSchema&quot;: true\n}<\/code><\/pre>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nconst choices = [\n  {\n    name: 'Gitee\uff08\u6700\u5feb\uff09',\n    value: DEFAULT_TEMPLATE_SRC_GITEE\n  },\n  {\n    name: 'Github\uff08\u6700\u65b0\uff09',\n    value: DEFAULT_TEMPLATE_SRC\n  },\n  {\n    name: 'CLI \u5185\u7f6e\u9ed8\u8ba4\u6a21\u677f',\n    value: 'default-template'\n  },\n  {\n    name: '\u81ea\u5b9a\u4e49',\n    value: 'self-input'\n  },\n  {\n    name: '\u793e\u533a\u4f18\u8d28\u6a21\u677f\u6e90',\n    value: 'open-source'\n  }\n]\n\n\/\/ \u7701\u7565\u90e8\u5206\u4ee3\u7801\u672c\u5730\u6a21\u677f\u6e90\u7684\u5224\u65ad\uff0c\u5728\u4e0a\u65b9\u5df2\u7ecf\u5c55\u793a\u3002\n\nprompts.push({\n  type: 'list',\n  name: 'templateSource',\n  message: '\u8bf7\u9009\u62e9\u6a21\u677f\u6e90',\n  choices\n}, {\n  type: 'input',\n  name: 'templateSource',\n  message: '\u8bf7\u8f93\u5165\u6a21\u677f\u6e90\uff01',\n  askAnswered: true,\n  when (answers) {\n    return answers.templateSource === 'self-input'\n  }\n}, {\n  type: 'list',\n  name: 'templateSource',\n  message: '\u8bf7\u9009\u62e9\u793e\u533a\u6a21\u677f\u6e90',\n  async choices (answers) {\n    const choices = await getOpenSourceTemplates(answers.framework)\n    return choices\n  },\n  askAnswered: true,\n  when (answers) {\n    return answers.templateSource === 'open-source'\n  }\n})<\/code><\/pre>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nasync ask () {\n    \/\/ \u7701\u7565\u4e0a\u534a\u90e8\u5206\u4ee3\u7801\n    const answers = await inquirer.prompt&lt;IProjectConf&gt;(prompts)\n\n    prompts = []\n    const templates = await this.fetchTemplates(answers)\n    await this.askTemplate(conf, prompts, templates)\n    const templateChoiceAnswer = await inquirer.prompt&lt;IProjectConf&gt;(prompts)\n\n    return {\n      ...answers,\n      ...templateChoiceAnswer\n    }\n}<\/code><\/pre>\n<p>\u6211\u4eec\u7ee7\u7eed\u6765\u770b <code>fetchTemplates<\/code> \u51fd\u6570\uff1a<\/p>\n<h3>5.3 fetchTemplates \u83b7\u53d6\u6a21\u677f\u5217\u8868<\/h3>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nasync fetchTemplates (answers: IProjectConf): Promise&lt;ITemplates[]&gt; {\n  const { templateSource, framework, compiler } = answers\n  this.conf.framework = this.conf.framework || framework || ''\n  this.conf.templateSource = this.conf.templateSource || templateSource\n\n  \/\/ \u4f7f\u7528\u9ed8\u8ba4\u6a21\u7248\n  if (answers.templateSource === 'default-template') {\n    this.conf.template = 'default'\n    answers.templateSource = DEFAULT_TEMPLATE_SRC_GITEE\n  }\n  if (this.conf.template === 'default' || answers.templateSource === NONE_AVAILABLE_TEMPLATE) return Promise.resolve([])\n\n  \/\/ \u4ece\u6a21\u677f\u6e90\u4e0b\u8f7d\u6a21\u677f\n  const isClone = \/gitee\/.test(this.conf.templateSource) || this.conf.clone\n  const templateChoices = await fetchTemplate(this.conf.templateSource, this.templatePath(''), isClone)\n\n  const filterFramework = (_framework) =&gt; {\n    const current = this.conf.framework?.toLowerCase()\n\n    if (typeof _framework === 'string' &amp;&amp; _framework) {\n      return current === _framework.toLowerCase()\n    } else if (isArray(_framework)) {\n      return _framework?.map(name =&gt; name.toLowerCase()).includes(current)\n    } else {\n      return true\n    }\n  }\n\n  const filterCompiler = (_compiler) =&gt; {\n    if (_compiler &amp;&amp; isArray(_compiler)) {\n      return _compiler?.includes(compiler)\n    }\n    return true\n  }\n\n  \/\/ \u6839\u636e\u7528\u6237\u9009\u62e9\u7684\u6846\u67b6\u7b5b\u9009\u6a21\u677f\n  const newTemplateChoices: ITemplates[] = templateChoices\n    .filter(templateChoice =&gt; {\n      const { platforms, compiler } = templateChoice\n      return filterFramework(platforms) &amp;&amp; filterCompiler(compiler)\n    })\n\n  return newTemplateChoices\n}<\/code><\/pre>\n<p>\u6211\u4eec\u7ee7\u7eed\u6765\u770b <code>fetchTemplate<\/code> \u51fd\u6570\uff0c\u5b83\u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\u60c5\uff1a<\/p>\n<h4>5.3.1 fetchTemplate \u83b7\u53d6\u6a21\u677f<\/h4>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/fetchTemplate.ts\nimport * as path from 'node:path'\n\nimport { chalk, fs } from '@tarojs\/helper'\nimport * as AdmZip from 'adm-zip'\nimport axios from 'axios'\nimport * as download from 'download-git-repo'\nimport * as ora from 'ora'\n\nimport { getTemplateSourceType, readDirWithFileTypes } from '..\/util'\nimport { TEMPLATE_CREATOR } from '.\/constants'\n\nexport interface ITemplates {\n  name: string\n  value: string\n  platforms?: string | string[]\n  desc?: string\n  compiler?: string[]\n}\n\nconst TEMP_DOWNLOAD_FOLDER = 'taro-temp'\n\nexport default function fetchTemplate (templateSource: string, templateRootPath: string, clone?: boolean): Promise&lt;ITemplates[]&gt; {\n  const type = getTemplateSourceType(templateSource)\n  const tempPath = path.join(templateRootPath, TEMP_DOWNLOAD_FOLDER)\n  let name: string\n  \/\/ eslint-disable-next-line no-async-promise-executor\n  return new Promise&lt;void&gt;(async (resolve) =&gt; {\n    \/\/ \u4e0b\u8f7d\u6587\u4ef6\u7684\u7f13\u5b58\u76ee\u5f55\n    if (fs.existsSync(tempPath)) await fs.remove(tempPath)\n    await fs.mkdir(tempPath)\n\n    const spinner = ora(`\u6b63\u5728\u4ece ${templateSource} \u62c9\u53d6\u8fdc\u7a0b\u6a21\u677f...`).start()\n\n    if (type === 'git') {\n      name = path.basename(templateSource)\n      download(templateSource, path.join(tempPath, name), { clone }, async error =&gt; {\n        if (error) {\n          console.log(error)\n          spinner.color = 'red'\n          spinner.fail(chalk.red('\u62c9\u53d6\u8fdc\u7a0b\u6a21\u677f\u4ed3\u5e93\u5931\u8d25\uff01'))\n          await fs.remove(tempPath)\n          return resolve()\n        }\n        spinner.color = 'green'\n        spinner.succeed(`${chalk.grey('\u62c9\u53d6\u8fdc\u7a0b\u6a21\u677f\u4ed3\u5e93\u6210\u529f\uff01')}`)\n        resolve()\n      })\n    } else if (type === 'url') {\n      \/\/ \u7701\u7565\u8fd9\u90e8\u5206\u4ee3\u7801...\n      \/\/ \u5982\u679c\u662f `url` \u5219\u7528 `axios` \u4e0b\u8f7d\n    }\n  }).then(async () =&gt; {\n    \/\/ \u62c6\u89e3\u5230\u4e0b\u65b9\u8bb2\u8ff0\n  })\n}\n<\/code><\/pre>\n<p>\u8fd9\u4e2a\u65b9\u6cd5\u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\u60c5\uff1a<\/p>\n<ul>\n<li>\u5224\u65ad\u6a21\u677f\u6765\u6e90\u5730\u5740\u662f <code>git<\/code> \u7c7b\u578b\uff0c\u90a3\u4e48\u4f7f\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=4jmG3jfWx9YASMj2iHUtJA%3D%3D.gGpZelhmzpyJzs%2FTMGSxrqNxQlGNhrasR3buveHXXF5I0l1a%2BCZaz1Z39C73QAW2\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">download-git-repo<\/a> \u4e0b\u8f7d\u8fdc\u7a0b\u4ed3\u5e93\u5230\u672c\u5730\u3002<\/li>\n<li>\u5224\u65ad\u6a21\u677f\u6765\u6e90\u5730\u5740\u662f <code>git<\/code> \u7c7b\u578b\uff0c\u90a3\u4e48\u5219\u7528 <code>axios<\/code> \u4e0b\u8f7d\u3002<\/li>\n<\/ul>\n<p><strong>then \u90e8\u5206<\/strong><\/p>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/fetchTemplate.ts\n\/\/ then \u90e8\u5206\nconst templateFolder = name ? path.join(tempPath, name) : ''\n\n\/\/ \u4e0b\u8f7d\u5931\u8d25\uff0c\u53ea\u663e\u793a\u9ed8\u8ba4\u6a21\u677f\nif (!fs.existsSync(templateFolder)) return Promise.resolve([])\n\nconst isTemplateGroup = !(\n  fs.existsSync(path.join(templateFolder, 'package.json')) ||\n  fs.existsSync(path.join(templateFolder, 'package.json.tmpl'))\n)\n\nif (isTemplateGroup) {\n  \/\/ \u6a21\u677f\u7ec4\n  const files = readDirWithFileTypes(templateFolder)\n    .filter(file =&gt; !file.name.startsWith('.') &amp;&amp; file.isDirectory &amp;&amp; file.name !== '__MACOSX')\n    .map(file =&gt; file.name)\n  await Promise.all(\n    files.map(file =&gt; {\n      const src = path.join(templateFolder, file)\n      const dest = path.join(templateRootPath, file)\n      return fs.move(src, dest, { overwrite: true })\n    })\n  )\n  await fs.remove(tempPath)\n\n  const res: ITemplates[] = files.map(name =&gt; {\n    const creatorFile = path.join(templateRootPath, name, TEMPLATE_CREATOR)\n\n    if (!fs.existsSync(creatorFile)) return { name, value: name }\n    const { name: displayName, platforms = '', desc = '', compiler } = require(creatorFile)\n\n    return {\n      name: displayName || name,\n      value: name,\n      platforms,\n      compiler,\n      desc\n    }\n  })\n  return Promise.resolve(res)\n} else {\n  \/\/ \u5355\u6a21\u677f\n  \/\/ \u7701\u7565\u8fd9\u90e8\u5206\u4ee3\u7801\uff0c\u5355\u6a21\u7248\u548c\u6a21\u677f\u7ec4\u903b\u8f91\u57fa\u672c\u4e00\u81f4\uff0c\u53ea\u662f\u4e00\u4e2a\u662f\u591a\u4e2a\u4e00\u4e2a\u662f\u5355\u4e2a\n}<\/code><\/pre>\n<p>\u8fd9\u6bb5\u4ee3\u7801\u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\u60c5\uff1a<\/p>\n<ul>\n<li>\u5224\u65ad\u662f\u5426\u662f\u6a21\u677f\u7ec4\uff0c\u5982\u679c\u662f\u6a21\u677f\u7ec4\uff0c\u5219\u904d\u5386 <code>packages\/taro-cli\/templates\/taro-temp<\/code> \u6587\u4ef6\u5939\u4e0b\u7684\u6240\u6709\u6587\u4ef6\u5939\uff0c\u5e76\u79fb\u52a8\u5230 <code>packages\/taro-cli<\/code> \u76ee\u5f55\u4e0b\u7684 <code>templates<\/code> \u6587\u4ef6\u5939\u3002<\/li>\n<li>\u4e0d\u662f\u6a21\u677f\u7ec4\uff0c\u5219\u76f4\u63a5\u79fb\u52a8\u5230 <code>packages\/taro-cli\/templates\/taro-temp<\/code> \u76ee\u5f55\u4e0b\u5355\u4e2a\u6a21\u677f\u5230 <code>templates<\/code> \u6587\u4ef6\u5939\u3002<\/li>\n<\/ul>\n<p>\u7528\u4e00\u5f20\u56fe\u6765\u5c55\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025882\" alt=\"\u5408\u5e76\" title=\"\u5408\u5e76\" loading=\"lazy\"><\/p>\n<h3>5.4 askTemplate \u8be2\u95ee\u7528\u6237\u9009\u62e9\u6a21\u677f<\/h3>\n<pre><code class=\"ts\">askTemplate: AskMethods = function (conf, prompts, list = []) {\n    const choices = list.map(item =&gt; ({\n      name: item.desc ? `${item.name}\uff08${item.desc}\uff09` : item.name,\n      value: item.value || item.name\n    }))\n\n    if (!conf.hideDefaultTemplate) {\n      choices.unshift({\n        name: '\u9ed8\u8ba4\u6a21\u677f',\n        value: 'default'\n      })\n    }\n\n    if ((typeof conf.template as 'string' | undefined) !== 'string') {\n      prompts.push({\n        type: 'list',\n        name: 'template',\n        message: '\u8bf7\u9009\u62e9\u6a21\u677f',\n        choices\n      })\n    }\n  }<\/code><\/pre>\n<h2>6. write \u5199\u5165\u9879\u76ee<\/h2>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nwrite (cb?: () =&gt; void) {\n    this.conf.src = SOURCE_DIR\n    const { projectName, projectDir, template, autoInstall = true, framework, npm } = this.conf as IProjectConf\n    \/\/ \u5f15\u5165\u6a21\u677f\u7f16\u5199\u8005\u7684\u81ea\u5b9a\u4e49\u903b\u8f91\n    \/\/ taro\/packages\/taro-cli\/templates\/default\n    const templatePath = this.templatePath(template)\n    \/\/ taro\/packages\/taro-cli\/templates\/default\/template_creator.js\n    const handlerPath = path.join(templatePath, TEMPLATE_CREATOR)\n    const handler = fs.existsSync(handlerPath) ? require(handlerPath).handler : {}\n    createProject({\n      projectRoot: projectDir,\n      projectName,\n      template,\n      npm,\n      framework,\n      css: this.conf.css || CSSType.None,\n      autoInstall: autoInstall,\n      templateRoot: getRootPath(),\n      version: getPkgVersion(),\n      typescript: this.conf.typescript,\n      date: this.conf.date,\n      description: this.conf.description,\n      compiler: this.conf.compiler,\n      period: PeriodType.CreateAPP,\n    }, handler).then(() =&gt; {\n      cb &amp;&amp; cb()\n    })\n}<\/code><\/pre>\n<p><code>write<\/code> \u51fd\u6570\u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\u60c5\uff1a<\/p>\n<ul>\n<li>\u83b7\u53d6\u7528\u6237\u8f93\u5165\u7684\u53c2\u6570\uff0c\u5305\u62ec\u9879\u76ee\u540d\u79f0\u3001\u9879\u76ee\u76ee\u5f55\u3001\u6a21\u677f\u540d\u79f0\u7b49\u3002<\/li>\n<li>\u5f15\u5165\u6a21\u677f\u7f16\u5199\u8005\u7684\u81ea\u5b9a\u4e49\u903b\u8f91\u3002<\/li>\n<li>\u8c03\u7528 <code>createProject<\/code> \u51fd\u6570\uff0c\u4f20\u5165\u7528\u6237\u8f93\u5165\u7684\u53c2\u6570\u548c\u6a21\u677f\u7f16\u5199\u8005\u7684\u81ea\u5b9a\u4e49\u903b\u8f91\u3002<\/li>\n<\/ul>\n<p>\u8c03\u8bd5\u622a\u56fe<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025883\" alt=\"taro-init-debugger-write.png\" title=\"taro-init-debugger-write.png\" loading=\"lazy\"><\/p>\n<h3>6.1 template\/_creator.js \u9ed8\u8ba4\u6a21\u677f\u4e2d\u521b\u5efa\u6a21\u677f\u7684\u81ea\u5b9a\u4e49\u903b\u8f91<\/h3>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/templates\/default\/template_creator.js\nconst path = require('path')\n\nfunction createWhenTs (err, params) {\n  return !!params.typescript\n}\n\nfunction normalizePath (path) {\n  return path.replace(\/\/\/\/g, '\/').replace(\/\/\/{2,}\/g, '\/')\n}\n\nconst SOURCE_ENTRY = '\/src'\nconst PAGES_ENTRY = '\/src\/pages'\n\nconst handler = {\n  '\/tsconfig.json': createWhenTs,\n  '\/types\/global.d.ts': createWhenTs,\n  '\/types\/vue.d.ts' (err, { framework, typescript }) {\n    return ['Vue3'].includes(framework) &amp;&amp; !!typescript\n  },\n  '\/src\/pages\/index\/index.jsx' (err, { pageDir = '', pageName = '', subPkg = '' }) {\n    return {\n      setPageName: normalizePath(path.join(PAGES_ENTRY, pageDir, pageName, 'index.jsx')),\n      setSubPkgName: normalizePath(path.join(SOURCE_ENTRY, subPkg, pageDir, pageName, 'index.jsx'))\n    }\n  },\n  \/\/ \u7701\u7565\u90e8\u5206\u4ee3\u7801\n  '\/_editorconfig' () {\n    return { setPageName: `\/.editorconfig` }\n  },\n  '\/_env.development' () {\n    return { setPageName: `\/.env.development` }\n  },\n  '\/_env.production' () {\n    return { setPageName: `\/.env.production` }\n  },\n  '\/_env.test' () {\n    return { setPageName: `\/.env.test` }\n  },\n  '\/_eslintrc' () {\n    return { setPageName: `\/.eslintrc` }\n  },\n  '\/_gitignore' () {\n    return { setPageName: `\/.gitignore` }\n  }\n}\n\nconst basePageFiles = [\n  '\/src\/pages\/index\/index.jsx',\n  '\/src\/pages\/index\/index.vue',\n  '\/src\/pages\/index\/index.css',\n  '\/src\/pages\/index\/index.config.js'\n]\n\nmodule.exports = {\n  handler,\n  basePageFiles\n}<\/code><\/pre>\n<p><code>template_creator.js<\/code> \u6587\u4ef6\u4e2d\u7684 <code>handler<\/code> \u5bf9\u8c61\uff0c\u5b9a\u4e49\u4e86\u6a21\u677f\u4e2d\u521b\u5efa\u7684\u6587\u4ef6\u548c\u81ea\u5b9a\u4e49\u903b\u8f91\u3002<br \/>\u6bd4\u5982\u5f53 <code>!!params.typescript<\/code> \u7684\u65f6\u5019\uff0c\u521b\u5efa <code>\/tsconfig.json<\/code>\u3001<code>types\/global.d.ts<\/code> \u6587\u4ef6\u3002<br \/>\u5f53 <code>\/['Vue3'].includes(framework) &amp;&amp; !!typescript<\/code> \u7684\u65f6\u5019\uff0c\u521b\u5efa <code>types\/vue.d.ts<\/code> \u6587\u4ef6\u3002<br \/>\u6839\u636e <code>\/\/_env.development<\/code> \u6587\u4ef6\u521b\u5efa <code>.env.development<\/code><br \/>\u7b49\u7b49<\/p>\n<blockquote><p>\u56e0\u4e3a\u5728\u4e00\u4e9b\u573a\u666f\u4e0b\uff0c<code>.<\/code> \u5f00\u5934\u6587\u4ef6\u4f1a\u51fa\u73b0\u95ee\u9898\uff0c\u6240\u4ee5\u6539\u7528 <code>_<\/code> \u5f00\u5934\u547d\u540d\u6587\u4ef6\uff0c\u521b\u5efa\u65f6\u505a\u4e00\u6b21\u66ff\u6362\u3002<\/p><\/blockquote>\n<h2>7. \u8c03\u8bd5 rust \u4ee3\u7801<\/h2>\n<p>\u6211\u4eec\u4ece <code>write<\/code> \u51fd\u6570\u8c03\u7528 <code>createProject<\/code> \u51fd\u6570\uff0c\u53ef\u4ee5\u770b\u5230 <code>createProject<\/code> \u7b49\u662f\u4ece  <code>@tarojs\/binding<\/code> \u5f15\u5165\u7684\u3002<\/p>\n<pre><code class=\"ts\">import { CompilerType, createProject, CSSType, FrameworkType, NpmType, PeriodType } from '@tarojs\/binding'<\/code><\/pre>\n<p>\u7b80\u5355\u6765\u8bf4\u5c31\u662f\uff1a\u901a\u8fc7 <a href=\"https:\/\/link.segmentfault.com\/?enc=%2F6B17kdmeH1cKicvkVL0lA%3D%3D.BaYyKyLbwWfton%2FDIRl3CETq8zMyk5HIKAwQsCy4I5uUrK%2FAPXbCL62QOi0XajfTpRM%2BkN45bGtnrLaoivFCkQ%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">napi-rs<\/a> \u628a <code>create_project<\/code> \u51fd\u6570\u66b4\u9732\u7ed9 <code>nodejs<\/code> \uff0c\u7136\u540e\u901a\u8fc7 <code>nodejs<\/code> \u8c03\u7528 <code>rust<\/code> \u7684 <code>create_project<\/code> \u51fd\u6570\u3002<\/p>\n<p>\u5173\u4e8e\u5177\u4f53\u7ec6\u8282\uff0c\u7528 <code>rust<\/code> \u6539\u9020 <code>taro init<\/code> \u8fd9\u90e8\u5206\u4ee3\u7801\u7684\u4f5c\u8005 <code>@luckyadam<\/code>\uff0c\u5199\u4e86\u4e00\u7bc7\u6587\u7ae0\u3002\u53ef\u4ee5\u53c2\u8003\u5b66\u4e60<a href=\"https:\/\/link.segmentfault.com\/?enc=G%2FNdibKVKt4Di21US2PGXg%3D%3D.pWm8BgKHqXdWhRSgaZM46TBgm%2FZL1WoDSXyf6FfokKqLoYwTOnjTGafwaN8vmwYL\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u89e3\u9501\u524d\u7aef\u65b0\u6f5c\u80fd\uff1a\u5982\u4f55\u4f7f\u7528 Rust \u9508\u5316\u524d\u7aef\u5de5\u5177\u94fe<\/a>\uff0c\u6211\u5728\u8fd9\u91cc\u5c31\u4e0d\u8d58\u8ff0\u4e86\u3002<\/p>\n<blockquote><p>\u5b89\u88c5 <code>VSCode<\/code> \u63d2\u4ef6 <a href=\"https:\/\/link.segmentfault.com\/?enc=LU5n0vCA6WGGlqRcTmTVDw%3D%3D.VDt%2F3hIw4Kmd%2FPidu1w7r1rPqUQFfnqTiwqBFFblE1Yb7CqWWoIEDDl4lAuZgvRvDKOG%2B3WwsIWqAkYaJ31%2FzYobbDWKKyvCZzTprw%2F6EW4%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">rust-analyzer<\/a> (\u65b9\u4fbf\u8df3\u8f6c\u4ee3\u7801\u5b9a\u4e49\u7b49) \u548c\u8c03\u8bd5\u4ee3\u7801\u7684\u63d2\u4ef6 <a href=\"https:\/\/link.segmentfault.com\/?enc=sE%2FHxdyoE46mO8qRw1yFYg%3D%3D.T7IXJcb%2FJsTyPrxkbFX20Y7iLBq9HZwT0Lsct%2BYh%2BOQkNziLqr761GbwUB0BXywgnxy2JWFgeg26IG6GHCtYF8ePbOzx9YzniNyBmPW3FDc7CRrRIpeSo%2BmvIzcXk8bu\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">CodeLLDB<\/a><\/p><\/blockquote>\n<p>\u66f4\u591a <code>rust<\/code> \u5b66\u4e60\uff0c\u53ef\u53c2\u8003 <a href=\"https:\/\/link.segmentfault.com\/?enc=W6v%2BhNtTAWk0h6veH%2B0q1A%3D%3D.tt72kpy5BoZSJlGknGJMwy4hTz7%2BllW6g934KRD9yH8iyi9fUSDR%2Bd6pWH1YdgOn\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">rust \u5b98\u7f51\uff1arust-lang.org<\/a><\/p>\n<p>\u6211\u4eec\u5728 <code>.vscode\/launch.json<\/code> \u4e2d\u7684\u539f\u6709\u7684 <code>debug-init<\/code> \u547d\u4ee4\u884c\u8c03\u8bd5\u914d\u7f6e\uff0c\u4fee\u6539 <code>&quot;type&quot;: &quot;lldb&quot;,<\/code> \u914d\u7f6e\u5982\u4e0b\uff1a<\/p>\n<pre><code>\/\/ .vscode\/launch.json\n{\n  &quot;version&quot;: &quot;0.2.0&quot;,\n  &quot;configurations&quot;: [\n    {\n-     &quot;type&quot;: &quot;node&quot;,\n+     &quot;type&quot;: &quot;lldb&quot;,\n      &quot;request&quot;: &quot;launch&quot;,\n      &quot;name&quot;: &quot;debug-init&quot;,\n      &quot;sourceLanguages&quot;: [&quot;rust&quot;],\n      &quot;program&quot;: &quot;node&quot;,\n      &quot;args&quot;: [&quot;${workspaceFolder}\/packages\/taro-cli\/bin\/taro&quot;, &quot;init&quot;, &quot;test_pro&quot;],\n      &quot;cwd&quot;: &quot;${workspaceFolder}&quot;,\n      &quot;preLaunchTask&quot;: &quot;build binding debug&quot;,\n      &quot;postDebugTask&quot;: &quot;remove test_pro&quot;\n    }]\n}<\/code><\/pre>\n<p>\u8fd9\u6837\u6211\u4eec\u5c31\u53ef\u4ee5\u5728 <code>crates\/native_binding\/src\/lib.rs<\/code> \u6587\u4ef6\u4e2d\u6253\u65ad\u70b9\u8c03\u8bd5\u4e86\u3002<\/p>\n<p>\u8c03\u8bd5\u622a\u56fe\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025884\" alt=\"taro-init-debugger-rust.png\" title=\"taro-init-debugger-rust.png\" loading=\"lazy\"><\/p>\n<p>\u6211\u4eec\u7ee7\u7eed\u6765\u770b <code>crates\/native_binding\/src\/lib.rs<\/code> \u6587\u4ef6\u4e2d\u7684 <code>create_project<\/code> \uff08 <code>nodejs<\/code> \u4e2d\u8c03\u7528\u5219\u662f <code>createProject<\/code> \uff09\u51fd\u6570\uff1a<\/p>\n<h2>8. rust create\/_project \u521b\u5efa\u9879\u76ee<\/h2>\n<pre><code class=\"rs\">\/\/ crates\/native_binding\/src\/lib.rs\n#[napi]\npub async fn create_project(\n  conf: Project,\n  handlers: HashMap&lt;String, ThreadsafeFunction&lt;CreateOptions&gt;&gt;,\n) -&gt; Result&lt;()&gt; {\n  let project: Project = Project::new(\n    conf.project_root,\n    conf.project_name,\n    conf.npm,\n    conf.description,\n    conf.typescript,\n    conf.template,\n    conf.css,\n    conf.framework,\n    conf.auto_install,\n    conf.template_root,\n    conf.version,\n    conf.date,\n    conf.compiler,\n    conf.period,\n  );\n  let mut thread_safe_functions = HashMap::new();\n  for (key, callback) in handlers {\n    thread_safe_functions.insert(key, callback);\n  }\n  if let Err(e) = project.create(thread_safe_functions).await {\n    println!(&quot;\u521b\u5efa\u9879\u76ee\u9519\u8bef\uff0c\u539f\u56e0\u5982\u4e0b\uff1a&quot;);\n    println!(&quot;{:?}&quot;, e);\n    return Err(napi::Error::from_reason(format!(&quot;{:?}&quot;, e)));\n  }\n  Ok(())\n}<\/code><\/pre>\n<p>\u6211\u4eec\u91cd\u70b9\u6765\u770b\u4e00\u4e0b <code>project.create<\/code> \u51fd\u6570\uff1a<\/p>\n<h3>8.1 create \u521b\u5efa\u6587\u4ef6<\/h3>\n<pre><code class=\"rs\">\/\/ crates\/taro_init\/src\/project.rs\npub async fn create(\n    &amp;self,\n    js_handlers: HashMap&lt;String, ThreadsafeFunction&lt;CreateOptions&gt;&gt;,\n  ) -&gt; anyhow::Result&lt;()&gt; {\n    \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801\n    let all_files = get_all_files_in_folder(template_path.clone(), filter, None)?;\n    let mut create_options = CreateOptions {\n      \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801\n    };\n    let all_files = all_files.iter().filter_map(|f| f.to_str()).collect::&lt;Vec&lt;_&gt;&gt;();\n    println!();\n    println!(\n      &quot;{} {}&quot;,\n      style(&quot;\u2714&quot;).green(),\n      format!(\n        &quot;{}{}&quot;,\n        style(&quot;\u521b\u5efa\u9879\u76ee: &quot;).color256(238),\n        style(self.project_name.as_str()).color256(238).bold()\n      )\n    );\n    creator\n      .create_files(\n        all_files.as_slice(),\n        template_path.as_str(),\n        &amp;mut create_options,\n        &amp;js_handlers,\n      )\n      .await?;\n    \/\/ \u5f53\u9009\u62e9 rn \u6a21\u677f\u65f6\uff0c\u66ff\u6362\u9ed8\u8ba4\u9879\u76ee\u540d\n    if self.template.eq(&quot;react-native&quot;) {\n      change_default_name_in_template(\n        &amp;self.project_name,\n        template_path.as_str(),\n        project_path_str.as_str(),\n      )\n      .await?;\n    }\n    println!();\n    init_git(&amp;self.project_name, project_path_str.as_str())?;\n    let auto_install = self.auto_install.unwrap_or(true);\n    if auto_install {\n      install_deps(&amp;self.npm, || self.call_success()).await?;\n    } else {\n      self.call_success();\n    }\n    Ok(())\n  }<\/code><\/pre>\n<p><code>create<\/code> \u4e3b\u8981\u505a\u4e86\u4ee5\u4e0b\u51e0\u4ef6\u4e8b\u60c5\uff1a<\/p>\n<ol>\n<li>\u521b\u5efa\u9879\u76ee\u76ee\u5f55<\/li>\n<li>\u521b\u5efa\u9879\u76ee\u6587\u4ef6 <code>creator.create_files<\/code><\/li>\n<li>\u521d\u59cb\u5316 <code>git init_git<\/code><\/li>\n<li>\u5b89\u88c5\u4f9d\u8d56 <code>install_deps<\/code><\/li>\n<\/ol>\n<p>\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025885\" alt=\"\u521d\u59cb\u53162\uff0c\u521b\u5efa\u9879\u76ee\" title=\"\u521d\u59cb\u53162\uff0c\u521b\u5efa\u9879\u76ee\" loading=\"lazy\"><\/p>\n<p>\u63a5\u7740\u6211\u4eec\u91cd\u70b9\u6765\u770b\u4e00\u4e0b <code>creator.create_files<\/code> \u51fd\u6570\uff1a<\/p>\n<h3>8.2 creator.create\/_files<\/h3>\n<pre><code class=\"rs\">\/\/ crates\/taro_init\/src\/creator.rs\npub async fn create_files(\n    &amp;self,\n    files: &amp;[&amp;str],\n    template_path: &amp;str,\n    options: &amp;mut CreateOptions,\n    js_handlers: &amp;HashMap&lt;String, ThreadsafeFunction&lt;CreateOptions&gt;&gt;,\n  ) -&gt; anyhow::Result&lt;()&gt; {\n    let current_style_ext = STYLE_EXT_MAP\n      .get(&amp;options.css.unwrap_or(CSSType::None))\n      .unwrap_or(&amp;&quot;css&quot;);\n    options.css_ext = Some(current_style_ext.to_string());\n    for file in files {\n      \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801...\n      if need_create_file {\n        \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801...\n        let dest_path = self.get_destination_path(&amp;[&amp;dest_re_path]);\n        let from_path: String = PathBuf::from(file_relative_path)\n          .to_string_lossy()\n          .to_string();\n        self\n          .tempate(from_path.as_str(), dest_path.as_str(), &amp;options.clone())\n          .await?;\n        println!(\n          &quot;{} {}&quot;,\n          style(&quot;\u2714&quot;).green(),\n          style(&quot;\u521b\u5efa\u6587\u4ef6: &quot;.to_owned() + dest_path.as_str()).color256(238)\n        );\n      }\n    }\n    Ok(())\n  }<\/code><\/pre>\n<p>\u6211\u4eec\u91cd\u70b9\u6765\u770b\u4e00\u4e0b <code>creator.tempate<\/code> \u51fd\u6570\uff1a<\/p>\n<h3>8.3 creator.tempate \u6a21\u677f<\/h3>\n<pre><code class=\"rs\">\/\/ crates\/taro_init\/src\/creator.rs\n\npub async fn tempate(\n    &amp;self,\n    from_path: &amp;str,\n    dest_path: &amp;str,\n    options: &amp;CreateOptions,\n  ) -&gt; anyhow::Result&lt;()&gt; {\n    if MEDIA_REGEX.is_match(from_path) {\n      let dir_name = PathBuf::from(dest_path)\n        .parent()\n        .unwrap()\n        .to_string_lossy()\n        .to_string();\n      async_fs::create_dir_all(&amp;dir_name)\n        .await\n        .with_context(|| format!(&quot;\u6587\u4ef6\u5939\u521b\u5efa\u5931\u8d25: {}&quot;, dir_name))?;\n      async_fs::copy(from_path, dest_path)\n        .await\n        .with_context(|| format!(&quot;\u6587\u4ef6\u590d\u5236\u5931\u8d25: {}&quot;, from_path))?;\n      return Ok(());\n    }\n    generate_with_template(from_path, dest_path, options).await?;\n    Ok(())\n  }<\/code><\/pre>\n<p>\u6211\u4eec\u91cd\u70b9\u6765\u770b\u4e00\u4e0b <code>generate_with_template<\/code> \u51fd\u6570\uff1a<\/p>\n<h3>8.4 generate\/_with\/_template \u6839\u636e\u6570\u636e\u6e32\u67d3\u6a21\u677f\uff0c\u751f\u6210\u6587\u4ef6<\/h3>\n<pre><code class=\"rs\">\/\/ crates\/taro_init\/src\/utils.rs\npub async fn generate_with_template(from_path: &amp;str, dest_path: &amp;str, data: &amp;impl serde::Serialize) -&gt; anyhow::Result&lt;()&gt; {\n  let form_template = async_fs::read(from_path).await.with_context(|| format!(&quot;\u6587\u4ef6\u8bfb\u53d6\u5931\u8d25: {}&quot;, from_path))?;\n  let from_template = String::from_utf8_lossy(&amp;form_template);\n  let template = if from_template == &quot;&quot; {\n    &quot;&quot;.to_string()\n  } else {\n    HANDLEBARS.render_template(&amp;from_template, data).with_context(|| format!(&quot;\u6a21\u677f\u6e32\u67d3\u5931\u8d25: {}&quot;, from_path))?\n  };\n  let dir_name = Path::new(dest_path).parent().unwrap().to_string_lossy().to_string();\n  async_fs::create_dir_all(&amp;dir_name).await.with_context(|| format!(&quot;\u6587\u4ef6\u5939\u521b\u5efa\u5931\u8d25: {}&quot;, dir_name))?;\n  let metadata = async_fs::metadata(from_path).await.with_context(|| format!(&quot;\u6587\u4ef6\u8bfb\u53d6\u5931\u8d25: {}&quot;, from_path))?;\n  async_fs::write(dest_path, template).await.with_context(|| format!(&quot;\u6587\u4ef6\u5199\u5165\u5931\u8d25: {}&quot;, dest_path))?;\n  #[cfg(unix)]\n  async_fs::set_permissions(dest_path, metadata.permissions()).await.with_context(|| format!(&quot;\u6587\u4ef6\u6743\u9650\u8bbe\u7f6e\u5931\u8d25: {}&quot;, dest_path))?;\n  Ok(())\n}<\/code><\/pre>\n<p>taro init \u7684 rust\u4ee3\u7801\u4e2d\uff0c\u5b89\u88c5\u4f9d\u8d56\u5f15\u5165\u4e86<a href=\"https:\/\/link.segmentfault.com\/?enc=6UfPawdPSHmPdkFYEqWolg%3D%3D.M6PW97s3hQiTPjdtFu9pdsZ6S0KlMnQnbe2%2BdXnPMKkIZEWAPZeWRyK31MQxSYSI\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">crates\/handlebars rust\u5305<\/a>\uff0c\u7c7b\u4f3c <a href=\"https:\/\/segmentfault.com\/a\/npmjs.com\" target=\"_blank\" rel=\"noopener noreferrer\">npm \u5305\u7ba1\u7406\u5b98\u7f51<\/a>\u3002<\/p>\n<p>\u7ecf\u8fc7 <code>HANDLEBARS.render_template(&amp;from_template, data)<\/code> <a href=\"https:\/\/link.segmentfault.com\/?enc=tz3v%2FatefDDC7xqV89Zp8w%3D%3D.jaIW%2F59jeb6hlLoGlbPmHTtNtSXVxxUuIjhe5XYJYtE0K02O4rsz8XXMkRMHsAUl\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">handlebars-rust<\/a> \u6839\u636e\u6570\u636e\u6e32\u67d3\u6a21\u677f\uff0c\u751f\u6210\u6587\u4ef6\u3002<\/p>\n<p>\u6bd4\u5982\uff1a<code>handlebars<\/code> \u6a21\u677f\u4e2d\u7684 <code>app.config.js =&gt; app.config.ts<\/code><\/p>\n<p>\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025886\" alt=\"handlebars-render.png\" title=\"handlebars-render.png\" loading=\"lazy\"><\/p>\n<p>\u66f4\u591a <code>handlebars<\/code> \u7528\u6cd5\uff0c\u53c2\u8003<a href=\"https:\/\/link.segmentfault.com\/?enc=jOHZAAr3mU0sVUJJ6vsamw%3D%3D.9DXGeeSCEPKIlOA%2BRvtrUFSZUGUuGHk0IQ%2BU%2FATYYmiQ3PWh%2BiB888bqZb%2FArUalj1EWyTHDE9MvE9PMnqMqYg%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">handlebars\u5b98\u7f51<\/a>\u3002<\/p>\n<h2>9. \u603b\u7ed3<\/h2>\n<p>\u6211\u4eec\u518d\u6765\u770b\u4e0b\u5f00\u5934\u521d\u59cb\u5316\u9879\u76ee\u7684 <code>gif<\/code> \u56de\u987e\u4e0b\u6574\u4e2a <code>taro init<\/code> \u8fc7\u7a0b\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025877\" alt=\"taro-init-gif-high.gif\" title=\"taro-init-gif-high.gif\" loading=\"lazy\"><\/p>\n<p>\u6839\u636e\u524d\u9762\u4e24\u7bc7 <a href=\"https:\/\/link.segmentfault.com\/?enc=CG938RmnMcxXrqUDsXT29A%3D%3D.9E4zNvsZCKcRNyVQW4sBzfjo0EfcX9ojm6igSD1GwWxJIoUsOlLg%2FAE%2FLJT5PaOQ\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">1. taro cli init<\/a>\u3001<a href=\"https:\/\/link.segmentfault.com\/?enc=65nCyiJ00a0u6LLatR26kA%3D%3D.%2FxvYbSwsqSbXVaDx0SW3gBHHaHhnNJNlTQYB1b7O8Eb1PVw9jUvWkXpeiTROkRVg\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">2. taro \u63d2\u4ef6\u673a\u5236<\/a> \u6587\u7ae0\uff0c\u6211\u4eec\u53ef\u4ee5\u5f97\u77e5\uff1a<code>taro init<\/code> \u521d\u59cb\u5316\u547d\u4ee4\uff0c\u6700\u7ec8\u8c03\u7528\u7684\u662f <code>packages\/taro-cli\/src\/presets\/commands\/init.ts<\/code> \u6587\u4ef6\u4e2d\u7684 <code>ctx.registerCommand<\/code> \u6ce8\u518c\u7684 <code>init<\/code> \u547d\u4ee4\u884c\u7684 <code>fn<\/code> \u51fd\u6570\u3002<\/p>\n<p>\u53ef\u4ee5\u6839\u636e\u914d\u7f6e <code>.vscode\/launch.json<\/code> \u6587\u4ef6\u8c03\u8bd5 <code>taro init<\/code> <code>node<\/code> \u90e8\u5206\u4ee3\u7801\u548c <code>rust<\/code> \u914d\u7f6e <code>type:lldb<\/code> \u4ee3\u7801\u3002<\/p>\n<pre><code class=\"ts\">export default (ctx: IPluginContext) =&gt; {\n  ctx.registerCommand({\n    name: 'init',\n    optionsMap: {\n        \/\/ \u7701\u7565\u82e5\u5e72\u4ee3\u7801...\n    },\n    async fn (opts) {\n      const Project = require('..\/..\/create\/project').default\n      const project = new Project({\n        \/\/ \u7701\u7565\u82e5\u5e72\u53c2\u6570...\n      })\n      project.create()\n    }\n  })\n}<\/code><\/pre>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nasync create () {\n    try {\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        this.write()\n    } catch (error) {\n        console.log(chalk.red('\u521b\u5efa\u9879\u76ee\u5931\u8d25: ', error))\n    }\n}<\/code><\/pre>\n<p><code>ask<\/code> \u547d\u4ee4\u884c\u4ea4\u4e92\u5f0f\u9009\u62e9\u4f7f\u7528\u7684\u662f <a href=\"https:\/\/link.segmentfault.com\/?enc=2vTred4HFmhKpBMaHlevTw%3D%3D.ayGBHVcnOVeaxwfx25tOEW4%2FuBFH7%2F5tSZFDBHJhYTZDVBWAbdGXhMhG8%2F%2FKvnsw\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">inquirer<\/a> <code>inquirer.prompt<\/code> \u5b9e\u73b0\u3002\u4f7f\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=2ifgpWb%2BwYLD%2FNoDhnyCsg%3D%3D.GBBc7Ezou%2BaoTUc5lhNJ1pVUT5sqvmaz16TCACo3kCLrKGb%2FEFrXnYBn2vbYFnSa\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">download-git-repo<\/a> \u5305\uff08\u5982\u679c\u662f <code>url<\/code> \u5219\u7528 <code>axios<\/code> \u4e0b\u8f7d\uff09\u628a\u8fdc\u7a0b\u4ed3\u5e93\u4e0b\u8f7d\u5230\u672c\u5730\u79fb\u52a8\u5230<code>packages\/taro-cli\/templates<\/code>\u3002<\/p>\n<pre><code class=\"ts\">import { createProject } from '@tarojs\/binding'<\/code><\/pre>\n<pre><code class=\"ts\">\/\/ packages\/taro-cli\/src\/create\/project.ts\nwrite (cb?: () =&gt; void) {\n    createProject({\n    }, handler).then(() =&gt; {\n      cb &amp;&amp; cb()\n    })\n}<\/code><\/pre>\n<p><code>write<\/code> \u51fd\u6570\u4e2d\u7684 <code>createProject<\/code> \u521b\u5efa\u6587\u4ef6\u90e8\u5206\u662f\u4f7f\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=Kwc3sY99OqepYVgJxBTAVA%3D%3D.64oteCZFDctZYT8Gc6Q0Pc5rdQGZsTpiMy2UJzlGlM2iWAgIxqPHCwBrROXcML5i\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">rust<\/a> \u5b9e\u73b0\u7684\u3002\u4f7f\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=wygGEHZoGjuoq9Pqa0ez3g%3D%3D.UtLj7%2Bo2rOHEa928fwMm2eClQw38nsahXyLfOjAJN0kOjviUWMJBSjLzQ%2F6G90cIqXrNcCa3Pd6CJMRxsimO7Q%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">napi-rs<\/a> \u5305\u7ed1\u5b9a <code>rust<\/code> \u4ee3\u7801\uff0c\u7ed9 <code>nodejs<\/code> \u8c03\u7528\u3002<\/p>\n<p>\u6a21\u677f\u90e8\u5206\u4f7f\u7528\u7684\u662f <a href=\"https:\/\/link.segmentfault.com\/?enc=7kc0L4NNmBP4%2BuFUNgNyNA%3D%3D.pD5sQLyje253icbq%2FzRpfpK0Uzl0Lo9GcR5%2BNJf7jAwR2%2BIKAJ1wWM%2Fs0Z1Vm%2FMNhHOtCJ9xg6gcpkefj%2BHs0g%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">handlebars<\/a>\uff0c<code>rust<\/code> \u4f7f\u7528\u7684 <a href=\"https:\/\/link.segmentfault.com\/?enc=SgZ6UlBcyKvZvLuQsYDTqw%3D%3D.LHpQ5YpoEQkjg6MdWGTqisghB0Jxq6SenNauzHVxaTtQNrce%2FcjZ1qviGO4yKPIi\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">handlebars rust \u5305 crates\/handlebars<\/a> <a href=\"https:\/\/link.segmentfault.com\/?enc=0RBTJbmMIhB17AFZtfSLyA%3D%3D.KIm7%2FfWIjixPW55y1ecW%2FV4PlOaaQEsEm1nc9Jhjj%2BwPiNmk%2BXM4NzFKJrWE41Ch\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">rust<\/a> \u5b9e\u73b0\u3002<\/p>\n<p>\u6839\u636e\u6570\u636e\u6e32\u67d3 <code>handlebars<\/code> \u6a21\u677f\uff0c\u521b\u5efa\u9879\u76ee\uff0c\u751f\u6210\u6587\u4ef6\u3002<\/p>\n<p>\u518d\u6839\u636e\u5305\u7ba1\u7406\u5668\u5b89\u88c5\u4f9d\u8d56\u3002\u6700\u540e\u6253\u5370\u521b\u5efa\u9879\u76ee\u6210\u529f\uff0c\u8bf7\u8fdb\u5165\u9879\u76ee\u76ee\u5f55\u5de5\u4f5c\u3002<\/p>\n<p>\u6574\u4e2a <code>taro init<\/code> \u521b\u5efa\u65b0\u9879\u76ee\u6d41\u7a0b\u7528\u4e00\u5f20\u56fe\u8868\u793a\u5982\u56fe\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000046025887\" alt=\"taro init \u521b\u5efa\u65b0\u9879\u76ee\u6d41\u7a0b\" title=\"taro init \u521b\u5efa\u65b0\u9879\u76ee\u6d41\u7a0b\" loading=\"lazy\"><\/p>\n<hr>\n<p><strong>\u5982\u679c\u770b\u5b8c\u6709\u6536\u83b7\uff0c\u6b22\u8fce\u70b9\u8d5e\u3001\u8bc4\u8bba\u3001\u5206\u4eab\u3001\u6536\u85cf\u652f\u6301\u3002\u4f60\u7684\u652f\u6301\u548c\u80af\u5b9a\uff0c\u662f\u6211\u5199\u4f5c\u7684\u52a8\u529b\u3002\u4e5f\u6b22\u8fce\u63d0\u5efa\u8bae\u548c\u4ea4\u6d41\u8ba8\u8bba<\/strong>\u3002<\/p>\n<p>\u4f5c\u8005\uff1a\u5e38\u4ee5<strong>\u82e5\u5ddd<\/strong>\u4e3a\u540d\u6df7\u8ff9\u4e8e\u6c5f\u6e56\u3002\u6240\u77e5\u751a\u5c11\uff0c\u552f\u5584\u5b66\u3002<a href=\"https:\/\/link.segmentfault.com\/?enc=o0x7UyamA%2FT7taQ3fiydvA%3D%3D.TSFwf5cHvg5UHPwMRaDTS8ViBaJIuI0k%2FmZlS6Oei3o%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u82e5\u5ddd\u7684\u535a\u5ba2<\/a>\uff0c<a href=\"https:\/\/link.segmentfault.com\/?enc=iAjmQVFnxrNXwyFtEvrxhQ%3D%3D.7qw9UBvO509GpiGEqn461%2FpLP6KBhvZiWrB6P9YffA8k6ixiuW4B31qH4pxYsK7D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">github blog<\/a>\uff0c\u53ef\u4ee5\u70b9\u4e2a <code>star<\/code> \u9f13\u52b1\u4e0b\u6301\u7eed\u521b\u4f5c\u3002<\/p>\n<p>\u6700\u540e\u53ef\u4ee5\u6301\u7eed\u5173\u6ce8\u6211<a href=\"https:\/\/link.segmentfault.com\/?enc=WtYYn72z9F1cjzfNFinN%2BQ%3D%3D.wbFkns1Upba6dQd0Msnjp%2FJQGbmqa2DMloyuTE%2FQVplp8MgX0FlSpyNrnMweXZXr\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@\u82e5\u5ddd<\/a>\uff0c\u6b22\u8fce\u5173\u6ce8\u6211\u7684<a href=\"https:\/\/link.segmentfault.com\/?enc=HSS8co3k1TNd99xojAJbkQ%3D%3D.AAcJr8lgfAVp6kIftj7qtYUJKVQYo%2BnJEEt7%2FVJcyJoRfscvYjGJrxkKVXRN6uG3gsDAK8%2FBsgcZk9zBLf5nrQ%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u516c\u4f17\u53f7\uff1a\u82e5\u5ddd\u89c6\u91ce<\/a>\u3002\u6211\u503e\u529b\u6301\u7eed\u7ec4\u7ec7\u4e86 3 \u5e74\u591a<a href=\"https:\/\/link.segmentfault.com\/?enc=Zb1A8bOWWZRqeKUVturmGg%3D%3D.8BJFDV0As7yUpGjDNzWlyIqR5XEExYYm%2BuKOkYLwQmpmUdXYcy5V7klCwbjTb1%2BU\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u6bcf\u5468\u5927\u5bb6\u4e00\u8d77\u5b66\u4e60 200 \u884c\u5de6\u53f3\u7684\u6e90\u7801\u5171\u8bfb\u6d3b\u52a8<\/a>\uff0c\u611f\u5174\u8da3\u7684\u53ef\u4ee5<a href=\"https:\/\/link.segmentfault.com\/?enc=KQ512aobu9h0hiRxfcu0%2Bw%3D%3D.%2FSmu4%2Boy7uLtzWUMa4tGcV8%2B5epJ4qppMHMH0VF6STL1gwVK0SOJVkndvGZK59qv\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u70b9\u6b64\u626b\u7801\u52a0\u6211\u5fae\u4fe1 <code>ruochuan02<\/code> \u53c2\u4e0e<\/a>\u3002\u53e6\u5916\uff0c\u60f3\u5b66\u6e90\u7801\uff0c\u6781\u529b\u63a8\u8350\u5173\u6ce8\u6211\u5199\u7684\u4e13\u680f<a href=\"https:\/\/link.segmentfault.com\/?enc=%2B8ZRXn0vu3uKKFnJWuHFoA%3D%3D.rGA0%2FPogD69Wi2SLU9VHyML6f9XAB0EfhRquZ89DQZyyoBPwzQTQVcUyYbQGmS3e\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u300a\u5b66\u4e60\u6e90\u7801\u6574\u4f53\u67b6\u6784\u7cfb\u5217\u300b<\/a>\uff0c\u76ee\u524d\u662f\u6398\u91d1\u5173\u6ce8\u4eba\u6570\uff086k+\u4eba\uff09\u7b2c\u4e00\u7684\u4e13\u680f\uff0c\u5199\u6709\u51e0\u5341\u7bc7\u6e90\u7801\u6587\u7ae0\u3002<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000046025874\">https:\/\/segmentfault.com\/a\/1190000046025874<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. \u524d\u8a00 \u5927\u5bb6\u597d\uff0c\u6211\u662f\u82e5\u5ddd\uff0c\u6b22\u8fce\u5173\u6ce8\u6211\u7684\u516c\u4f17\u53f7\uff1a\u82e5\u5ddd\u89c6\u91ce\u3002\u6211\u503e\u529b\u6301\u7eed\u7ec4\u7ec7\u4e86 3 \u5e74\u591a\u6bcf\u5468\u5927\u5bb6\u4e00\u8d77\u5b66\u4e60 200 [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10020622","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020622","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"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10020622"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020622\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10020622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10020622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10020622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}