{"id":20082592,"url":"https://github.com/lexmin0412/taro2-template","last_synced_at":"2025-05-06T01:30:29.845Z","repository":{"id":63292295,"uuid":"223903353","full_name":"lexmin0412/taro2-template","owner":"lexmin0412","description":"可用于生产环境的taro项目模版，技术栈：taro + taro-ui + typescript + dva / mobx + sass，无需过多关注项目配置，预置功能包括但不限于页面/组件/store/service模版一键生成/编译自动生成路由列表和组件入口/代码规范强制检查/请求拦截封装/小程序CI等，实现多端项目的高效快速开发。目前已有1.x / 2.x / 3.x 版本。","archived":false,"fork":false,"pushed_at":"2022-02-27T20:03:26.000Z","size":7027,"stargazers_count":62,"open_issues_count":0,"forks_count":20,"subscribers_count":4,"default_branch":"2.x","last_synced_at":"2025-04-24T04:37:48.195Z","etag":null,"topics":["dva","mobx","node","react","react-template","scss","taro","taro-template","taro-ui","template","typescript","vue","vue-template"],"latest_commit_sha":null,"homepage":"https://lexmin0412.github.io/taro-template/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lexmin0412.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-25T08:54:22.000Z","updated_at":"2025-02-24T21:17:39.000Z","dependencies_parsed_at":"2022-11-16T12:34:03.300Z","dependency_job_id":null,"html_url":"https://github.com/lexmin0412/taro2-template","commit_stats":null,"previous_names":["cathe-zhang/taro-template"],"tags_count":1,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexmin0412%2Ftaro2-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexmin0412%2Ftaro2-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexmin0412%2Ftaro2-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexmin0412%2Ftaro2-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lexmin0412","download_url":"https://codeload.github.com/lexmin0412/taro2-template/tar.gz/refs/heads/2.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252429931,"owners_count":21746571,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dva","mobx","node","react","react-template","scss","taro","taro-template","taro-ui","template","typescript","vue","vue-template"],"created_at":"2024-11-13T15:44:01.482Z","updated_at":"2025-05-06T01:30:29.448Z","avatar_url":"https://github.com/lexmin0412.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Taro 2.x 项目模版\n\n\u003e 说明：当前仓库长期维护基于 Taro2.x 的模版，同时还提供了 1.x 和 3.x 版本(基于React)可供选择。\n\u003e\n\u003e [1.x 版本模版点此前往](https://github.com/lexmin0412/taro-template/tree/1.x/)\n\u003e\n\u003e 3.x 版本为独立仓库，[点此前往](https://github.com/lexmin0412/taro3-react-template)\n\n## 相关项目\n\n基于这个模版，开发了 [taro-xui](https://github.com/lexmin0412/taro-xui) 这个 UI 库，而在这个模版中又引用了 taro-xui 作为首页的演示 demo，emm...\n\n禁止套娃...\n\n## 导航\n\n- [功能列表](#功能列表)\n- [项目结构](#项目结构)\n- [开始](#开始)\n- [开发](#开发)\n  - [编译](#编译)\n  - [预置功能](#预置功能)\n  - [基础开发](#基础开发)\n    - [请求数据](#请求数据)\n      - [创建 service](#创建service)\n      - [直接调用 service 获取数据](#直接调用service获取数据)\n    - [组件](#组件)\n      - [1.定义组件](#1.定义组件)\n      - [2.在页面中引用](#在页面中引用)\n  - [开发规范](#开发规范)\n    - [ESLint](#ESLint)\n    - [静态资源导入规范](#静态资源导入规范)\n    - [类名规范](#类名规范)\n  - [代码/性能优化](#代码/性能优化)\n- [部署](#部署)\n- [技术栈](#技术栈)\n- [后续工作](#后续工作)\n- [问题记录](#问题记录)\n  - [Taro 升级问题](#Taro升级问题)\n  - [其他](#其他)\n- [优化](#优化)\n  - [taro-ui 样式引入](#taro-ui样式引入)\n  - [官方优化指南](#官方优化指南)\n\n## 功能列表\n\n- 基础功能支持\n  - [x] TypeScript\n  - [x] Sass，全局注入公用样式文件\n  - [x] UI 库（taro-ui）\n  - [x] 状态管理（mobx）\n  - [x] 异步编程（async/await）\n  - [x] 引入字体（iconfont）\n- 接口请求\n  - [x] request 类\n  - [x] 拦截器\n    - [x] url 拦截器\n    - [x] header 拦截器\n    - [x] param 拦截器\n    - [x] data 拦截器\n  - [x] 开发环境本地代理（h5 端）\n  - [x] jsonp 支持（h5 端）\n- 调试\n  - [x] vconsole（h5 端）\n- 工程化\n  - [x] 全局变量\n  - [x] 插件\n    - [x] [环境变量检查 - taro-plugin-check-env](https://github.com/lexmin0412/taro-plugin-check-env)\n    - [x] [pages/components 文件扫描，入口文件初始化 - taro-plugin-init-app](https://github.com/lexmin0412/taro-plugin-init-app)\n    - [x] [根据不同的环境变量生成不同的 project.config.json（小程序端） - taro-plugin-mp](https://github.com/lexmin0412/taro-plugin-mp)\n  - [x] 通过 plop 插件一键生成模版文件（页面、组件、样式、服务类、mobx 状态管理）\n  - [x] 底层组件，用于页面和组件继承，实现类似 vue 原型绑定的功能\n  - [x] git hooks\n    - [x] eslint\n    - [x] stylelint\n    - [x] prettier\n    - [x] commit lint\n  - [x] 引入自建组件库([taro-xui](https://github.com/lexmin0412/taro-xui))\n  - [x] 引入自建工具类库（wtils）\n  - [ ] 接入 Taro 模版源 \u003chttp://taro-docs.jd.com/taro/docs/template.html\u003e\n  - [ ] 提交 Taro 物料市场 \u003chttps://taro-ext.jd.com/\u003e\n- 组件\n  - [x] Card 卡片组件 提供圆角、阴影功能，可自定义类名、样式（圆角及内外边距）\n  - [x] Countdown 倒计时组件，可自定义结束时间、自定义倒计时长、是否展示天，自定义 item 样式\n  - [x] Divider 分割线，可自定义高度\n  - [x] Nodata 缺省组件 可自定义图片、文字、宽高\n  - [x] Paging 分页提示组件 将 scrollerLoader, scrollerEndMessage 合并成一个组件，减少判断\n  - [x] Modal 基础弹窗组件，可选择弹窗位置，包括中间弹窗、底部弹窗，抛出关闭回调\n  - [x] Tabs 标签页\n  - [x] TButton 按钮组件，可自定义类名、自定义宽高、背景色、圆角、positionType\n  - [x] TImage 图片组件 提供错误处理、loading 过渡、查看大图等功能\n  - [x] TImageUploader 图片上传组件 基于 image 提供上传图片、图片数量限制、删除图片、查看大图等功能\n- 工具类\n  - [x] img.ts 图片处理类（如拼接 url、预览等）\n  - [x] mp.ts 小程序独有 api 封装（如检查更新）\n  - [x] page.ts 页面工具类，实现获取页面路由、跳转等功能\n  - [x] toast.ts loading/toast api 封装简化\n  - [x] validator.ts 表单验证\n  - [x] meta.ts meta 相关功能\n- 体验工程\n  - [ ] 骨架屏\n\n## 项目结构\n\n以下是项目结构的缩略图\n\n![项目结构](./docs/structure.png)\n\n## 开始\n\n```zsh\n# 获取模版\ngit clone https://github.com/lexmin0412/taro-template.git\n# 进入项目文件夹\ncd taro_template\n# 安装依赖\nyarn\n# 本地浏览器运行\nyarn dev:h5\n# 本地小程序运行\nyarn dev:mp\n```\n\n## 开发\n\n### 编译\n\n为了提高开发体验、调整了默认 taro 模版的部分编译命令，也为不同服务器环境（包括 dev/sit/uat/pro）、不同编译模式（开发/打包）、不同运行环境（h5/小程序）提供了统一的命令。\n\n新增的服务器环境参数，主要是考虑到在处理线上问题时，为了复现问题，经常需要在本地请求非开发环境的接口，这时候习惯的操作是去更改配置文件，而更改配置文件的风险是很高的，不仅操作繁琐，更容易在多人开发时造成冲突，甚至可能将测试的变量提交到生产环境，造成不必要的线上问题。\n\n编译命令格式如下：\n\n```shell\nyarn \u003cmode\u003e:\u003cplatform\u003e-\u003cenv\u003e\n```\n\n`mode` ，编译模式：\n\n- dev 本地开发\n- build 服务器部署\n\n`platform` ，运行环境\n\n- mp 微信小程序\n- h5 h5\n\n`env` ，服务器环境标识，不同标识对应着不同的配置项，如接口 host\n\n- sit 测试环境\n- uat 预发环境\n- pro 生产环境\n- 空 开发环境\n\n示例：\n\n```shell\nyarn dev:mp  # 本地开发 小程序 开发环境\nyarn dev:mp-sit  # 本地开发 小程序 测试环境\nyarn build:mp   # 部署 小程序 开发环境\nyarn build-mo-pro  # 部署 小程序 生产环境\n```\n\n完整的编译命令列表详见 [package.json](./package.json) 中的 `scripts` 配置项。\n\n### 启动本地调试\n\n启动本地调试模式需要新建 config/local.js，参考如下内容：\n\n```js\n/**\n * 本地调试配置\n * 默认使用开发环境\n * 运行 yarn dev:h5命令\n */\n\nmodule.exports = {\n\tdefineConstants: {\n\t\tAPP_CONF: {\n\t\t\tAPI_HOST: JSON.stringify('https://xx.com/'),\n\t\t\tAPPID: JSON.stringify('this_is_my_tourist_appid'),\n\t\t\tAPI_MAP_QQ: JSON.stringify('https://apis.map.qq.com'),\n\t\t\tKEY_MAP_QQ: JSON.stringify('UQPBZ-RCU36-K2YS3-EMV6Y-JI6JJ-3WBUM'),\n\t\t},\n\t},\n}\n```\n\n### 预置功能\n\n在开发阶段，为了减少一些重复且枯燥，还有可能造成报错的代码，做了以下几个工作：\n\n- 通过命令生成文件\n- pages 和 components 文件夹的扫描\n- 公用 sass 文件的全局注册\n\n1. **通过命令生成文件**\n\n对于文件的新建操作，在项目中也预置了命令，开发者只需在命令行中输入 `yarn template` ，然后根据相关提示输入对应的配置项，即可生成对应的文件，目前支持以下四种文件的快捷创建：\n\n- 页面（同时生成对应的 scss 和 ts 类型生命文件）\n- 组件（同时生成对应的 scss 文件）\n- mobx 模块\n- service 类\n\n2. pages 和 components 文件夹的扫描\n\n在平常的项目开发中，存在以下问题：\n\n- 每新建一个页面文件，就需要在 app.tsx 中的 pages 配置项中追加一行；\n- 每一个组件的引用，都需要另起一行，引用到具体的组件存放路径\n\npages 文件夹的扫描，是基于 pages 目录及其所有文件夹及文件夹下的文件名，生成一个路由文件 routes.js，再读取这个路由文件，追加到 app.tsx 模版文件的 pages 配置项中去。\n\ncomponents 文件夹的扫描，跟 pages 目录同理，但生成的是一个 index.ts 文件，自动引入了 components 文件夹下的所有组件并导出，这样做的目的是在多个组件引用时，不需要每一个组件的引用都另起一行，而可以通过如下方式书写：\n\n```tsx\nimport { Line, TImage } from '~/components\n```\n\n3. 公用 sass 文件的全局注册\n\n在 config/index.js 中预置了如下内容：\n\n```js\n// config/index.js\n{\n    sass: {\n        // 全局注入scss文件\n        resource: [\n            'src/styles/classes.scss',\n            'src/styles/mixin.scss',\n            'src/styles/theme.scss',\n            'src/styles/var.scss'\n        ],\n        // 指定项目根目录，这样在resource字段中就不需要重复书写path.resolve了\n        projectDirectory: path.resolve(__dirname, '..')\n    },\n}\n```\n\n作用是全局注入了 mixin.scss 和 theme.scss，这样做之后，在项目内的所有 scss 文件中，可以直接使用这两个文件中的所有特性而不需要引入对应的文件，如果有更多的公用文件注入，只需要修改这里的配置项即可（注意：修改后需要重启项目才能生效）。（**TODO：后续需要在编译插件中扫描 styles 文件夹，省去配置项追加的操作**）\n\n```scss\n// pages/index/index.scss\n.index-page {\n\tbackground-color: $body-bg; // 变量来自styles/theme.scss\n\n\t.block-title {\n\t\t@include textOrient(1); // textOrient来自styles/\n\t}\n}\n```\n\n### 基础开发\n\n#### 请求数据\n\n在页面中请求数据，需要先做一个判断：当前这个接口的数据需不需要跨页面共享，如果不需要，那么就没有必要经过 dva，直接调用 service 即可；反之则需要定义 model , 在页面上发起 action, 走 dva 的流程。\n\n##### 创建 service\n\nservice, 也就是我们的服务模块，用于统一存放后端接口定义，供页面调用。\n\n** `service` 文件设计规范**\n\n由于同一个接口被不同页面调用调用的可能性非常高，服务模块的结构需要依照后端接口来设计，如项目内既包含了公司后端项目的接口请求，又需要请求第三方接口，那么 service 模块就要分成两个大的模块，大的模块下面再根据接口模块划分来划分小的 service 文件。\n\n如一个接口路径为 `https://xxx.normal.com/webapi/account/queryBalanceAccount` , 用途是查询用户账户余额，那么这个接口在 service 模块的结构就应该表现为：\n\n首先分为两个大的模块，下一层是后台的项目，最后根据后台接口模块命名一个 `xxx.service.ts` , xxx 是后台的模块名称。只要一个接口是在后台接口项目中的这个子模块，那么在前端就应该定义在相应的 service 文件下。\n\n上面的示例接口设计结构如下：\n\n```bash\n├── services        服务根文件夹\n|   ├── inside        内部服务\n|   ├── qqMap         腾讯地图api接口\n|     ├── ws.service.ts    webservice服务\n```\n\n##### 直接调用 service 获取数据\n\n```tsx\nimport QQMapWSService from '~/services/qqMap/ws.service'\n\nclass Index extends Component {\n\tstate = {}\n\n\tcomponentDidMount() {\n\t\tthis.handleJSONPTest()\n\t}\n\n\t// 直接调用service\n\tasync handleJSONPTest() {\n\t\tconst result = await QQMapWSService.geocoder({\n\t\t\tlocation: `28.2532,112.87887`,\n\t\t\tget_poi: 0,\n\t\t})\n\t\tthis.setState({\n\t\t\tlocationData: result.data,\n\t\t})\n\t\tconsole.log('result', result)\n\t}\n\n render() {\n  const { locationData } = this.state\n  return (\n\t\t\u003cView className='home-index-page'\u003e\n\t\t\t{locationData \u0026\u0026 (\n\t\t\t\t\u003cView\u003e\n\t\t\t\t\t当前位置：{locationData.latitude}，{locationData.longitude}\n\t\t\t\t\u003c/View\u003e\n\t\t\t)}\n\t\t\u003c/Vew\u003e\n  )\n }\n}\n```\n\n#### 组件\n\n在业务开发的过程中，我们常需要复用一些相同的结构，如商品轮播图，订单 item 等，如果每个页面都复制粘贴一遍，不仅不美观，更难以维护，这时候就需要开发组件了。\n\n组件分为展示型组件和容器型组件。展示型组件只需要接收父组件传递的属性并渲染页面，容器型组件则会涉及到数据处理等复杂的逻辑，难以重用，所以平常我们开发的一般都是展示型的组件。\n\n在项目模板中已经包含了数个常用的基础组件，可直接使用，引用方式：\n\n```tsx\nimport { Card, TImage } from '~/components'\n```\n\n在编译前已经进行了 components 文件夹的扫描操作，自动生成了 components/index.ts，而 `~/components` 会指向 src/components/index.ts 文件，所以可以直接通过以上方式引用。\n\n##### 1. 定义组件\n\n通过 yarn template 命令新建组件，会生成如下模版：\n\n```tsx\n/**\n * ComponentDesc\n */\n\nimport { ComponentClass } from 'react'\nimport Taro, { Component } from '@tarojs/taro'\nimport { View } from '@tarojs/components'\n\nimport './ComponentName.scss'\n\n/**\n * props属性\n */\ninterface IProps {\n\t/**\n\t * 子元素\n\t */\n\tchildren?: any\n}\n\n/**\n * 组件内部属性\n */\ninterface IState {}\n\ninterface ComponentName {\n\tprops: IProps\n\tstate: IState\n}\n\nclass ComponentName extends Component {\n\tstatic defaultProps: IProps = {}\n\n\trender() {\n\t\treturn \u003cView className='ComponentName-comp'\u003eComponentDesc\u003c/View\u003e\n\t}\n}\n\nexport default ComponentName as ComponentClass\u003cIProps, IState\u003e\n```\n\n基于以上模版，我们就可以开始组件的具体逻辑开发了。\n\n##### 2. 在页面中引用\n\n```tsx\nimport { ComponentName } from '~/components'\n```\n\n### 开发规范\n\n#### ESLint\n\n代码书写规范请遵循 [Taro 规范](http://taro-docs.jd.com/taro/docs/spec-for-taro.html)，后续会有更完善的规范补充。\n\n#### 静态资源导入规范\n\n一个页面文件导入模块时应该按照如下规范：\n\n    1. 先导入第三方模块，如第三方UI库等\n    2. 再导入项目内部模块，如组件、工具类等\n    3. 导入静态文件，图片在前，其他资源次之，样式文件最后\n\n示例：\n\n```tsx\n// 导入第三方库\nimport Taro, { Component, Config } from '@tarojs/taro'\nimport { View, Text } from '@tarojs/components'\nimport { connect } from '@tarojs/redux'\nimport { ComponentClass } from 'react'\n\n// 导入项目内部模块\nimport Line from '~/components/Line'\nimport Toast from '~/utils/toast'\n\n// 导入静态文件和样式\nimport './index.scss'\n```\n\n#### 类名规范\n\n- 页面容器应以模块-文件名-容器类型命名，如 home-index-page, line-comp 等\n\n- 样式\n\n```scss\n.index-page {\n\tbackground: $theme-color;\n}\n```\n\n### 代码/性能优化\n\n请基于以下文档优化：\n\n- [Taro 最佳实践](http://taro-docs.jd.com/taro/docs/best-practice.html)\n- [Render Props](http://taro-docs.jd.com/taro/docs/render-props.html)\n- [Taro 性能优化实践](http://taro-docs.jd.com/taro/docs/optimized-practice.html)\n\n## 部署\n\n根据 [package.json](./package.json) 文件中的 scripts 配置项，在对应的自动化部署工具（如 jenkins）中进行相应的配置即可。编译命令说明 [详见](#编译)\n\n## 技术栈\n\n- [taro](https://nervjs.github.io/taro/docs/README.html)\n- [taro-ui](https://taro-ui.aotu.io/)\n- [mobx](https://cn.mobx.js.org/)\n- [typescript](https://www.tslang.cn/docs/handbook/basic-types.html)\n- [scss](https://www.sass.hk/)\n\n## 问题记录\n\n### Taro 升级问题\n\n#### 使用 async/await 在小程序中报 `regeneratorRuntime is not defined`\n\n原因：没有 async await 支持\n\n解决方案：\n\n- \u003chttps://nervjs.github.io/taro/docs/async-await.html#docsNav\u003e\n- \u003chttps://nervjs.github.io/taro/docs/migrate-to-2.html\u003e\n\n### 其他\n\n#### 小程序中无法识别类型声明独立文件的操作\n\n解决方案：不将类型声明独立文件，此问题需要后续观察。\n\n#### h5 中 调用 chooseImage，点击取消按钮无法不会进入 success fail complete 中的任何一个回调\n\n解决方案：loading 放在 success 回调中 上传之前开始展示\n\n## 优化\n\n### taro-ui 样式引入\n\n```scss\n// app.scss\n\n// 方式1: 一次性引入所有样式\n@import '~taro-ui/dist/style/index.scss';\n\n// 方式2: 在使用到新的组件时才引入\n@import '~taro-ui/dist/style/components/noticeBar.scss';\n@import '~taro-ui/dist/style/components/tag.scss';\n```\n\n对于上面的情况，如果在项目中只使用到了 taro-ui 中的 Button 和 Tag 组件，打包后的 app.css 体积从 210kb 减少到 53kb，只要打包后生成的 app.css 文件小于 210kb，那么这种引入方式就是值得的。\n\n## 项目文档\n\n- [常见问题记录](./problems.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexmin0412%2Ftaro2-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flexmin0412%2Ftaro2-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexmin0412%2Ftaro2-template/lists"}