From 0f719115d2baa4c653ee8015a109d2add6a7802b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Thu, 15 Aug 2024 01:55:01 +0800 Subject: [PATCH] feat(vue-jsx): add `defineComponentName` option --- packages/plugin-vue-jsx/README.md | 10 ++++++- packages/plugin-vue-jsx/src/index.ts | 40 +++++++++++++++++++++------- packages/plugin-vue-jsx/src/types.ts | 7 +++-- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/packages/plugin-vue-jsx/README.md b/packages/plugin-vue-jsx/README.md index 5b74fdda..3fd94da9 100644 --- a/packages/plugin-vue-jsx/README.md +++ b/packages/plugin-vue-jsx/README.md @@ -35,12 +35,20 @@ A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patt > See [@vue/babel-plugin-jsx](https://github.com/vuejs/jsx-next) for other options. +### defineComponentName + +Type: `string[]` + +Default: `['defineComponent']` + +The name of the function to be used for defining components. This is useful when you have a custom `defineComponent` function. + ## HMR Detection This plugin supports HMR of Vue JSX components. The detection requirements are: - The component must be exported. -- The component must be declared by calling `defineComponent` via a root-level statement, either variable declaration or export declaration. +- The component must be declared by calling `defineComponent` or the name specified in `defineComponentName` via a root-level statement, either variable declaration or export declaration. ### Supported patterns diff --git a/packages/plugin-vue-jsx/src/index.ts b/packages/plugin-vue-jsx/src/index.ts index 2d2b82da..2c680d81 100644 --- a/packages/plugin-vue-jsx/src/index.ts +++ b/packages/plugin-vue-jsx/src/index.ts @@ -38,7 +38,13 @@ function vueJsxPlugin(options: Options = {}): Plugin { let needHmr = false let needSourceMap = true - const { include, exclude, babelPlugins = [], ...babelPluginOptions } = options + const { + include, + exclude, + babelPlugins = [], + defineComponentName = ['defineComponent'], + ...babelPluginOptions + } = options const filter = createFilter(include || /\.[jt]sx$/, exclude) return { @@ -103,7 +109,9 @@ function vueJsxPlugin(options: Options = {}): Plugin { visitor: { CallExpression: { enter(_path: babel.NodePath) { - if (isDefineComponentCall(_path.node)) { + if ( + isDefineComponentCall(_path.node, defineComponentName) + ) { const callee = _path.node.callee as Identifier callee.name = `/* @__PURE__ */ ${callee.name}` } @@ -144,7 +152,7 @@ function vueJsxPlugin(options: Options = {}): Plugin { for (const node of result.ast!.program.body) { if (node.type === 'VariableDeclaration') { - const names = parseComponentDecls(node) + const names = parseComponentDecls(node, defineComponentName) if (names.length) { declaredComponents.push(...names) } @@ -156,7 +164,10 @@ function vueJsxPlugin(options: Options = {}): Plugin { node.declaration.type === 'VariableDeclaration' ) { hotComponents.push( - ...parseComponentDecls(node.declaration).map((name) => ({ + ...parseComponentDecls( + node.declaration, + defineComponentName, + ).map((name) => ({ local: name, exported: name, id: getHash(id + name), @@ -194,7 +205,9 @@ function vueJsxPlugin(options: Options = {}): Plugin { id: getHash(id + 'default'), }) } - } else if (isDefineComponentCall(node.declaration)) { + } else if ( + isDefineComponentCall(node.declaration, defineComponentName) + ) { hasDefault = true hotComponents.push({ local: '__default__', @@ -254,22 +267,31 @@ function vueJsxPlugin(options: Options = {}): Plugin { } } -function parseComponentDecls(node: types.VariableDeclaration) { +function parseComponentDecls( + node: types.VariableDeclaration, + fnNames: string[], +) { const names = [] for (const decl of node.declarations) { - if (decl.id.type === 'Identifier' && isDefineComponentCall(decl.init)) { + if ( + decl.id.type === 'Identifier' && + isDefineComponentCall(decl.init, fnNames) + ) { names.push(decl.id.name) } } return names } -function isDefineComponentCall(node?: types.Node | null) { +function isDefineComponentCall( + node: types.Node | null | undefined, + names: string[], +) { return ( node && node.type === 'CallExpression' && node.callee.type === 'Identifier' && - node.callee.name === 'defineComponent' + names.includes(node.callee.name) ) } diff --git a/packages/plugin-vue-jsx/src/types.ts b/packages/plugin-vue-jsx/src/types.ts index a3be5808..3c174fdf 100644 --- a/packages/plugin-vue-jsx/src/types.ts +++ b/packages/plugin-vue-jsx/src/types.ts @@ -6,5 +6,8 @@ export interface FilterOptions { exclude?: FilterPattern } -export type Options = VueJSXPluginOptions & - FilterOptions & { babelPlugins?: any[] } +export interface Options extends VueJSXPluginOptions, FilterOptions { + babelPlugins?: any[] + /** @default ['defineComponent'] */ + defineComponentName?: string[] +}