mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
refactor(nuxt,schema,vite,webpack): use unplugin for vfs
This commit is contained in:
parent
e74b512dc0
commit
6133fe62d6
@ -211,13 +211,10 @@ export async function _generateTypes (nuxt: Nuxt) {
|
||||
exclude: [...exclude],
|
||||
} satisfies TSConfig)
|
||||
|
||||
const aliases: Record<string, string> = {
|
||||
...nuxt.options.alias,
|
||||
'#build': nuxt.options.buildDir,
|
||||
}
|
||||
const aliases: Record<string, string> = nuxt.options.alias
|
||||
|
||||
// Exclude bridge alias types to support Volar
|
||||
const excludedAlias = [/^@vue\/.*$/]
|
||||
const excludedAlias = [/^@vue\/.*$/, /^#internal\/nuxt/]
|
||||
|
||||
const basePath = tsConfig.compilerOptions!.baseUrl
|
||||
? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl)
|
||||
|
@ -34,9 +34,6 @@ describe('tsConfig generation', () => {
|
||||
const { tsConfig } = await _generateTypes(mockNuxt)
|
||||
expect(tsConfig.compilerOptions?.paths).toMatchInlineSnapshot(`
|
||||
{
|
||||
"#build": [
|
||||
".",
|
||||
],
|
||||
"some-custom-alias": [
|
||||
"../some-alias",
|
||||
],
|
||||
|
@ -74,7 +74,7 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?:
|
||||
if (template.modified) {
|
||||
nuxt.vfs[fullPath] = contents
|
||||
|
||||
const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '')
|
||||
const aliasPath = '#build/' + template.filename
|
||||
nuxt.vfs[aliasPath] = contents
|
||||
|
||||
// In case a non-normalized absolute path is called for on Windows
|
||||
|
@ -102,7 +102,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
devHandlers: [],
|
||||
baseURL: nuxt.options.app.baseURL,
|
||||
virtual: {
|
||||
'#internal/nuxt.config.mjs': () => nuxt.vfs['#build/nuxt.config'],
|
||||
'#internal/nuxt.config.mjs': () => nuxt.vfs['#build/nuxt.config.mjs'],
|
||||
'#spa-template': async () => `export const template = ${JSON.stringify(await spaLoadingTemplate(nuxt))}`,
|
||||
},
|
||||
routeRules: {
|
||||
@ -193,11 +193,11 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
},
|
||||
'@vue/devtools-api': 'vue-devtools-stub',
|
||||
|
||||
// Paths
|
||||
'#internal/nuxt/paths': resolve(distDir, 'core/runtime/nitro/paths'),
|
||||
|
||||
// Nuxt aliases
|
||||
...nuxt.options.alias,
|
||||
|
||||
// Paths
|
||||
'#internal/nuxt/paths': resolve(distDir, 'core/runtime/nitro/paths'),
|
||||
},
|
||||
replace: {
|
||||
'process.env.NUXT_NO_SSR': nuxt.options.ssr === false,
|
||||
|
@ -46,6 +46,7 @@ import { RemovePluginMetadataPlugin } from './plugins/plugin-metadata'
|
||||
import { AsyncContextInjectionPlugin } from './plugins/async-context'
|
||||
import { resolveDeepImportsPlugin } from './plugins/resolve-deep-imports'
|
||||
import { prehydrateTransformPlugin } from './plugins/prehydrate'
|
||||
import { VirtualFSPlugin } from './plugins/virtual'
|
||||
|
||||
export function createNuxt (options: NuxtOptions): Nuxt {
|
||||
const hooks = createHooks<NuxtHooks>()
|
||||
@ -242,6 +243,10 @@ async function initNuxt (nuxt: Nuxt) {
|
||||
}
|
||||
}
|
||||
|
||||
// Support Nuxt VFS
|
||||
addBuildPlugin(VirtualFSPlugin(nuxt, { mode: 'server' }), { client: false })
|
||||
addBuildPlugin(VirtualFSPlugin(nuxt, { mode: 'client', alias: { '#internal/nitro': '#build/nitro.client.mjs' } }), { server: false })
|
||||
|
||||
// Add plugin normalization plugin
|
||||
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
||||
|
||||
|
@ -16,7 +16,7 @@ export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
|
||||
conditions = config.mode === 'test' ? [...config.resolve.conditions, 'import', 'require'] : config.resolve.conditions
|
||||
},
|
||||
async resolveId (id, importer) {
|
||||
if (!importer || isAbsolute(id) || (!isAbsolute(importer) && !importer.startsWith('virtual:')) || exclude.some(e => id.startsWith(e))) {
|
||||
if (!importer || isAbsolute(id) || (!isAbsolute(importer) && !importer.startsWith('virtual:') && !importer.startsWith('\0virtual:')) || exclude.some(e => id.startsWith(e))) {
|
||||
return
|
||||
}
|
||||
|
||||
|
64
packages/nuxt/src/core/plugins/virtual.ts
Normal file
64
packages/nuxt/src/core/plugins/virtual.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { resolveAlias, useNuxt } from '@nuxt/kit'
|
||||
import { dirname, isAbsolute, join, resolve } from 'pathe'
|
||||
import { createUnplugin } from 'unplugin'
|
||||
|
||||
const PREFIX = '\0virtual:nuxt:'
|
||||
|
||||
interface VirtualFSPluginOptions {
|
||||
mode: 'client' | 'server'
|
||||
alias?: Record<string, string>
|
||||
}
|
||||
|
||||
export const VirtualFSPlugin = (nuxt = useNuxt(), options: VirtualFSPluginOptions) => createUnplugin(() => {
|
||||
const extensions = ['', ...nuxt.options.extensions]
|
||||
const alias = { ...nuxt.options.alias, ...options.alias }
|
||||
|
||||
const resolveWithExt = (id: string) => {
|
||||
for (const suffix of ['', '.' + options.mode]) {
|
||||
for (const ext of extensions) {
|
||||
const rId = id + suffix + ext
|
||||
if (rId in nuxt.vfs) {
|
||||
return rId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'nuxt:virtual',
|
||||
enforce: 'post',
|
||||
|
||||
resolveId (id, importer) {
|
||||
const _id = id
|
||||
id = resolveAlias(id, alias)
|
||||
|
||||
if (process.platform === 'win32' && isAbsolute(id)) {
|
||||
// Add back C: prefix on Windows
|
||||
id = resolve(id)
|
||||
}
|
||||
|
||||
const resolvedId = resolveWithExt(id)
|
||||
if (resolvedId) {
|
||||
return PREFIX + resolvedId
|
||||
}
|
||||
|
||||
if (importer && !isAbsolute(id)) {
|
||||
const resolved = resolveWithExt(join(dirname(importer), id))
|
||||
if (resolved) {
|
||||
return PREFIX + resolved
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
loadInclude (id) {
|
||||
return id.startsWith(PREFIX)
|
||||
},
|
||||
|
||||
load (id) {
|
||||
return {
|
||||
code: nuxt.vfs[id.slice(PREFIX.length)] || '',
|
||||
map: null,
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
@ -57,7 +57,7 @@ export const cssTemplate: NuxtTemplate = {
|
||||
}
|
||||
|
||||
export const clientPluginTemplate: NuxtTemplate = {
|
||||
filename: 'plugins/client.mjs',
|
||||
filename: 'plugins.client.mjs',
|
||||
async getContents (ctx) {
|
||||
const clientPlugins = await annotatePlugins(ctx.nuxt, ctx.app.plugins.filter(p => !p.mode || p.mode !== 'server'))
|
||||
checkForCircularDependencies(clientPlugins)
|
||||
@ -77,7 +77,7 @@ export const clientPluginTemplate: NuxtTemplate = {
|
||||
}
|
||||
|
||||
export const serverPluginTemplate: NuxtTemplate = {
|
||||
filename: 'plugins/server.mjs',
|
||||
filename: 'plugins.server.mjs',
|
||||
async getContents (ctx) {
|
||||
const serverPlugins = await annotatePlugins(ctx.nuxt, ctx.app.plugins.filter(p => !p.mode || p.mode !== 'client'))
|
||||
checkForCircularDependencies(serverPlugins)
|
||||
|
@ -81,8 +81,8 @@ export default import.meta.server ? [CapoPlugin({ track: true })] : [];`
|
||||
|
||||
// template is only exposed in nuxt context, expose in nitro context as well
|
||||
nuxt.hooks.hook('nitro:config', (config) => {
|
||||
config.virtual!['#internal/unhead-plugins.mjs'] = () => nuxt.vfs['#build/unhead-plugins']
|
||||
config.virtual!['#internal/unhead.config.mjs'] = () => nuxt.vfs['#build/unhead.config']
|
||||
config.virtual!['#internal/unhead-plugins.mjs'] = () => nuxt.vfs['#build/unhead-plugins.mjs']
|
||||
config.virtual!['#internal/unhead.config.mjs'] = () => nuxt.vfs['#build/unhead.config.mjs']
|
||||
})
|
||||
|
||||
// Add library-specific plugin
|
||||
|
@ -421,7 +421,7 @@ export default defineUntypedSchema({
|
||||
*/
|
||||
alias: {
|
||||
$resolve: async (val: Record<string, string>, get): Promise<Record<string, string>> => {
|
||||
const [srcDir, rootDir, assetsDir, publicDir] = await Promise.all([get('srcDir'), get('rootDir'), get('dir.assets'), get('dir.public')]) as [string, string, string, string]
|
||||
const [srcDir, rootDir, assetsDir, publicDir, buildDir] = await Promise.all([get('srcDir'), get('rootDir'), get('dir.assets'), get('dir.public'), get('buildDir')]) as [string, string, string, string, string]
|
||||
return {
|
||||
'~': srcDir,
|
||||
'@': srcDir,
|
||||
@ -429,6 +429,8 @@ export default defineUntypedSchema({
|
||||
'@@': rootDir,
|
||||
[basename(assetsDir)]: resolve(srcDir, assetsDir),
|
||||
[basename(publicDir)]: resolve(srcDir, publicDir),
|
||||
'#build': buildDir,
|
||||
'#internal/nuxt/paths': resolve(buildDir, 'paths.mjs'),
|
||||
...val,
|
||||
}
|
||||
},
|
||||
|
@ -109,9 +109,7 @@ export async function buildClient (ctx: ViteBuildContext) {
|
||||
alias: {
|
||||
...nodeCompat.alias,
|
||||
...ctx.config.resolve?.alias,
|
||||
'#internal/nuxt/paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
|
||||
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/client'),
|
||||
'#internal/nitro': resolve(ctx.nuxt.options.buildDir, 'nitro.client.mjs'),
|
||||
'#internal/nitro': '#build/nitro.client.mjs',
|
||||
},
|
||||
dedupe: [
|
||||
'vue',
|
||||
|
@ -1,48 +0,0 @@
|
||||
import { dirname, isAbsolute, join, resolve } from 'pathe'
|
||||
import type { Plugin } from 'vite'
|
||||
|
||||
const PREFIX = 'virtual:nuxt:'
|
||||
|
||||
export default function virtual (vfs: Record<string, string>): Plugin {
|
||||
const extensions = ['', '.ts', '.vue', '.mjs', '.cjs', '.js', '.json']
|
||||
const resolveWithExt = (id: string) => {
|
||||
for (const ext of extensions) {
|
||||
const rId = id + ext
|
||||
if (rId in vfs) {
|
||||
return rId
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'virtual',
|
||||
|
||||
resolveId (id, importer) {
|
||||
if (process.platform === 'win32' && isAbsolute(id)) {
|
||||
// Add back C: prefix on Windows
|
||||
id = resolve(id)
|
||||
}
|
||||
const resolvedId = resolveWithExt(id)
|
||||
if (resolvedId) { return PREFIX + resolvedId }
|
||||
if (importer && !isAbsolute(id)) {
|
||||
const importerNoPrefix = importer.startsWith(PREFIX) ? importer.slice(PREFIX.length) : importer
|
||||
const importedDir = dirname(importerNoPrefix)
|
||||
const resolved = resolveWithExt(join(importedDir, id))
|
||||
if (resolved) { return PREFIX + resolved }
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
load (id) {
|
||||
if (!id.startsWith(PREFIX)) { return null }
|
||||
const idNoPrefix = id.slice(PREFIX.length)
|
||||
if (idNoPrefix in vfs) {
|
||||
return {
|
||||
code: vfs[idNoPrefix] || '',
|
||||
map: null,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
@ -59,10 +59,6 @@ export async function buildServer (ctx: ViteBuildContext) {
|
||||
},
|
||||
resolve: {
|
||||
conditions: ((ctx.nuxt as any)._nitro as Nitro)?.options.exportConditions,
|
||||
alias: {
|
||||
'#internal/nuxt/paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
|
||||
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/server'),
|
||||
},
|
||||
},
|
||||
ssr: {
|
||||
external: [
|
||||
|
@ -41,7 +41,7 @@ export function viteNodePlugin (ctx: ViteBuildContext): VitePlugin {
|
||||
configureServer (server) {
|
||||
function invalidateVirtualModules () {
|
||||
for (const [id, mod] of server.moduleGraph.idToModuleMap) {
|
||||
if (id.startsWith('virtual:')) {
|
||||
if (id.startsWith('virtual:') || id.startsWith('\0virtual:')) {
|
||||
markInvalidate(mod)
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import { resolveTSConfig } from 'pkg-types'
|
||||
|
||||
import { buildClient } from './client'
|
||||
import { buildServer } from './server'
|
||||
import virtual from './plugins/virtual'
|
||||
import { warmupViteServer } from './utils/warmup'
|
||||
import { resolveCSSOptions } from './css'
|
||||
import { composableKeysPlugin } from './plugins/composable-keys'
|
||||
@ -66,10 +65,6 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
||||
alias: {
|
||||
...nuxt.options.alias,
|
||||
'#app': nuxt.options.appDir,
|
||||
// We need this resolution to be present before the following entry, but it
|
||||
// will be filled in client/server configs
|
||||
'#build/plugins': '',
|
||||
'#build': nuxt.options.buildDir,
|
||||
'web-streams-polyfill/ponyfill/es2018': 'unenv/runtime/mock/empty',
|
||||
// Cannot destructure property 'AbortController' of ..
|
||||
'abort-controller': 'unenv/runtime/mock/empty',
|
||||
@ -111,7 +106,6 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
||||
composables: nuxt.options.optimization.keyedComposables,
|
||||
}),
|
||||
replace({ preventAssignment: true, ...globalThisReplacements }),
|
||||
virtual(nuxt.vfs),
|
||||
],
|
||||
server: {
|
||||
watch: { ignored: isIgnored },
|
||||
@ -225,7 +219,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
||||
// Invalidate virtual modules when templates are re-generated
|
||||
ctx.nuxt.hook('app:templatesGenerated', () => {
|
||||
for (const [id, mod] of server.moduleGraph.idToModuleMap) {
|
||||
if (id.startsWith('virtual:')) {
|
||||
if (id.startsWith('virtual:') || id.startsWith('\0virtual:')) {
|
||||
server.moduleGraph.invalidateModule(mod)
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ export default defineBuildConfig({
|
||||
dependencies: [
|
||||
'@nuxt/kit',
|
||||
'unplugin',
|
||||
'webpack-virtual-modules',
|
||||
'postcss',
|
||||
'postcss-loader',
|
||||
'vue-loader',
|
||||
|
@ -66,7 +66,6 @@
|
||||
"webpack-bundle-analyzer": "^4.10.2",
|
||||
"webpack-dev-middleware": "^7.4.2",
|
||||
"webpack-hot-middleware": "^2.26.1",
|
||||
"webpack-virtual-modules": "^0.6.2",
|
||||
"webpackbar": "^6.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -118,15 +118,9 @@ function basePlugins (ctx: WebpackConfigContext) {
|
||||
function baseAlias (ctx: WebpackConfigContext) {
|
||||
ctx.alias = {
|
||||
'#app': ctx.options.appDir,
|
||||
'#build/plugins': resolve(ctx.options.buildDir, 'plugins', ctx.isClient ? 'client' : 'server'),
|
||||
'#build': ctx.options.buildDir,
|
||||
'#internal/nuxt/paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
|
||||
...ctx.options.alias,
|
||||
...ctx.alias,
|
||||
}
|
||||
if (ctx.isClient) {
|
||||
ctx.alias['#internal/nitro'] = resolve(ctx.nuxt.options.buildDir, 'nitro.client.mjs')
|
||||
}
|
||||
}
|
||||
|
||||
function baseResolve (ctx: WebpackConfigContext) {
|
||||
|
@ -1,26 +0,0 @@
|
||||
import { useNuxt } from '@nuxt/kit'
|
||||
import VirtualModulesPlugin from 'webpack-virtual-modules'
|
||||
|
||||
export function registerVirtualModules () {
|
||||
const nuxt = useNuxt()
|
||||
|
||||
// Initialize virtual modules instance
|
||||
const virtualModules = new VirtualModulesPlugin(nuxt.vfs)
|
||||
const writeFiles = () => {
|
||||
for (const filePath in nuxt.vfs) {
|
||||
virtualModules.writeModule(filePath, nuxt.vfs[filePath] || '')
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround to initialize virtual modules
|
||||
nuxt.hook('webpack:compile', ({ compiler }) => {
|
||||
if (compiler.name === 'server') { writeFiles() }
|
||||
})
|
||||
// Update virtual modules when templates are updated
|
||||
nuxt.hook('app:templatesGenerated', writeFiles)
|
||||
|
||||
nuxt.hook('webpack:config', configs => configs.forEach((config) => {
|
||||
// Support virtual modules (input)
|
||||
config.plugins!.push(virtualModules)
|
||||
}))
|
||||
}
|
@ -15,7 +15,6 @@ import { composableKeysPlugin } from '../../vite/src/plugins/composable-keys'
|
||||
import { DynamicBasePlugin } from './plugins/dynamic-base'
|
||||
import { ChunkErrorPlugin } from './plugins/chunk'
|
||||
import { createMFS } from './utils/mfs'
|
||||
import { registerVirtualModules } from './virtual-modules'
|
||||
import { client, server } from './configs'
|
||||
import { applyPresets, createWebpackConfigContext, getWebpackConfig } from './utils/config'
|
||||
|
||||
@ -23,8 +22,6 @@ import { applyPresets, createWebpackConfigContext, getWebpackConfig } from './ut
|
||||
// const plugins: string[] = []
|
||||
|
||||
export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
||||
registerVirtualModules()
|
||||
|
||||
const webpackConfigs = await Promise.all([client, ...nuxt.options.ssr ? [server] : []].map(async (preset) => {
|
||||
const ctx = createWebpackConfigContext(nuxt)
|
||||
ctx.userConfig = defu(nuxt.options.webpack[`$${preset.name as 'client' | 'server'}`], ctx.userConfig)
|
||||
|
@ -912,9 +912,6 @@ importers:
|
||||
webpack-hot-middleware:
|
||||
specifier: ^2.26.1
|
||||
version: 2.26.1
|
||||
webpack-virtual-modules:
|
||||
specifier: ^0.6.2
|
||||
version: 0.6.2
|
||||
webpackbar:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1(webpack@5.95.0)
|
||||
|
Loading…
Reference in New Issue
Block a user