From 4fd3e69b45e9969187cabc1f6c5790061b568439 Mon Sep 17 00:00:00 2001 From: innocces Date: Wed, 24 Jul 2024 18:51:00 +0800 Subject: [PATCH] feat(react-vite): plugin-react support vite compiler --- packages/plugin-react/src/index.ts | 69 ++++--------------- packages/plugin-react/src/runtime/constant.ts | 4 ++ .../src/runtime/modifyViteConfig.ts | 67 ++++++++++++++++++ .../src/runtime/modifyWebpackChain.ts | 27 ++++++++ packages/plugin-react/src/runtime/shared.ts | 40 +++++++++++ 5 files changed, 150 insertions(+), 57 deletions(-) create mode 100644 packages/plugin-react/src/runtime/constant.ts create mode 100644 packages/plugin-react/src/runtime/modifyViteConfig.ts create mode 100644 packages/plugin-react/src/runtime/modifyWebpackChain.ts create mode 100644 packages/plugin-react/src/runtime/shared.ts diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 21c6b7864..6a7f3ddfd 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -1,65 +1,20 @@ -import { chalk } from '@tarojs/helper'; import { IPluginContext } from '@tarojs/service'; -// 同时兼容一下 preact 和 nerv -const reactLike = ['preact', 'nerv']; -const supportFrameworks = ['react', ...reactLike]; +import { modifyViteConfig } from './runtime/modifyViteConfig'; +import { modifyWebpackChain } from './runtime/modifyWebpackChain'; + +import { getReactPath } from './runtime/shared'; +import { supportFrameworks } from './runtime/constant'; +// 同时兼容一下 preact 和 nerv export default (ctx: IPluginContext) => { const { framework } = ctx.initialConfig; - if ((framework && !supportFrameworks.includes(framework)) || !getReactPath(framework)) + if ( + (framework && !supportFrameworks.includes(framework)) || + !getReactPath(framework) + ) return; - ctx.modifyWebpackChain(({ chain, webpack }) => { - setDefinePlugin(chain, webpack); - console.log( - chalk.blue( - `✨ 逮到一个使用taro-hooks的小可爱~ \n 当前使用的框架是: ${framework}`, - ), - ); - - chain.resolve.alias.set('@taro-hooks/core', getRealRuntimePath()); - - // 检查一下除 react 的框架是否包含了对应的 alias. 不然 runtime 会报错 - if (reactLike.includes(framework!) && !chain.resolve.alias.get('react')) { - chain.resolve.alias.set('react', framework!); - } - }); + modifyWebpackChain(ctx); + modifyViteConfig(ctx); }; - -function setDefinePlugin(chain: any, webpack: any) { - chain.plugin('defined').use(webpack.DefinePlugin, [ - { - // fix process is not defined in 3.5.x webpackv5 mode! - __TARO_HOOKS_REACT__: JSON.stringify(true), - __TARO_HOOKS_VUE__: JSON.stringify(false), - TARO_ENV: JSON.stringify(process.env.TARO_ENV?.toLocaleUpperCase()), - }, - ]); -} - -function getNumberVersion(): number { - try { - const pkgPath = require.resolve('@tarojs/taro/package.json', { - paths: [process.cwd()], - }); - return require(pkgPath).version?.replace(/\./gi, ''); - } catch (e) { - return Infinity; - } -} - -function getRealRuntimePath(): string { - return `@taro-hooks/plugin-react/dist/runtime`; -} - -export function getReactPath(framework = 'react'): string { - try { - return require.resolve(framework, { - paths: [process.cwd()], - }); - } catch (error) { - console.log(chalk.yellow(`找不到 ${framework}. 请先安装。`)); - process.exit(1); - } -} diff --git a/packages/plugin-react/src/runtime/constant.ts b/packages/plugin-react/src/runtime/constant.ts new file mode 100644 index 000000000..a7dd6faf9 --- /dev/null +++ b/packages/plugin-react/src/runtime/constant.ts @@ -0,0 +1,4 @@ +// 同时兼容一下 preact 和 nerv +export const reactLike = ['preact', 'nerv']; + +export const supportFrameworks = ['react', ...reactLike]; diff --git a/packages/plugin-react/src/runtime/modifyViteConfig.ts b/packages/plugin-react/src/runtime/modifyViteConfig.ts new file mode 100644 index 000000000..9468f8d01 --- /dev/null +++ b/packages/plugin-react/src/runtime/modifyViteConfig.ts @@ -0,0 +1,67 @@ +import { IPluginContext } from '@tarojs/service'; +import { chalk } from '@tarojs/helper'; +import { reactLike } from './constant'; +import { getRealRuntimePath, isVersion4, getDefine } from './shared'; + +export function modifyViteConfig(ctx: IPluginContext) { + const { framework } = ctx.initialConfig; + + if (isVersion4() && 'modifyViteConfig' in ctx) { + ctx.modifyViteConfig(({ viteConfig }) => { + const taroHooksVitePlugins = [setDefinePlugin(), setAlias(framework)]; + console.log( + chalk.blue( + `✨ 逮到一个使用taro-hooks的小可爱~ \n 当前使用的框架是: ${framework}`, + ), + ); + + viteConfig.plugins.push(...taroHooksVitePlugins); + }); + } +} + +function setDefinePlugin() { + return { + name: '@taro-hooks/plugin-react:define', + config: () => { + return { + define: { + ...getDefine(), + }, + }; + }, + }; +} + +function setAlias(framework) { + return { + name: '@taro-hooks/plugin-react:alias', + enforce: 'pre', + config: (userConfig) => { + const alias: Record[] = [ + { find: '@taro-hooks/core', replacement: getRealRuntimePath() }, + ]; + const userAlias = userConfig.resolve?.alias; + let aliasReact = true; + if (Array.isArray(userAlias)) { + aliasReact = userAlias.find((v) => v.find === 'react'); + } else if ( + Object.prototype.toString.call(userAlias) === '[object Object]' + ) { + aliasReact = 'react' in userAlias; + } + // 检查一下除 react 的框架是否包含了对应的 alias. 不然 runtime 会报错 + if (reactLike.includes(framework!) && !aliasReact) { + alias.push({ + find: 'react', + replacement: framework, + }); + } + return { + resolve: { + alias, + }, + }; + }, + }; +} diff --git a/packages/plugin-react/src/runtime/modifyWebpackChain.ts b/packages/plugin-react/src/runtime/modifyWebpackChain.ts new file mode 100644 index 000000000..b5d1df7e2 --- /dev/null +++ b/packages/plugin-react/src/runtime/modifyWebpackChain.ts @@ -0,0 +1,27 @@ +import { IPluginContext } from '@tarojs/service'; +import { chalk } from '@tarojs/helper'; +import { reactLike } from './constant'; +import { getRealRuntimePath, getDefine } from './shared'; + +export function modifyWebpackChain(ctx: IPluginContext) { + const { framework } = ctx.initialConfig; + ctx.modifyWebpackChain(({ chain, webpack }) => { + setDefinePlugin(chain, webpack); + console.log( + chalk.blue( + `✨ 逮到一个使用taro-hooks的小可爱~ \n 当前使用的框架是: ${framework}`, + ), + ); + + chain.resolve.alias.set('@taro-hooks/core', getRealRuntimePath()); + + // 检查一下除 react 的框架是否包含了对应的 alias. 不然 runtime 会报错 + if (reactLike.includes(framework!) && !chain.resolve.alias.get('react')) { + chain.resolve.alias.set('react', framework!); + } + }); +} + +function setDefinePlugin(chain: any, webpack: any) { + chain.plugin('defined').use(webpack.DefinePlugin, [getDefine()]); +} diff --git a/packages/plugin-react/src/runtime/shared.ts b/packages/plugin-react/src/runtime/shared.ts new file mode 100644 index 000000000..131deafcc --- /dev/null +++ b/packages/plugin-react/src/runtime/shared.ts @@ -0,0 +1,40 @@ +import { chalk } from '@tarojs/helper'; + +export function getNumberVersion(): number { + try { + const pkgPath = require.resolve('@tarojs/taro/package.json', { + paths: [process.cwd()], + }); + return require(pkgPath).version?.replace(/\./gi, ''); + } catch (e) { + return Infinity; + } +} + +export function isVersion4() { + return String(getNumberVersion()).startsWith('4'); +} + +export function getRealRuntimePath(): string { + return `@taro-hooks/plugin-react/dist/runtime`; +} + +export function getReactPath(framework = 'react'): string { + try { + return require.resolve(framework, { + paths: [process.cwd()], + }); + } catch (error) { + console.log(chalk.yellow(`找不到 ${framework}. 请先安装。`)); + process.exit(1); + } +} + +export function getDefine() { + return { + // fix process is not defined in 3.5.x webpackv5 mode! + __TARO_HOOKS_REACT__: JSON.stringify(true), + __TARO_HOOKS_VUE__: JSON.stringify(false), + TARO_ENV: JSON.stringify(process.env.TARO_ENV?.toLocaleUpperCase()), + }; +}