diff --git a/.cursor/skills/nutui-taro-weapp-wxss/SKILL.md b/.cursor/skills/nutui-taro-weapp-wxss/SKILL.md new file mode 100644 index 0000000000..4324ed7255 --- /dev/null +++ b/.cursor/skills/nutui-taro-weapp-wxss/SKILL.md @@ -0,0 +1,106 @@ +--- +name: nutui-taro-weapp-wxss +description: >- + NutUI React Taro 小程序 WXSS 编译超时修复:nutui-taro-demo 样式 bundle 合并、 + 删除无效 renderingMode、app-origin.wxss 体积治理。Use when 微信小程序报 + [ WXSS 文件编译错误] something must be wrong、wcsc timeout、app-origin.wxss + 过大、predev:taro 重写 app.config、或修改 generate-nutui-taro.js / + nutui.react.scss.taro.bundle.scss。 +--- + +# NutUI Taro 小程序 WXSS 编译治理 + +## 1. 背景与根因 + +**现象**:`[ WXSS 文件编译错误] something must be wrong` + `Error: timeout`;偶发 `无效的 app.json ["renderingMode"]`。 + +**根因**:`app.ts` → `nutui.react.scss.taro.ts` 曾 **100+ 条**独立 `import` 组件 scss;Taro `sass.resource` 向**每个**文件注入 `variables.scss` + `theme-default.scss`(含 base64 `@font-face`)。 + +| 指标 | 修复前 | 修复后(bundle) | +| --- | --- | --- | +| `app-origin.wxss` | ~4MB | ~0.3–0.9MB | +| `@font-face` 重复 | ~216 | ~2–10 | + +**不是**单个组件(如 `switch.scss`)的 bug,而是 **demo 全量样式打包方式** 导致。 + +**数据流(修复后)**: + +``` +app.ts → nutui.react.scss.taro.ts → nutui.react.scss.taro.bundle.scss + ├─ variables + theme(各 1 次) + └─ 全部组件 scss → dist/weapp/app-origin.wxss +``` + +--- + +## 2. 最小改动清单 + +| 文件 | 改动 | +| --- | --- | +| `scripts/taro/generate-nutui-taro.js` | 新增 `bundleScssStr`;遍历组件拼 `@import`;`nutui.react.scss.taro.ts` 改为单 import bundle;新增写 `nutui.react.scss.taro.bundle.scss` | +| `src/packages/nutui.react.scss.taro.bundle.scss` | variables/theme + 全部组件 `@import`(**自动生成,勿手改**) | +| `scripts/build-taro.mjs` | `buildCSS` / `buildHarmonyCSS` 的 glob 排除 `nutui.react.scss.taro.bundle.scss`,避免打进 npm 按组件发包 | +| `scripts/harmony/update-taro-entry.js` | 删除 `renderingMode: 'mixed'` | +| `scripts/taro/generate-taro-route.js` | 同上 | + +- `nutui.react.scss.ts`(H5)**不变**,`generate-nutui.js` 仍生成 100+ 条 JS import +- **勿只改** `app.config.ts`:`predev:taro` 会跑 `update-taro-entry.js` 覆盖 +- **不在最小集**:`config/index.js` minimize、各组件 scss calc 优化、`package.json` dev:weapp + +### 边界说明(H5 / 发包) + +| 场景 | 是否走 bundle | 说明 | +| --- | --- | --- | +| H5 文档站 `sites/mobile` + `nutui.react.scss.ts` | 否 | Vite `additionalData` 只注入 variables,theme 在 `main.tsx` 单独 import 一次,无 wcsc 超时问题 | +| Taro demo `dev:taro`(weapp / h5) | 是 | `app.ts` → `nutui.react.scss.taro.ts` → bundle | +| Taro 发包 `build:taro` | 否 | bundle 被 glob exclude;构建结束会删除 `nutui.react.scss.js`;业务方仍 `import '@nutui/nutui-react-taro/dist/es/packages/xxx/style'` | + +--- + +## 3. 解决 / 好处 / 影响 + +**解决**:WXSS 超时;无效 `renderingMode` 警告;demo 可预览(需登录开发者工具 + 清缓存)。 + +**好处**:样式单入口;不改 `build:taro` 发包;新增组件仍由 `generate-nutui-taro.js` 写入 bundle。 + +| 命令 | 影响 | +| --- | --- | +| `dev:taro weapp` | 有 | +| `build:taro` / `build:taro:demo` | 无(bundle 已在 `build-taro.mjs` glob 中排除) | +| `prepare` / `generate:file:taro` | 有(再生 bundle) | +| `VITE_APP_PROJECT_ID=jmapp` | bundle 写死 default 主题,需另行验证 | + +**已知限制**:`build:weapp` 生产压缩时 postcss-calc 可能破坏嵌套 `var+calc`(dev 无此问题);游客模式 `webapi_getwxaasyncsecinfo:fail` 为环境问题。 + +--- + +## 4. 验证 + +```bash +pnpm run dev:taro weapp +wc -c packages/nutui-taro-demo/dist/weapp/app-origin.wxss +grep -c '@font-face' packages/nutui-taro-demo/dist/weapp/app-origin.wxss +``` + +期望:体积远小于 4MB;`@font-face` 为个位数。 + +--- + +## 5. 未采纳方案(备查) + +| 方案 | 未采纳原因 | +| --- | --- | +| 各组件 scss 局部 CSS 变量 | 非主因,扩大 diff | +| `config/index.js` minimize(false) | dev 不需要 | +| `webpackImporter: false` | 引发 Module not found | +| sass.resource 置空 | 嵌套 @import(popup→overlay)缺变量 | +| 手改 app.config.ts | predev:taro 会覆盖 | + +--- + +## 6. Agent 自检 + +- [ ] 只改生成脚本 + bundle + `build-taro.mjs` exclude,未扩大组件 scss diff? +- [ ] `build-taro.mjs` 已排除 `nutui.react.scss.taro.bundle.scss`? +- [ ] 两个生成脚本已去掉 `renderingMode`? +- [ ] 仍超时:查 `app-origin.wxss` 体积、游客模式、是否未重新 dev diff --git a/scripts/build-taro.mjs b/scripts/build-taro.mjs index 4380c57b82..bf7446d930 100644 --- a/scripts/build-taro.mjs +++ b/scripts/build-taro.mjs @@ -348,7 +348,11 @@ async function copyStyles() { // 构建样式 async function buildCSS(themeName = '') { const componentScssFiles = await glob(['src/packages/**/*.scss'], { - ignore: ['src/packages/**/demo.scss'], + ignore: [ + 'src/packages/**/demo.scss', + // demo 专用全量 bundle,不参与 npm 按组件发包 + 'src/packages/nutui.react.scss.taro.bundle.scss', + ], }) const variables = await readFile( @@ -438,7 +442,10 @@ async function buildCSS(themeName = '') { // 构建样式 async function buildHarmonyCSS(themeName = '') { const componentScssFiles = await glob(['src/packages/**/*.scss'], { - ignore: ['src/packages/**/demo.scss'], + ignore: [ + 'src/packages/**/demo.scss', + 'src/packages/nutui.react.scss.taro.bundle.scss', + ], }) const variables = await readFile( diff --git a/scripts/build.mjs b/scripts/build.mjs index 91a7b71bc4..02805d4e1a 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -297,7 +297,11 @@ async function copyStyles() { // 构建样式 async function buildCSS(themeName = '') { const componentScssFiles = await glob(['src/packages/**/*.scss'], { - ignore: ['src/packages/**/demo.scss'], + ignore: [ + 'src/packages/**/demo.scss', + // Taro demo 专用全量 bundle,不参与 H5 npm 按组件发包 + 'src/packages/nutui.react.scss.taro.bundle.scss', + ], }) const variables = await readFile( diff --git a/scripts/harmony/update-taro-entry.js b/scripts/harmony/update-taro-entry.js index 88a92e77aa..540c0fef21 100644 --- a/scripts/harmony/update-taro-entry.js +++ b/scripts/harmony/update-taro-entry.js @@ -72,7 +72,6 @@ export default defineAppConfig({ navigationBarTitleText: 'NutUI-React', navigationBarTextStyle: 'black' }, - renderingMode: 'mixed', components: ['pages/index/index', ...(subPackages.map(subPackage => { return subPackage.pages.map(page => \`\${subPackage.root}/\${page}\`) }).flat())] diff --git a/scripts/taro/generate-nutui-taro.js b/scripts/taro/generate-nutui-taro.js index 9cb481ad19..2480d3da11 100644 --- a/scripts/taro/generate-nutui-taro.js +++ b/scripts/taro/generate-nutui-taro.js @@ -7,6 +7,7 @@ let importStr = `` let importRNStr = `` let importMarkdownStr = `` let importScssStr = `\n` +let bundleScssStr = `@import '../styles/variables.scss';\n@import '../styles/theme-default.scss';\n` const packages = [] const mds = [] const raws = [] @@ -21,6 +22,7 @@ config.nav.map((item) => { importRNStr += `import ${name} from '@/packages/${name.toLowerCase()}/index.${rn?'rn':'taro'}'\n` importRNStr += `export * from '@/packages/${name.toLowerCase()}/index.${rn?'rn':'taro'}'\n` importScssStr += `import '@/packages/${name.toLowerCase()}/${name.toLowerCase()}.scss'\n` + bundleScssStr += `@import './${name.toLowerCase()}/${name.toLowerCase()}.scss';\n` packages.push(name) glob @@ -99,8 +101,7 @@ fs.outputFile( // } // ) -let taroScssfileStr = ` -${importScssStr} +let taroScssfileStr = `import './nutui.react.scss.taro.bundle.scss' export default { "NutUI":"NutUI-Taro" };` fs.outputFile( path.resolve(__dirname, '../../src/packages/nutui.react.scss.taro.ts'), @@ -111,6 +112,15 @@ fs.outputFile( } ) +fs.outputFile( + path.resolve(__dirname, '../../src/packages/nutui.react.scss.taro.bundle.scss'), + bundleScssStr, + 'utf8', + (error) => { + if (error) throw error + } +) + fs.outputFile( path.resolve(__dirname, '../../src/packages/nutui.react.scss.ts'), importScssStr, diff --git a/scripts/taro/generate-taro-route.js b/scripts/taro/generate-taro-route.js index a695e0979f..6d45e68bfe 100644 --- a/scripts/taro/generate-taro-route.js +++ b/scripts/taro/generate-taro-route.js @@ -42,7 +42,6 @@ export default defineAppConfig ({ navigationBarTitleText: 'NutUI-React', navigationBarTextStyle: 'black' }, - renderingMode: 'mixed', components: ['pages/index/index', ...(subPackages.map(subPackage => { return subPackage.pages.map(page => \`\${subPackage.root}/\${page}\`) }).flat())] diff --git a/src/packages/configprovider/types.ts b/src/packages/configprovider/types.ts index baa2d926a6..a24463de94 100644 --- a/src/packages/configprovider/types.ts +++ b/src/packages/configprovider/types.ts @@ -706,6 +706,13 @@ export type NutCSSVariables = | 'nutuiIndicatorDotActiveSize' | 'nutuiIndicatorBorderRadius' | 'nutuiIndicatorDotMargin' + | 'nutuiIndicatorDotBorder' + | 'nutuiIndicatorDotInactiveColor' + | 'nutuiIndicatorTrackWidth' + | 'nutuiIndicatorSliderWidth' + | 'nutuiIndicatorDualScreenInactiveWidth' + | 'nutuiIndicatorPlacementGap' + | 'nutuiIndicatorPlacementSafeGap' | 'nutuiMenuScrollFixedTop' | 'nutuiMenuScrollFixedZIndex' | 'nutuiMenuBarLineHeight' @@ -941,6 +948,8 @@ export type NutCSSVariables = | 'nutuiToastTitleFontWeight' | 'nutuiToastIconColor' | 'nutuiSafeAreaMultiple' + | 'nutuiIndicatorCurrent' + | 'nutuiIndicatorTotal' | 'nutuiButtonDisabledBackgroundColor' | 'nutuiBlack3' | 'nutuiBlack1' diff --git a/src/packages/nutui.react.scss.taro.bundle.scss b/src/packages/nutui.react.scss.taro.bundle.scss new file mode 100644 index 0000000000..839d068077 --- /dev/null +++ b/src/packages/nutui.react.scss.taro.bundle.scss @@ -0,0 +1,107 @@ +@import '../styles/variables.scss'; +@import '../styles/theme-default.scss'; +@import './button/button.scss'; +@import './cell/cell.scss'; +@import './cellgroup/cellgroup.scss'; +@import './configprovider/configprovider.scss'; +@import './image/image.scss'; +@import './overlay/overlay.scss'; +@import './divider/divider.scss'; +@import './grid/grid.scss'; +@import './griditem/griditem.scss'; +@import './layout/layout.scss'; +@import './col/col.scss'; +@import './row/row.scss'; +@import './safearea/safearea.scss'; +@import './space/space.scss'; +@import './sticky/sticky.scss'; +@import './backtop/backtop.scss'; +@import './elevator/elevator.scss'; +@import './fixednav/fixednav.scss'; +@import './hoverbutton/hoverbutton.scss'; +@import './hoverbuttonitem/hoverbuttonitem.scss'; +@import './navbar/navbar.scss'; +@import './sidebar/sidebar.scss'; +@import './sidebaritem/sidebaritem.scss'; +@import './tabbar/tabbar.scss'; +@import './tabbaritem/tabbaritem.scss'; +@import './tabpane/tabpane.scss'; +@import './tabs/tabs.scss'; +@import './address/address.scss'; +@import './calendar/calendar.scss'; +@import './calendaritem/calendaritem.scss'; +@import './calendarcard/calendarcard.scss'; +@import './cascader/cascader.scss'; +@import './checkbox/checkbox.scss'; +@import './checkboxgroup/checkboxgroup.scss'; +@import './datepicker/datepicker.scss'; +@import './datepickerview/datepickerview.scss'; +@import './form/form.scss'; +@import './formitem/formitem.scss'; +@import './input/input.scss'; +@import './inputnumber/inputnumber.scss'; +@import './menu/menu.scss'; +@import './menuitem/menuitem.scss'; +@import './numberkeyboard/numberkeyboard.scss'; +@import './picker/picker.scss'; +@import './pickerview/pickerview.scss'; +@import './radio/radio.scss'; +@import './radiogroup/radiogroup.scss'; +@import './range/range.scss'; +@import './rate/rate.scss'; +@import './searchbar/searchbar.scss'; +@import './shortpassword/shortpassword.scss'; +@import './signature/signature.scss'; +@import './switch/switch.scss'; +@import './textarea/textarea.scss'; +@import './uploader/uploader.scss'; +@import './actionsheet/actionsheet.scss'; +@import './badge/badge.scss'; +@import './dialog/dialog.scss'; +@import './drag/drag.scss'; +@import './empty/empty.scss'; +@import './infiniteloading/infiniteloading.scss'; +@import './loading/loading.scss'; +@import './noticebar/noticebar.scss'; +@import './notify/notify.scss'; +@import './popover/popover.scss'; +@import './popup/popup.scss'; +@import './pulltorefresh/pulltorefresh.scss'; +@import './resultpage/resultpage.scss'; +@import './skeleton/skeleton.scss'; +@import './swipe/swipe.scss'; +@import './toast/toast.scss'; +@import './animate/animate.scss'; +@import './animatingnumbers/animatingnumbers.scss'; +@import './audio/audio.scss'; +@import './avatar/avatar.scss'; +@import './avatargroup/avatargroup.scss'; +@import './circleprogress/circleprogress.scss'; +@import './collapse/collapse.scss'; +@import './collapseitem/collapseitem.scss'; +@import './countdown/countdown.scss'; +@import './ellipsis/ellipsis.scss'; +@import './imagepreview/imagepreview.scss'; +@import './indicator/indicator.scss'; +@import './lottie/lottie.scss'; +@import './pagination/pagination.scss'; +@import './price/price.scss'; +@import './progress/progress.scss'; +@import './segmented/segmented.scss'; +@import './step/step.scss'; +@import './steps/steps.scss'; +@import './swiper/swiper.scss'; +@import './swiperitem/swiperitem.scss'; +@import './table/table.scss'; +@import './tag/tag.scss'; +@import './tour/tour.scss'; +@import './video/video.scss'; +@import './virtuallist/virtuallist.scss'; +@import './quickenter/quickenter.scss'; +@import './avatarcropper/avatarcropper.scss'; +@import './barrage/barrage.scss'; +@import './card/card.scss'; +@import './timedetail/timedetail.scss'; +@import './timeselect/timeselect.scss'; +@import './trendarrow/trendarrow.scss'; +@import './watermark/watermark.scss'; diff --git a/src/styles/variables-daojia.scss b/src/styles/variables-daojia.scss index b125a9f7ef..61390c644c 100644 --- a/src/styles/variables-daojia.scss +++ b/src/styles/variables-daojia.scss @@ -1281,6 +1281,34 @@ $indicator-dot-active-size: var(--nutui-indicator-dot-active-size, $indicator-border-radius: var(--nutui-indicator-border-radius, $radius-xxs) !default; $indicator-dot-margin: var(--nutui-indicator-dot-margin, $spacing-xxs) !default; +$indicator-dot-border: var( + --nutui-indicator-dot-border, + 0.33px solid $color-border +) !default; +$indicator-dot-inactive-color: var( + --nutui-indicator-dot-inactive-color, + #f0f2f7 +) !default; +$indicator-track-width: var( + --nutui-indicator-track-width, + 24px +) !default; +$indicator-slider-width: var( + --nutui-indicator-slider-width, + 8px +) !default; +$indicator-dual-screen-inactive-width: var( + --nutui-indicator-dual-screen-inactive-width, + 16px +) !default; +$indicator-placement-gap: var( + --nutui-indicator-placement-gap, + 8px +) !default; +$indicator-placement-safe-gap: var( + --nutui-indicator-placement-safe-gap, + 12px +) !default; // menu(✅) $menu-scroll-fixed-top: var(--nutui-menu-scroll-fixed-top, 0) !default; diff --git a/src/styles/variables-jmapp.scss b/src/styles/variables-jmapp.scss index 1fe8f89e33..4b505b8824 100644 --- a/src/styles/variables-jmapp.scss +++ b/src/styles/variables-jmapp.scss @@ -2166,6 +2166,34 @@ $indicator-dot-active-size: var( ) !default; $indicator-border-radius: var(--nutui-indicator-border-radius, 2px) !default; $indicator-dot-margin: var(--nutui-indicator-dot-margin, $spacing-xs) !default; +$indicator-dot-border: var( + --nutui-indicator-dot-border, + 0.33px solid $color-border +) !default; +$indicator-dot-inactive-color: var( + --nutui-indicator-dot-inactive-color, + #f0f2f7 +) !default; +$indicator-track-width: var( + --nutui-indicator-track-width, + 24px +) !default; +$indicator-slider-width: var( + --nutui-indicator-slider-width, + 8px +) !default; +$indicator-dual-screen-inactive-width: var( + --nutui-indicator-dual-screen-inactive-width, + 16px +) !default; +$indicator-placement-gap: var( + --nutui-indicator-placement-gap, + 8px +) !default; +$indicator-placement-safe-gap: var( + --nutui-indicator-placement-safe-gap, + 12px +) !default; // menu(✅) $menu-scroll-fixed-top: var(--nutui-menu-scroll-fixed-top, 0) !default; diff --git a/src/styles/variables-jrkf.scss b/src/styles/variables-jrkf.scss index 871959aa11..c82688e2f5 100644 --- a/src/styles/variables-jrkf.scss +++ b/src/styles/variables-jrkf.scss @@ -2269,6 +2269,34 @@ $indicator-dot-active-size: var( ) !default; $indicator-border-radius: var(--nutui-indicator-border-radius, 2px) !default; $indicator-dot-margin: var(--nutui-indicator-dot-margin, $spacing-xs) !default; +$indicator-dot-border: var( + --nutui-indicator-dot-border, + 0.33px solid $color-border +) !default; +$indicator-dot-inactive-color: var( + --nutui-indicator-dot-inactive-color, + #f0f2f7 +) !default; +$indicator-track-width: var( + --nutui-indicator-track-width, + 24px +) !default; +$indicator-slider-width: var( + --nutui-indicator-slider-width, + 8px +) !default; +$indicator-dual-screen-inactive-width: var( + --nutui-indicator-dual-screen-inactive-width, + 16px +) !default; +$indicator-placement-gap: var( + --nutui-indicator-placement-gap, + 8px +) !default; +$indicator-placement-safe-gap: var( + --nutui-indicator-placement-safe-gap, + 12px +) !default; // menu(✅) $menu-scroll-fixed-top: var(--nutui-menu-scroll-fixed-top, 0) !default;