From bc07582f9a59d0506d79c0f61d539dcd0abd8c76 Mon Sep 17 00:00:00 2001 From: zernonia Date: Tue, 2 Jan 2024 16:05:14 +0800 Subject: [PATCH] refactor: use recast instead of ts-morph due to performance issue --- packages/module/src/module.ts | 42 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/module/src/module.ts b/packages/module/src/module.ts index a5b58655..04a71e2a 100644 --- a/packages/module/src/module.ts +++ b/packages/module/src/module.ts @@ -1,7 +1,7 @@ -import { readdirSync } from 'node:fs' -import { join } from 'pathe' -import { addComponent, createResolver, defineNuxtModule } from '@nuxt/kit' -import { Project } from 'ts-morph' +import { readFileSync, readdirSync } from 'node:fs' +import { join } from 'node:path' +import { addComponent, createResolver, defineNuxtModule } from 'nuxt/kit' +import { parse } from 'recast' // Module options TypeScript interface definition export interface ModuleOptions { @@ -25,33 +25,35 @@ export default defineNuxtModule({ prefix: '', componentDir: './components/ui', }, - async setup(options, nuxt) { - const IGNORE_DIR = '**/components/ui' - const COMPONENT_DIR_PATH = options.componentDir! + async setup({ prefix, componentDir }, nuxt) { + const COMPONENT_DIR_PATH = componentDir! const ROOT_DIR_PATH = nuxt.options.rootDir - const { resolve, resolvePath } = createResolver(ROOT_DIR_PATH) - nuxt.options.ignore.push(IGNORE_DIR) - nuxt._ignore?.add(IGNORE_DIR) - nuxt._ignorePatterns?.push(IGNORE_DIR) + nuxt.hook('components:dirs', (dirs) => { + dirs.unshift({ + path: resolve(COMPONENT_DIR_PATH), + extensions: [], + }) + }) try { readdirSync(resolve(COMPONENT_DIR_PATH)) .forEach(async (dir) => { - const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, 'index'), { extensions: ['.ts', '.js'] }) + const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, 'index'), { extensions: ['.ts', 'js'] }) + const content = readFileSync(filePath, { encoding: 'utf8' }) + const ast = parse(content) - const project = new Project() - project.addSourceFileAtPath(filePath) - const sourceFile = project.getSourceFileOrThrow(filePath) - const exportedDeclarations = sourceFile.getExportedDeclarations() - - // Filter out non-component export - const exportedKeys = Array.from(exportedDeclarations.keys()).filter(key => /^[A-Z]/.test(key)) + const exportedKeys: string[] = ast.program.body + // @ts-expect-error parse return any + .filter(node => node.type === 'ExportNamedDeclaration') + // @ts-expect-error parse return any + .flatMap(node => node.specifiers.map(specifier => specifier.exported.name)) + .filter((key: string) => /^[A-Z]/.test(key)) exportedKeys.forEach((key) => { addComponent({ - name: `${options.prefix}${key}`, // name of the component to be used in vue templates + name: `${prefix}${key}`, // name of the component to be used in vue templates export: key, // (optional) if the component is a named (rather than default) export filePath: resolve(filePath), })