mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 01:15:58 +00:00
fix(nuxt3): import top-level files and subdirectory indices (#2774)
This commit is contained in:
parent
8588f749ad
commit
b38e394dfe
@ -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).
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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 })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user