fix(mini-user): dedupe Taro reactMeta so H5 useDidShow works
CI / verify (pull_request) Has been cancelled
CI / verify (pull_request) Has been cancelled
Vite was bundling plugin-framework-react runtime twice, so tab pages crashed with useContext is not a function on enter/switch. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,27 @@
|
|||||||
|
import { createRequire } from 'node:module';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { defineConfig } from '@tarojs/cli';
|
import { defineConfig } from '@tarojs/cli';
|
||||||
|
|
||||||
/** 小程序/H5 请求的后端 origin(不含 /api);本地联调可用 VITE_API_TARGET 覆盖 */
|
/** 小程序/H5 请求的后端 origin(不含 /api);本地联调可用 VITE_API_TARGET 覆盖 */
|
||||||
const API_ORIGIN = process.env.VITE_API_TARGET ?? 'https://dkapi.runxian.top';
|
const API_ORIGIN = process.env.VITE_API_TARGET ?? 'https://dkapi.runxian.top';
|
||||||
|
|
||||||
|
const requireFromApp = createRequire(path.resolve(__dirname, '../package.json'));
|
||||||
|
|
||||||
|
/** 解析包目录/文件,避免 pnpm/Vite 把同一 runtime 打成两份 → useDidShow 读到空 reactMeta */
|
||||||
|
function resolvePkgFile(id: string): string {
|
||||||
|
return requireFromApp.resolve(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePkgDir(id: string): string {
|
||||||
|
return path.dirname(requireFromApp.resolve(`${id}/package.json`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const TARO_FRAMEWORK_RUNTIME = resolvePkgFile('@tarojs/plugin-framework-react/dist/runtime.js');
|
||||||
|
const REACT_DIR = resolvePkgDir('react');
|
||||||
|
const REACT_DOM_DIR = resolvePkgDir('react-dom');
|
||||||
|
const TARO_RUNTIME_DIR = resolvePkgDir('@tarojs/runtime');
|
||||||
|
const TARO_SHARED_DIR = resolvePkgDir('@tarojs/shared');
|
||||||
|
|
||||||
export default defineConfig(async () => ({
|
export default defineConfig(async () => ({
|
||||||
projectName: 'mini-user',
|
projectName: 'mini-user',
|
||||||
date: '2026-7-12',
|
date: '2026-7-12',
|
||||||
@@ -18,8 +36,13 @@ export default defineConfig(async () => ({
|
|||||||
outputRoot: 'dist',
|
outputRoot: 'dist',
|
||||||
plugins: ['@tarojs/plugin-framework-react', '@tarojs/plugin-html'],
|
plugins: ['@tarojs/plugin-framework-react', '@tarojs/plugin-html'],
|
||||||
alias: {
|
alias: {
|
||||||
react: path.resolve(__dirname, '../node_modules/react'),
|
// 指向包目录(不是 index.js),否则 react-dom/client 会变成 index.js/client
|
||||||
'react-dom': path.resolve(__dirname, '../node_modules/react-dom'),
|
react: REACT_DIR,
|
||||||
|
'react-dom': REACT_DOM_DIR,
|
||||||
|
'@tarojs/runtime': TARO_RUNTIME_DIR,
|
||||||
|
'@tarojs/shared': TARO_SHARED_DIR,
|
||||||
|
'@tarojs/plugin-framework-react/dist/runtime': TARO_FRAMEWORK_RUNTIME,
|
||||||
|
'@tarojs/plugin-framework-react/dist/runtime.js': TARO_FRAMEWORK_RUNTIME,
|
||||||
},
|
},
|
||||||
defineConstants: {
|
defineConstants: {
|
||||||
TARO_APP_API_ORIGIN: JSON.stringify(API_ORIGIN),
|
TARO_APP_API_ORIGIN: JSON.stringify(API_ORIGIN),
|
||||||
@@ -43,6 +66,16 @@ export default defineConfig(async () => ({
|
|||||||
noDiscovery: true,
|
noDiscovery: true,
|
||||||
include: ['react', 'react-dom', 'react/jsx-runtime'],
|
include: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
// 防止 reactMeta(useDidShow 依赖)在 vendors 里出现两份
|
||||||
|
dedupe: [
|
||||||
|
'react',
|
||||||
|
'react-dom',
|
||||||
|
'@tarojs/runtime',
|
||||||
|
'@tarojs/shared',
|
||||||
|
'@tarojs/plugin-framework-react',
|
||||||
|
],
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import './lib/text-encoding-polyfill';
|
import './lib/text-encoding-polyfill';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
import WechatShareBootstrap from './components/WechatShareBootstrap';
|
import WechatShareBootstrap from './components/WechatShareBootstrap';
|
||||||
|
import { patchTaroH5Hooks } from './lib/patch-taro-h5-hooks';
|
||||||
import './app.css';
|
import './app.css';
|
||||||
|
|
||||||
|
// H5:在首屏 page hooks 执行前,把 Taro.useDidShow 等绑到与 createReactApp 同一份 runtime
|
||||||
|
patchTaroH5Hooks();
|
||||||
|
|
||||||
function App({ children }: PropsWithChildren) {
|
function App({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* H5:Taro Vite 偶发把 @tarojs/plugin-framework-react/dist/runtime 打成两份,
|
||||||
|
* 导致 createReactApp 初始化了 B 份 reactMeta,而 Taro.useDidShow 仍绑定 A 份(R={}),
|
||||||
|
* 页面一进就报 n.useContext is not a function。
|
||||||
|
*
|
||||||
|
* 在 App 渲染前,用与 createReactApp 同一份 runtime 的 hooks 覆盖到 Taro 上。
|
||||||
|
*/
|
||||||
|
import Taro from '@tarojs/taro';
|
||||||
|
import {
|
||||||
|
useAddToFavorites,
|
||||||
|
useDidHide,
|
||||||
|
useDidShow,
|
||||||
|
useError,
|
||||||
|
useKeyboardHeight,
|
||||||
|
useLaunch,
|
||||||
|
useLoad,
|
||||||
|
useOptionMenuClick,
|
||||||
|
usePageNotFound,
|
||||||
|
usePageScroll,
|
||||||
|
usePullDownRefresh,
|
||||||
|
usePullIntercept,
|
||||||
|
useReachBottom,
|
||||||
|
useReady,
|
||||||
|
useResize,
|
||||||
|
useRouter,
|
||||||
|
useSaveExitState,
|
||||||
|
useScope,
|
||||||
|
useShareAppMessage,
|
||||||
|
useShareTimeline,
|
||||||
|
useTabItemTap,
|
||||||
|
useTitleClick,
|
||||||
|
useUnhandledRejection,
|
||||||
|
useUnload,
|
||||||
|
} from '@tarojs/plugin-framework-react/dist/runtime';
|
||||||
|
|
||||||
|
const HOOKS = {
|
||||||
|
useAddToFavorites,
|
||||||
|
useDidHide,
|
||||||
|
useDidShow,
|
||||||
|
useError,
|
||||||
|
useKeyboardHeight,
|
||||||
|
useLaunch,
|
||||||
|
useLoad,
|
||||||
|
useOptionMenuClick,
|
||||||
|
usePageNotFound,
|
||||||
|
usePageScroll,
|
||||||
|
usePullDownRefresh,
|
||||||
|
usePullIntercept,
|
||||||
|
useReachBottom,
|
||||||
|
useReady,
|
||||||
|
useResize,
|
||||||
|
useRouter,
|
||||||
|
useSaveExitState,
|
||||||
|
useScope,
|
||||||
|
useShareAppMessage,
|
||||||
|
useShareTimeline,
|
||||||
|
useTabItemTap,
|
||||||
|
useTitleClick,
|
||||||
|
useUnhandledRejection,
|
||||||
|
useUnload,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export function patchTaroH5Hooks() {
|
||||||
|
if (process.env.TARO_ENV !== 'h5') return;
|
||||||
|
const target = Taro as unknown as Record<string, unknown>;
|
||||||
|
for (const [key, fn] of Object.entries(HOOKS)) {
|
||||||
|
target[key] = fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user