├── src ├── app.css ├── composables │ ├── index.ts │ └── useDark.ts ├── pages │ ├── index │ │ ├── index.config.ts │ │ └── index.vue │ └── hello │ │ ├── index.config.ts │ │ └── index.vue ├── layouts │ └── Layout.vue ├── store │ └── counter.ts ├── app.config.ts ├── app.ts ├── icons │ └── loading.svg ├── components │ └── Footer.vue └── index.html ├── .npmrc ├── .eslintignore ├── .eslintrc ├── config ├── dev.js ├── module │ ├── TimePlugin.js │ ├── keywords.ts │ └── TaroResolver.ts ├── plugin-mini-ci.js ├── prod.js └── index.js ├── project.tt.json ├── .gitignore ├── babel.config.js ├── project.config.json ├── types └── global.d.ts ├── tsconfig.json ├── README.md ├── uno.config.ts └── package.json /src/app.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/composables/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useDark' 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | index.html 2 | node_modules 3 | dist 4 | .history 5 | .swc 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@antfu", "./src/.eslintrc-auto-import.json"] 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/index/index.config.ts: -------------------------------------------------------------------------------- 1 | export default definePageConfig({ 2 | navigationBarTitleText: '首页', 3 | }) 4 | -------------------------------------------------------------------------------- /src/pages/hello/index.config.ts: -------------------------------------------------------------------------------- 1 | export default definePageConfig({ 2 | navigationBarTitleText: 'Hello', 3 | }) 4 | -------------------------------------------------------------------------------- /config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"', 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {}, 9 | } 10 | -------------------------------------------------------------------------------- /src/layouts/Layout.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "taro-unocss", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | deploy_versions/ 3 | .temp/ 4 | .rn_temp/ 5 | node_modules/ 6 | .DS_Store 7 | taro-apis.json 8 | scripts/ 9 | auto-imports.d.ts 10 | components.d.ts 11 | .eslintrc-auto-import.json 12 | Hooks/ 13 | .history 14 | .swc 15 | -------------------------------------------------------------------------------- /src/composables/useDark.ts: -------------------------------------------------------------------------------- 1 | import { useDark, useToggle } from '@vueuse/core' 2 | 3 | export const isDark = useDark({ 4 | onChanged: (val) => { 5 | setStorageSync('theme', val ? 'dark' : 'light') 6 | }, 7 | }) 8 | export const toggleDark = useToggle(isDark) 9 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'vue3', 7 | ts: true, 8 | }], 9 | ], 10 | } 11 | -------------------------------------------------------------------------------- /config/module/TimePlugin.js: -------------------------------------------------------------------------------- 1 | /** * @param ctx {import('@tarojs/service').IPluginContext} */ 2 | module.exports = (ctx) => { 3 | ctx.onBuildStart(() => { 4 | // console.time('build in ') 5 | }) 6 | ctx.onBuildFinish(() => { 7 | // console.timeEnd('build in ') 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /src/store/counter.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | export const useCounterStore = defineStore('counter', { 4 | state: () => ({ 5 | count: 0, 6 | }), 7 | actions: { 8 | increment() { 9 | this.count++ 10 | }, 11 | decrement() { 12 | this.count-- 13 | }, 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "taro-unocss", 4 | "description": "A Taro starter with unocss and auto-import", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index', 4 | 'pages/hello/index', 5 | ], 6 | window: { 7 | backgroundTextStyle: 'light', 8 | navigationBarBackgroundColor: '#fff', 9 | navigationBarTitleText: 'WeChat', 10 | navigationBarTextStyle: 'black', 11 | }, 12 | // tabBar: {}, 13 | // subPackages: [], 14 | darkmode: true, 15 | // debug: true, 16 | }) 17 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createPinia } from 'pinia' 3 | 4 | import 'uno.css' 5 | import './app.css' 6 | 7 | const App = createApp({ 8 | async onShow() { 9 | if (!getStorageSync('theme')) { 10 | const info = await getSystemInfo() 11 | setStorageSync('theme', info.theme || 'light') 12 | } 13 | }, 14 | // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖 15 | }) 16 | 17 | App.use(createPinia()) 18 | 19 | export default App 20 | -------------------------------------------------------------------------------- /src/icons/loading.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /types/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | 20 | declare module '@tarojs/components' { 21 | export * from '@tarojs/components/types/index.vue3' 22 | } 23 | -------------------------------------------------------------------------------- /src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 19 | -------------------------------------------------------------------------------- /src/pages/hello/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "ESNext", 5 | "target": "es2016", 6 | "lib": ["DOM", "es2016"], 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "incremental": false, 10 | "skipLibCheck": true, 11 | "moduleResolution": "node", 12 | "experimentalDecorators": true, 13 | "resolveJsonModule": true, 14 | "noUnusedLocals": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "outDir": "lib", 17 | "sourceMap": true, 18 | "allowJs": true, 19 | "jsx": "preserve", 20 | "types": [ 21 | "webpack-env", 22 | "node" 23 | ], 24 | "paths": { 25 | "~/*": ["src/*"], 26 | "@/*": ["src/*"] 27 | } 28 | }, 29 | "include": ["./src", "./types"], 30 | "exclude": ["dist", "node_modules"] 31 | } 32 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Taro & UnoCSS 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /config/plugin-mini-ci.js: -------------------------------------------------------------------------------- 1 | async function CIPluginFn() { 2 | // 可以在这里做一些异步事情, 比如请求接口获取配置 3 | /** 4 | * @typedef { import("@tarojs/plugin-mini-ci").CIOptions } CIOptions 5 | * @type {CIOptions} 6 | */ 7 | return { 8 | weapp: { 9 | appid: 'touristappid', 10 | privateKeyPath: '', 11 | // privateKeyPath: '密钥文件相对项目根目录的相对路径,例如 key/private.appid.key', 12 | }, 13 | tt: { 14 | email: '字节小程序邮箱', 15 | password: '字节小程序密码', 16 | }, 17 | alipay: { 18 | appid: '支付宝小程序appid', 19 | toolId: '工具id', 20 | privateKeyPath: '密钥文件相对项目根目录的相对路径,例如 key/pkcs8-private-pem', 21 | }, 22 | dd: { 23 | appid: '钉钉小程序appid,即钉钉开放平台后台应用管理的 MiniAppId 选项', 24 | token: '令牌,从钉钉后台获取', 25 | }, 26 | swan: { 27 | token: '鉴权需要的token令牌', 28 | }, 29 | // 版本号 30 | version: '1.0.0', 31 | // 版本发布描述 32 | desc: '版本描述', 33 | } 34 | } 35 | 36 | export default ['@tarojs/plugin-mini-ci', CIPluginFn] 37 | -------------------------------------------------------------------------------- /src/pages/index/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Taro-Unocss 2 | 3 | 一套使用 Taro + Vue3 + TypeScript 的初始化模板,在此基础上增加了一些配置好的库,方便快速进行开发。 4 | 5 | + taro: v3.6.6 6 | + webpack: v5.x 7 | 8 | ## 功能 9 | 10 | 自动引入 + Typescript 类型声明,可以非常方便的进行开发 11 | 12 | + [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import): 自动按需引入 Taro 所有API 13 | + [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components): 自动引入组件 14 | + [`unocss`](https://github.com/unocss/unocss): unocss 原子化 css 引擎 15 | + [`pinia`](https://github.com/vuejs/pinia): 状态管理 16 | + [`unocss - presetIcons`](https://github.com/unocss/unocss/tree/main/packages/preset-icons): 提供丰富的 SVG 图标,简单易用易扩展 17 | + [`vueuse/core`](https://github.com/vueuse/vueuse): 一组高效的 Composition API 集合 18 | 19 | > **注意事项** 20 | > 21 | > + 由于小程序限制,VueUse 和元素有关的 API 都不能使用,但是,部分和 Vue 相关的 API 可以使用 22 | > + 依赖升级可能会出现问题,出现问题请退回到现在的版本 23 | 24 | ## 文件结构 25 | 26 | + components: 公共组件 27 | + composables: 实用 API 集合 28 | + icons: 自定义图标 29 | + store: 状态管理 30 | 31 | ## 开发 32 | 33 | ```bash 34 | npx degit aliuq/mp-taro . 35 | pnpm install 36 | pnpm dev:weapp 37 | pnpm build:weapp 38 | ``` 39 | 40 | ## 感谢 41 | 42 | 感谢 [@antfu](https://github.com/antfu) 开源的 UnoCSS 项目以及其他的开源项目,让我们可以更加方便的进行开发。 43 | -------------------------------------------------------------------------------- /config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"', 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: { 9 | /** 10 | * WebpackChain 插件配置 11 | * @docs https://github.com/neutrinojs/webpack-chain 12 | */ 13 | // webpackChain (chain) { 14 | // /** 15 | // * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。 16 | // * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer 17 | // */ 18 | // chain.plugin('analyzer') 19 | // .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, []) 20 | 21 | // /** 22 | // * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。 23 | // * @docs https://github.com/chrisvfritz/prerender-spa-plugin 24 | // */ 25 | // const path = require('path') 26 | // const Prerender = require('prerender-spa-plugin') 27 | // const staticDir = path.join(__dirname, '..', 'dist') 28 | // chain 29 | // .plugin('prerender') 30 | // .use(new Prerender({ 31 | // staticDir, 32 | // routes: [ '/pages/index/index' ], 33 | // postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') }) 34 | // })) 35 | // } 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /uno.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, presetAttributify, presetIcons, presetTypography, presetUno, transformerDirectives, transformerVariantGroup } from 'unocss' 2 | 3 | import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders' 4 | import presetWeapp from 'unocss-preset-weapp' 5 | import { transformerAttributify, transformerClass } from 'unocss-preset-weapp/transformer' 6 | 7 | export default defineConfig({ 8 | shortcuts: [ 9 | { 10 | 'border-base': 'border-gray-200 dark:border-dark-200', 11 | 'bg-base': 'bg-white dark:bg-dark-100', 12 | 'color-base': 'text-gray-900 dark:text-gray-300', 13 | 'color-fade': 'text-gray-900:50 dark:text-gray-300:50', 14 | }, 15 | ], 16 | rules: [], 17 | presets: [ 18 | presetUno({ 19 | preflight: false, 20 | }), 21 | presetWeapp({ 22 | isH5: process.env.TARO_ENV === 'h5', 23 | platform: 'taro', 24 | taroWebpack: 'webpack5', 25 | whRpx: false, 26 | }), 27 | presetAttributify(), 28 | presetIcons({ 29 | collections: { 30 | carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default), 31 | mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default), 32 | my: FileSystemIconLoader( 33 | './src/icons', 34 | svg => svg.replace(/#fff/, 'currentColor'), 35 | ), 36 | }, 37 | scale: 1.2, 38 | warn: true, 39 | }), 40 | presetTypography(), 41 | ], 42 | transformers: [ 43 | transformerDirectives(), 44 | transformerVariantGroup(), 45 | transformerAttributify(), 46 | transformerClass(), 47 | ], 48 | }) 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "taro-unocss", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "A Taro + Vue3 + Typescript template with unocss and auto import", 6 | "templateInfo": { 7 | "name": "default", 8 | "typescript": true, 9 | "css": "none" 10 | }, 11 | "author": "", 12 | "scripts": { 13 | "build:weapp": "taro build --type weapp", 14 | "build:swan": "taro build --type swan", 15 | "build:alipay": "taro build --type alipay", 16 | "build:tt": "taro build --type tt", 17 | "build:h5": "taro build --type h5", 18 | "build:rn": "taro build --type rn", 19 | "build:qq": "taro build --type qq", 20 | "build:jd": "taro build --type jd", 21 | "build:quickapp": "taro build --type quickapp", 22 | "dev:weapp": "npm run build:weapp -- --watch", 23 | "dev:swan": "npm run build:swan -- --watch", 24 | "dev:alipay": "npm run build:alipay -- --watch", 25 | "dev:tt": "npm run build:tt -- --watch", 26 | "dev:h5": "npm run build:h5 -- --watch", 27 | "dev:rn": "npm run build:rn -- --watch", 28 | "dev:qq": "npm run build:qq -- --watch", 29 | "dev:jd": "npm run build:jd -- --watch", 30 | "dev:quickapp": "npm run build:quickapp -- --watch", 31 | "lint": "eslint .", 32 | "lint:fix": "npm run lint --fix", 33 | "pre:gen-taro-api": "npx tsx config/module/TaroResolver.ts" 34 | }, 35 | "browserslist": [ 36 | "last 3 versions", 37 | "Android >= 4.1", 38 | "ios >= 8" 39 | ], 40 | "dependencies": { 41 | "@babel/runtime": "^7.21.5", 42 | "@tarojs/components": "3.6.6", 43 | "@tarojs/plugin-framework-vue3": "3.6.6", 44 | "@tarojs/plugin-http": "^3.6.6", 45 | "@tarojs/plugin-platform-h5": "^3.6.6", 46 | "@tarojs/plugin-platform-weapp": "^3.6.6", 47 | "@tarojs/runtime": "3.6.6", 48 | "@tarojs/taro": "3.6.6", 49 | "@vueuse/core": "^10.1.2", 50 | "axios": "^1.4.0", 51 | "pinia": "^2.0.36", 52 | "vue": "^3.3.2" 53 | }, 54 | "devDependencies": { 55 | "@antfu/eslint-config": "^0.38.6", 56 | "@babel/core": "^7.21.8", 57 | "@iconify-json/carbon": "^1.1.16", 58 | "@iconify-json/mdi": "^1.1.52", 59 | "@tarojs/plugin-html": "3.6.6", 60 | "@tarojs/plugin-mini-ci": "^3.6.6", 61 | "@tarojs/webpack5-runner": "3.6.6", 62 | "@types/node": "^20.1.5", 63 | "@types/webpack-env": "^1.18.0", 64 | "@unocss/webpack": "^0.51.13", 65 | "@vue/babel-plugin-jsx": "^1.1.1", 66 | "@vue/compiler-sfc": "^3.3.2", 67 | "babel-preset-taro": "3.6.6", 68 | "eslint": "^8.40.0", 69 | "local-pkg": "^0.4.3", 70 | "stylelint": "^15.6.1", 71 | "typescript": "^5.0.4", 72 | "unocss": "^0.51.13", 73 | "unocss-preset-weapp": "^0.6.3", 74 | "unplugin-auto-import": "^0.16.0", 75 | "unplugin-vue-components": "^0.24.1", 76 | "vue-loader": "^17.1.1", 77 | "webpack": "^5.82.1" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /config/module/keywords.ts: -------------------------------------------------------------------------------- 1 | export const reservedKeywords = [ 2 | 'abstract', 3 | 'arguments', 4 | 'boolean', 5 | 'break', 6 | 'byte', 7 | 'case', 8 | 'catch', 9 | 'char', 10 | 'class', 11 | 'const', 12 | 'continue', 13 | 'debugger', 14 | 'default', 15 | 'delete', 16 | 'do', 17 | 'double', 18 | 'else', 19 | 'enum', 20 | 'eval', 21 | 'export', 22 | 'extends', 23 | 'false', 24 | 'final', 25 | 'finally', 26 | 'float', 27 | 'for', 28 | 'function', 29 | 'goto', 30 | 'if', 31 | 'implements', 32 | 'import', 33 | 'in', 34 | 'instanceof', 35 | 'int', 36 | 'interface', 37 | 'let', 38 | 'long', 39 | 'native', 40 | 'new', 41 | 'null', 42 | 'package', 43 | 'private', 44 | 'protected', 45 | 'public', 46 | 'return', 47 | 'short', 48 | 'static', 49 | 'super', 50 | 'switch', 51 | 'synchronized', 52 | 'this', 53 | 'throw', 54 | 'throws', 55 | 'transient', 56 | 'true', 57 | 'try', 58 | 'typeof', 59 | 'var', 60 | 'void', 61 | 'volatile', 62 | 'while', 63 | 'with', 64 | 'yield,', 65 | 'Array', 66 | 'Date', 67 | 'eval', 68 | 'function', 69 | 'hasOwnProperty', 70 | 'Infinity', 71 | 'isFinite', 72 | 'isNaN', 73 | 'isPrototypeOf', 74 | 'length', 75 | 'Math', 76 | 'NaN', 77 | 'name', 78 | 'Number', 79 | 'Object', 80 | 'prototype', 81 | 'String', 82 | 'toString', 83 | 'undefined', 84 | 'valueOf', 85 | 'alert', 86 | 'all', 87 | 'anchor', 88 | 'anchors', 89 | 'area', 90 | 'assign', 91 | 'blur', 92 | 'button', 93 | 'checkbox', 94 | 'clearInterval', 95 | 'clearTimeout', 96 | 'clientInformation', 97 | 'close', 98 | 'closed', 99 | 'confirm', 100 | 'constructor', 101 | 'crypto', 102 | 'decodeURI', 103 | 'decodeURIComponent', 104 | 'defaultStatus', 105 | 'document', 106 | 'element', 107 | 'elements', 108 | 'embed', 109 | 'embeds', 110 | 'encodeURI', 111 | 'encodeURIComponent', 112 | 'escape', 113 | 'event', 114 | 'fileUpload', 115 | 'focus', 116 | 'form', 117 | 'forms', 118 | 'frame', 119 | 'innerHeight', 120 | 'innerWidth', 121 | 'layer', 122 | 'layers', 123 | 'link', 124 | 'location', 125 | 'mimeTypes', 126 | 'navigate', 127 | 'navigator', 128 | 'frames', 129 | 'frameRate', 130 | 'hidden', 131 | 'history', 132 | 'image', 133 | 'images', 134 | 'offscreenBuffering', 135 | 'open', 136 | 'opener', 137 | 'option', 138 | 'outerHeight', 139 | 'outerWidth', 140 | 'packages', 141 | 'pageXOffset', 142 | 'pageYOffset', 143 | 'parent', 144 | 'parseFloat', 145 | 'parseInt', 146 | 'password', 147 | 'pkcs11', 148 | 'plugin', 149 | 'prompt', 150 | 'propertyIsEnum', 151 | 'radio', 152 | 'reset', 153 | 'screenX', 154 | 'screenY', 155 | 'scroll', 156 | 'secure', 157 | 'select', 158 | 'self', 159 | 'setInterval', 160 | 'setTimeout', 161 | 'status', 162 | 'submit', 163 | 'taint', 164 | 'text', 165 | 'textarea', 166 | 'top', 167 | 'unescape', 168 | 'untaint', 169 | 'window', 170 | 'onblur', 171 | 'onclick', 172 | 'onerror', 173 | 'onfocus', 174 | 'onkeydown', 175 | 'onkeypress', 176 | 'onkeyup', 177 | 'onmouseover', 178 | 'onload', 179 | 'onmouseup', 180 | 'onmousedown', 181 | 'onsubmit', 182 | ] 183 | -------------------------------------------------------------------------------- /config/module/TaroResolver.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import path from 'node:path' 3 | import { resolveModule } from 'local-pkg' 4 | import type { ImportNameAlias, ImportsMap } from 'unplugin-auto-import/types' 5 | import { reservedKeywords } from './keywords' 6 | 7 | const cachePath = './config/module/taro-apis.json' 8 | 9 | // generateApis() 10 | function generateApis() { 11 | const exclude = [ 12 | 'fail', 'success', 'complete', 'reject', 'resolve', 13 | ...reservedKeywords, 14 | ] 15 | const conflicts: Record = { 16 | nextTick: 'taroNextTick', 17 | getCurrentInstance: 'taroGetCurrentInstance', 18 | } 19 | 20 | const dir = resolveModule('@tarojs/taro') 21 | if (!dir) { 22 | console.error('\n[auto-import] Not found package `@tarojs/taro`, have you installed it?') 23 | console.error('see more https://github.com/NervJS/taro') 24 | return 25 | } 26 | 27 | try { 28 | const typesDir = `${path.dirname(dir) + path.sep}types` 29 | let maps: Array = [] 30 | 31 | const filesList: string[] = readFiles(typesDir) 32 | 33 | for (const file of filesList) { 34 | if (file.includes('taro.extend.d.ts')) 35 | continue 36 | 37 | const pContent = fs.readFileSync(file, 'utf-8') 38 | const match = pContent.match(/(interface TaroStatic \{(.|\n)*\})/) || [] 39 | const content = match[0] 40 | const reg = /(?<=\s{4})(?\w+)(?=(\s?\()|\<)/g 41 | 42 | if (!content) 43 | continue 44 | 45 | const funcs: Array = (content.match(reg) || []) 46 | .filter(fun => !exclude.includes(fun)) 47 | .map((fun: string) => conflicts[fun] ? [fun, conflicts[fun]] : fun) 48 | 49 | maps = maps.concat(funcs) 50 | } 51 | 52 | maps = [ 53 | 'getEnv', 54 | ['getCurrentInstance', 'taroGetCurrentInstance'], 55 | ...Array.from(new Set(maps)), 56 | ] as ImportNameAlias[] 57 | 58 | // fs.writeFileSync('./config/module/taro-apis.json', JSON.stringify(maps, null, 2)) 59 | return maps 60 | } 61 | catch (err: any) { 62 | console.error( 63 | 'Some errors have occurred, ' 64 | + 'please report an issue at https://github.com/antfu/unplugin-auto-import/issues/new?' 65 | + `title=${encodeURIComponent('[Taro] Failed generate apis')}&body=${encodeURIComponent(err?.message)}`, 66 | ) 67 | console.error(err) 68 | } 69 | } 70 | 71 | function readFiles(dir: string, filesList: string[] = []) { 72 | const files = fs.readdirSync(dir) 73 | 74 | for (const file of files) { 75 | const filePath = path.resolve(dir, file) 76 | const stat = fs.statSync(filePath) 77 | if (stat.isDirectory()) 78 | readFiles(filePath, filesList) 79 | 80 | else 81 | filesList.push(filePath) 82 | } 83 | 84 | return filesList 85 | } 86 | 87 | export default function (): ImportsMap { 88 | let jsonAPIs: (string | ImportNameAlias)[] = [] 89 | if (fs.existsSync(cachePath)) { 90 | jsonAPIs = JSON.parse(fs.readFileSync(cachePath, 'utf-8')) 91 | } 92 | else { 93 | jsonAPIs = generateApis() || [] 94 | jsonAPIs.length && fs.writeFileSync(cachePath, JSON.stringify(jsonAPIs, null, 2)) 95 | } 96 | 97 | return { 98 | '@tarojs/taro': jsonAPIs, 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import AutoImport from 'unplugin-auto-import/webpack' 3 | import Components from 'unplugin-vue-components/webpack' 4 | import UnoCSS from '@unocss/webpack' 5 | import TaroResolver from './module/TaroResolver' 6 | 7 | const r = p => path.resolve(__dirname, '..', p) 8 | 9 | const isDev = process.env.NODE_ENV === 'development' 10 | 11 | function webpackChain(chain) { 12 | // 添加自动引入 13 | // https://github.com/antfu/unplugin-auto-import 14 | chain.plugin('unplugin-auto-import').use(AutoImport({ 15 | imports: [ 16 | 'vue', 17 | // 注意: 针对可能出现的 `$` 和 `$$`,手动排除 18 | // https://vuejs.org/guide/extras/reactivity-transform.html#refs-vs-reactive-variables 19 | { 20 | 'vue/macros': ['$ref', '$shallowRef', '$toRef', '$customRef', '$computed'], 21 | }, 22 | TaroResolver(), 23 | ], 24 | dts: 'src/auto-imports.d.ts', 25 | dirs: [ 26 | 'src/composables', 27 | 'src/store', 28 | ], 29 | vueTemplate: true, 30 | eslintrc: { 31 | enabled: true, 32 | filepath: 'src/.eslintrc-auto-import.json', 33 | globalsPropValue: true, 34 | }, 35 | })) 36 | 37 | // 添加组件按需引入, 自动引入 `src/components` 目录下的组件 38 | // https://github.com/antfu/unplugin-vue-components 39 | chain.plugin('unplugin-vue-components').use(Components({ 40 | dts: 'src/components.d.ts', 41 | dirs: ['src/components', 'src/layouts'], 42 | resolvers: [], 43 | types: [{ 44 | from: '@tarojs/components', 45 | names: [ 46 | 'Ad', 'AdCustom', 'AnimationVideo', 'AnimationView', 'ArCamera', 'Audio', 'AwemeData', 'Block', 'Button', 'Camera', 'Canvas', 'ChannelLive', 'ChannelVideo', 'Checkbox', 'CheckboxGroup', 'CommentDetail', 'CommentList', 'ContactButton', 'CoverImage', 'CoverView', 'CustomWrapper', 'Editor', 'FollowSwan', 'Form', 'FunctionalPageNavigator', 'GridView', 'Icon', 'Image', 'InlinePaymentPanel', 'Input', 'KeyboardAccessory', 'Label', 'Lifestyle', 'Like', 'ListView', 'LivePlayer', 'LivePusher', 'Login', 'Lottie', 'Map', 'MatchMedia', 'MovableArea', 'MovableView', 'NativeSlot', 'NavigationBar', 'Navigator', 'OfficialAccount', 'OpenData', 'PageContainer', 'PageMeta', 'Picker', 'PickerGroup', 'PickerView', 'PickerViewColumn', 'Progress', 'PullToRefresh', 'Radio', 'RadioGroup', 'RichText', 'RootPortal', 'RtcRoom', 'RtcRoomItem', 'ScrollView', 'ShareElement', 'Slider', 'Slot', 'StickyHeader', 'StickySection', 'Swiper', 'SwiperItem', 'Switch', 'TabItem', 'Tabbar', 'Tabs', 'Text', 'Textarea', 'Video', 'VideoControl', 'VideoDanmu', 'View', 'VoipRoom', 'WebView', 47 | ], 48 | }], 49 | })) 50 | 51 | // 添加 unocss 支持 52 | // https://github.com/unocss/unocss 53 | chain.plugin('unocss').use(UnoCSS()) 54 | 55 | // 支持 mjs 模块 56 | chain.merge({ 57 | module: { 58 | rule: { 59 | mjs: { 60 | test: /\.mjs$/, 61 | include: [/node_modules/], 62 | type: 'javascript/auto', 63 | }, 64 | }, 65 | }, 66 | }) 67 | } 68 | /** @type {import('@tarojs/taro/types/compile').IProjectConfig} */ 69 | const config = { 70 | projectName: 'Taro & UnoCSS', 71 | date: '2022-6-7', 72 | designWidth: 750, 73 | deviceRatio: { 74 | 640: 2.34 / 2, 75 | 750: 1, 76 | 828: 1.81 / 2, 77 | }, 78 | sourceRoot: 'src', 79 | outputRoot: `dist/${process.env.TARO_ENV}`, 80 | plugins: [ 81 | '@tarojs/plugin-html', 82 | '@tarojs/plugin-http', 83 | ['@tarojs/plugin-framework-vue3', { 84 | vueLoaderOption: { 85 | // 添加 vue-macros 支持 86 | reactivityTransform: true, // 开启vue3响应性语法糖 87 | }, 88 | }], 89 | // r('config/module/TimePlugin'), 90 | ], 91 | // jsMinimizer: 'terser', 92 | defineConstants: { 93 | }, 94 | copy: { 95 | patterns: [], 96 | options: {}, 97 | }, 98 | alias: { 99 | '~': r('src'), 100 | '@': r('src'), 101 | }, 102 | framework: 'vue3', 103 | compiler: { 104 | type: 'webpack5', 105 | prebundle: { 106 | timings: true, 107 | }, 108 | }, 109 | cache: { 110 | enable: false, // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache 111 | }, 112 | logger: { 113 | stats: true, 114 | }, 115 | mini: { 116 | webpackChain, 117 | hot: true, 118 | // minifyXML: { 119 | // collapseWhitespace: true, 120 | // }, 121 | // prerender: { 122 | // match: 'pages/*/**', // 所有以 `pages/shop/` 开头的页面都参与 prerender 123 | // console: true, // 在 prerender 过程中 console 打印语句是否执行 124 | // }, 125 | postcss: { 126 | // 可以进行 autoprefixer 的配置。配置项参考官方文档 https://github.com/postcss/autoprefixer 127 | // autoprefixer: { 128 | // enable: true, 129 | // config: { 130 | // // autoprefixer 配置项 131 | // }, 132 | // }, 133 | pxtransform: { 134 | enable: true, 135 | config: { 136 | 137 | }, 138 | }, 139 | url: { 140 | enable: true, 141 | config: { 142 | limit: 1024, // 设定转换尺寸上限 143 | maxSize: 10, // 设定转换尺寸上限(单位:kbytes) 144 | }, 145 | }, 146 | cssModules: { 147 | enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true 148 | config: { 149 | namingPattern: 'module', // 转换模式,取值为 global/module 150 | generateScopedName: '[name]__[local]___[hash:base64:5]', 151 | }, 152 | }, 153 | }, 154 | }, 155 | h5: { 156 | publicPath: '/', 157 | staticDirectory: 'static', 158 | webpackChain, 159 | postcss: { 160 | autoprefixer: { 161 | enable: true, 162 | config: { 163 | }, 164 | }, 165 | cssModules: { 166 | enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true 167 | config: { 168 | namingPattern: 'module', // 转换模式,取值为 global/module 169 | generateScopedName: '[name]__[local]___[hash:base64:5]', 170 | }, 171 | }, 172 | }, 173 | }, 174 | } 175 | 176 | module.exports = function (merge) { 177 | if (isDev) 178 | return merge({}, config, require('./dev')) 179 | 180 | return merge({}, config, require('./prod')) 181 | } 182 | --------------------------------------------------------------------------------