在开发微信小程序时,发现使用webpack可以自动识别使用定制的custom-tab-bar,而使用vite则不能走定制的现象。这是在 微信小程序 里,custom-tab-bar
是否能生效,并不是框架层(React / Vue / Taro / ...)直接决定的,而是 编译工具链对小程序配置的支持程度 不一样导致的。
一、custom-tab-bar问题
这是常见的app.config.ts的配置,导航栏样式和tabBar都是走的定制化。
javascript
export default defineAppConfig({
pages: ['pages/index/index', 'pages/about/index'],
subPackages: [
{
root: 'subpackages/login',
pages: ['index']
}
],
window: {
navigationStyle: 'custom'
// backgroundTextStyle: 'light',
// navigationBarBackgroundColor: '#fff',
// navigationBarTitleText: 'WeChat',
// navigationBarTextStyle: 'black'
},
tabBar: {
custom: true,
color: '#333',
selectedColor: '#058fae',
list: [
{
pagePath: 'pages/index/index',
text: '首页',
iconPath: 'assets/images/tabBar/icon1.png',
selectedIconPath: 'assets/images/tabBar/icon1-active.png'
},
{
pagePath: 'pages/about/index',
text: '关于',
iconPath: 'assets/images/tabBar/icon2.png',
selectedIconPath: 'assets/images/tabBar/icon2-active.png'
}
]
},
usingComponents: {},
lazyCodeLoading: 'requiredComponents'
});
1. Webpack 场景
像 Taro + Webpack 这样的方案,官方在构建时会把 app.json
里的
javascript
"tabBar": {
"custom": true,
"list": [...]
}
以及 custom-tab-bar
目录下的代码一并编译进产物,微信小程序就能识别并使用自定义 tab bar。
2. Vite 场景
目前(尤其是 Taro Vite 模式),Vite 插件对小程序 非页面/组件目录 的处理不完整:
-
custom-tab-bar
目录不会被默认打包 -
导致运行时找不到
custom-tab-bar/index
,从而退回使用原生 tab bar
所以表现就是:Webpack 能跑,Vite 不能跑。
3. 解决方案
如果要在 Vite 模式下使用自定义 tabbar ,需要额外配置。完整的 vite.config.ts
示例 ,包含了 custom-tab-bar
的处理配置。这样在 Vite 模式 下打包时,会自动把 src/custom-tab-bar
目录复制到小程序 dist
目录中,微信就能正常识别自定义 tabbar。(注意custom-tab-bar文件位置一定是在src下和page同级,这是官网定义的)
javascript
import { defineConfig } from 'vite'
import { viteStaticCopy } from 'vite-plugin-static-copy'
export default defineConfig({
plugins: [
viteStaticCopy({
targets: [
{
src: 'src/custom-tab-bar', // custom-tab-bar 源目录
dest: '' // 复制到 dist/custom-tab-bar
}
]
})
],
build: {
outDir: 'dist', // 小程序编译输出目录
emptyOutDir: true
}
})
二、推荐使用京东NutUI-React Taro开发小程序(推荐方式一,简单方便)
官网步骤:NutUI-React Taro
安装 Taro 脚手架
bash
# pnpm
pnpm install -g @tarojs/cli
# npm
npm install -g @tarojs/cli
# yarn
yarn global add @tarojs/cli
方式一:使用 Taro 内置的 NutUI 模板快速创建项目
1、使用命令创建 Taro 项目:
taro init
2、参考下方操作,选择 NutUI React 模板
👽 Taro
Taro 即将创建一个新项目!
Need help? Go and open issue: https://tls.jd.com/taro-issue-helper
? 请输入项目名称! MyProject
? 请输入项目介绍
? 请选择框架 React
? 是否需要使用 TypeScript ? Yes
? 请选择 CSS 预处理器(Sass/Less/Stylus) Sass
? 请选择编译工具 Webpack5
? 请选择包管理工具 pnpm
? 请选择模板源 Github(最新)
✔ 拉取远程模板仓库成功!
默认模板
harmony
mobx
pwa
❯ react-NutUI(使用 NutUI React 的模板)
react-native
......
方式二:在已有 Taro 项目中引入 NutUI React
1、安装 NutUI React
# pnpm
pnpm add @nutui/nutui-react-taro
# npm
npm i @nutui/nutui-react-taro
# yarn
yarn add @nutui/nutui-react-taro
2、Taro 相关配置
注意,这里安装的版本 version 必须与项目中 Taro 版本保持一致!
# pnpm
pnpm add @tarojs/plugin-html@version
# yarn
yarn add @tarojs/plugin-html@version
# npm
npm i @tarojs/plugin-html@version
在项目中配置
javascript
// config/index.js
config = {
// 开启 HTML 插件
plugins: ['@tarojs/plugin-html'],
designWidth(input) {
// 配置 NutUI 375 尺寸
if (input?.file?.replace(/\\+/g, '/').indexOf('@nutui') > -1) {
return 375
}
// 全局使用 Taro 默认的 750 尺寸
return 750
},
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2,
375: 2 / 1,
},
}
3、组件使用与按需引入
您可以选择全量引入样式文件:
javascript
// 默认主题
import '@nutui/nutui-react-taro/dist/style.css'
// 默认主题暗黑模式
// import '@nutui/nutui-react-taro/dist/style.css'
// JMAPP 主题
// import '@nutui/nutui-react-taro/dist/style-jmapp.css'
// JRKF 主题
// import '@nutui/nutui-react-taro/dist/style-jrkf.css'
3.1、通过插件实现按需引入
需要注意的是,在手动按需加载时,你还需要在入口文件中引入 global 类的文件来加载一些 NutUI React Taro 的全局性逻辑和样式:
javascript
// css 主题文件路径
// 默认主题
import '@nutui/nutui-react-taro/dist/styles/themes/default.css'
// 默认暗黑主题
// import '@nutui/nutui-react-taro/dist/styles/themes/default-dark.css'
// JMAPP 主题
// import '@nutui/nutui-react-taro/dist/styles/themes/jmapp.css'
// JRKF 主题
// import '@nutui/nutui-react-taro/dist/styles/themes/jrkf.css'
// scss 主题文件路径
// 默认主题
// import '@nutui/nutui-react-taro/dist/styles/theme-default.scss'
// 默认暗黑主题
// import '@nutui/nutui-react-taro/dist/styles/theme-dark.scss'
// JMAPP 主题
// import '@nutui/nutui-react-taro/dist/styles/theme-jmapp.scss'
// JRKF 主题
// import '@nutui/nutui-react-taro/dist/styles/theme-jrkf.scss'
首先安装 babel-plugin-import
插件
# pnpm
pnpm add babel-plugin-import
# npm
npm i babel-plugin-import
# yarn
yarn add babel-plugin-import
入口文件需要引入全局样式
javascript
// app.js
// css 主题文件路径
// 默认主题
import '@nutui/nutui-react-taro/dist/styles/themes/default.css'
// 默认暗黑主题
// import '@nutui/nutui-react-taro/dist/styles/themes/default-dark.css'
// JMAPP 主题
// import '@nutui/nutui-react-taro/dist/styles/themes/jmapp.css'
// JRKF 主题
// import '@nutui/nutui-react-taro/dist/styles/themes/jrkf.css'
// scss 主题文件路径
// 默认主题
// import '@nutui/nutui-react-taro/dist/styles/theme-default.scss'
// 默认暗黑主题
// import '@nutui/nutui-react-taro/dist/styles/theme-dark.scss'
// JMAPP 主题
// import '@nutui/nutui-react-taro/dist/styles/theme-jmapp.scss'
// JRKF 主题
// import '@nutui/nutui-react-taro/dist/styles/theme-jrkf.scss'
babel 相关配置:
javascript
// babel.config.js
module.exports = {
presets: [
// ...
],
plugins: [
[
'import',
{
libraryName: '@nutui/nutui-react-taro',
camel2DashComponentName: false,
customName: (name, file) => {
return `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}`
},
// 自动加载 scss 样式文件
customStyleName: (name) =>
`@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style`,
// 自动加载 css 样式文件
// customStyleName: (name) => `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style/css`
// JMAPP 主题
// 自动加载 scss 样式文件
// customStyleName: (name) => `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style-jmapp`,
// 自动加载 css 样式文件
// customStyleName: (name) => `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style-jmapp/css`
// jrkf 端主题
// 自动加载 scss 样式文件
// customStyleName: (name) => `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style-jrkf`,
// 自动加载 css 样式文件
// customStyleName: (name) => `@nutui/nutui-react-taro/dist/es/packages/${name.toLowerCase()}/style-jrkf/css`
},
'nutui-react',
],
],
}
若您的项目采用 scss,则需要在 config/index 中增加如下配置:
javascript
{
sass: {
data: '@import "@nutui/nutui-react-taro/dist/styles/variables.scss";'
// JMAPP 主题
// data: `@import '@nutui/nutui-react-taro/dist/styles/variables-jmapp.scss';`
// JRKF 主题
// data: `@import '@nutui/nutui-react-taro/dist/styles/variables-jrkf.scss';`
}
}
注意事项
1、检查 Taro 是否安装成功
taro -v
出现 Taro 版本号说明安装成功。
2、安装 Taro 过程中出现 Saas 相关错误
可以考虑安装 mirror-config-china
后重试。
npm install -g mirror-config-china
3、小程序项目运行时出现「找不到模板」的错误提示
解决方案:在 Taro 配置文件中关闭 prebundle 及 cache
javascript
// config/index.js
config = {
compiler: {
type: 'webpack5',
prebundle: {
exclude: ['@nutui/nutui-react-taro', '@nutui/icons-react-taro'],
},
},
cache: {
enable: false,
},
}
4、样式单位转化
组件 CSS 单位使用的是 px ,但是在 Taro
编译时,Taro 会帮你对样式做尺寸转换操作,需要注意的是,要对 NutUI 相关的样式设置在黑名单里,如:
javascript
// config/index.js
config = {
h5: {
postcss: {
pxtransform: {
enable: true,
// 包含 `nut-` 的类名选择器中的 px 单位不会被解析
config: { selectorBlackList: ['nut-'] },
},
},
},
}
三、总结
使用NutUI-React Taro,操作简单易上手,开发简洁快速。根据步骤即可,也不会出现custom-tab-bar不生效问题。选用的是webpack,scss和less可根据自己习惯选用那个。
-
Webpack 是官方长期维护的稳定方案,能自动识别
custom-tab-bar
。 -
Vite 模式下需要 手动处理
custom-tab-bar
的输出 或 升级 Taro 插件。