diff --git a/docs/content/3.docs/2.directory-structure/10.plugins.md b/docs/content/3.docs/2.directory-structure/10.plugins.md index 20a7327754..3959b234ef 100644 --- a/docs/content/3.docs/2.directory-structure/10.plugins.md +++ b/docs/content/3.docs/2.directory-structure/10.plugins.md @@ -12,6 +12,23 @@ Nuxt will automatically read the files in your `plugins` directory and load them All plugins in your `plugins/` directory are auto-registered, so you should not add them to your `nuxt.config` separately. :: +## Which files are registered + +Only files at the top level of the `plugins/` directory (or index files within any subdirectories) will be registered as plugins. + +For example: + +```bash +plugins + | - myPlugin.ts + | - myOtherPlugin + | --- supportingFile.ts + | --- componentToRegister.vue + | --- index.ts +``` + +Only `myPlugin.ts` and `myOtherPlugin/index.ts` would be registered. + ## Creating plugins The only argument passed to a plugin is [`nuxtApp`](/docs/usage/nuxt-app). diff --git a/docs/content/3.docs/2.directory-structure/5.composables.md b/docs/content/3.docs/2.directory-structure/5.composables.md index b3d7988858..3e6594fd9e 100644 --- a/docs/content/3.docs/2.directory-structure/5.composables.md +++ b/docs/content/3.docs/2.directory-structure/5.composables.md @@ -8,7 +8,23 @@ head.title: Composables directory Nuxt 3 supports `composables/` directory to automatically import your Vue composables into your application using auto-imports! -Example: (using named export) +## How files are scanned + +Only files at the top level of the `composables/` directory (or index files within any subdirectories) will be scanned for composables. + +For example: + +```bash +composables + | - useFoo.ts + | - useBar + | --- supportingFile.ts + | --- index.ts +``` + +Only `useFoo.ts` and `useBar/index.ts` would be searched for imports - and if the latter is a default export, it would be registered as `useBar` rather than `index`. + +## Example: (using named export) ```js [composables/useFoo.ts] import { useState } from '#app' @@ -18,7 +34,7 @@ export const useFoo = () => { } ``` -Example: (using default export) +## Example: (using default export) ```js [composables/use-foo.ts or composables/useFoo.ts] import { useState } from '#app' diff --git a/packages/kit/src/resolve.ts b/packages/kit/src/resolve.ts index 8de9f214e5..fa228918d6 100644 --- a/packages/kit/src/resolve.ts +++ b/packages/kit/src/resolve.ts @@ -104,7 +104,7 @@ export function tryResolvePath (path: string, opts: ResolveOptions = {}) { } } -export async function resolveFiles (path: string, pattern: string) { +export async function resolveFiles (path: string, pattern: string | string[]) { const files = await globby(pattern, { cwd: path, followSymbolicLinks: true diff --git a/packages/nuxt3/src/auto-imports/composables.ts b/packages/nuxt3/src/auto-imports/composables.ts index cd089bc90c..fe137ff6e2 100644 --- a/packages/nuxt3/src/auto-imports/composables.ts +++ b/packages/nuxt3/src/auto-imports/composables.ts @@ -1,37 +1,42 @@ import { promises as fsp, existsSync } from 'fs' -import { parse as parsePath, join } from 'pathe' -import { globby } from 'globby' +import { parse as parsePath } from 'pathe' import { findExports } from 'mlly' import { camelCase } from 'scule' import { AutoImport } from '@nuxt/schema' +import { resolveFiles } from '@nuxt/kit' import { filterInPlace } from './utils' export async function scanForComposables (dir: string, autoImports: AutoImport[]) { if (!existsSync(dir)) { return } - const files = await globby(['*.{ts,js,tsx,jsx,mjs,cjs,mts,cts}'], { cwd: dir }) + const files = await resolveFiles(dir, [ + '*.{ts,js,mjs,cjs,mts,cts}', + '*/index.{ts,js,mjs,cjs,mts,cts}' + ]) await Promise.all( - files.map(async (file) => { - const importPath = join(dir, file) - + files.map(async (path) => { // Remove original entries from the same import (for build watcher) - filterInPlace(autoImports, i => i.from !== importPath) + filterInPlace(autoImports, i => i.from !== path) - const code = await fsp.readFile(join(dir, file), 'utf-8') + const code = await fsp.readFile(path, 'utf-8') const exports = findExports(code) const defaultExport = exports.find(i => i.type === 'default') if (defaultExport) { - autoImports.push({ name: 'default', as: camelCase(parsePath(file).name), from: importPath }) + let name = parsePath(path).name + if (name === 'index') { + name = parsePath(path.split('/').slice(0, -1).join('/')).name + } + autoImports.push({ name: 'default', as: camelCase(name), from: path }) } for (const exp of exports) { if (exp.type === 'named') { for (const name of exp.names) { - autoImports.push({ name, as: name, from: importPath }) + autoImports.push({ name, as: name, from: path }) } } else if (exp.type === 'declaration') { - autoImports.push({ name: exp.name, as: exp.name, from: importPath }) + autoImports.push({ name: exp.name, as: exp.name, from: path }) } } }) diff --git a/packages/nuxt3/src/core/app.ts b/packages/nuxt3/src/core/app.ts index b2d9a9bd42..cc11dbb4a7 100644 --- a/packages/nuxt3/src/core/app.ts +++ b/packages/nuxt3/src/core/app.ts @@ -73,7 +73,10 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) { // Resolve plugins app.plugins = [ ...nuxt.options.plugins, - ...await resolveFiles(nuxt.options.srcDir, 'plugins/**/*.{js,ts,mjs,cjs}') + ...await resolveFiles(nuxt.options.srcDir, [ + 'plugins/*.{ts,js,mjs,cjs,mts,cts}', + 'plugins/*/index.*{ts,js,mjs,cjs,mts,cts}' + ]) ].map(plugin => normalizePlugin(plugin)) // Extend app