mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-15 10:24:50 +00:00
145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
import { pathToFileURL } from 'node:url'
|
|
import { createApp, createError, defineEventHandler, defineLazyEventHandler } from 'h3'
|
|
import { ViteNodeServer } from 'vite-node/server'
|
|
import fse from 'fs-extra'
|
|
import { resolve } from 'pathe'
|
|
import { addServerMiddleware } from '@nuxt/kit'
|
|
import type { Plugin as VitePlugin, ViteDevServer } from 'vite'
|
|
import { ExternalsOptions, isExternal, ExternalsDefaults } from 'externality'
|
|
import { resolve as resolveModule } from 'mlly'
|
|
import { distDir } from './dirs'
|
|
import type { ViteBuildContext } from './vite'
|
|
import { isCSS } from './utils'
|
|
|
|
// TODO: Remove this in favor of registerViteNodeMiddleware
|
|
// after Nitropack or h3 fixed for adding middlewares after setup
|
|
export function viteNodePlugin (ctx: ViteBuildContext): VitePlugin {
|
|
return {
|
|
name: 'nuxt:vite-node-server',
|
|
enforce: 'pre',
|
|
configureServer (server) {
|
|
server.middlewares.use('/__nuxt_vite_node__', createViteNodeMiddleware(ctx))
|
|
}
|
|
}
|
|
}
|
|
|
|
export function registerViteNodeMiddleware (ctx: ViteBuildContext) {
|
|
addServerMiddleware({
|
|
route: '/__nuxt_vite_node__/',
|
|
handler: createViteNodeMiddleware(ctx)
|
|
})
|
|
}
|
|
|
|
function getManifest (server: ViteDevServer) {
|
|
const ids = Array.from(server.moduleGraph.urlToModuleMap.keys())
|
|
.filter(i => isCSS(i))
|
|
|
|
const entries = [
|
|
'@vite/client',
|
|
'entry.mjs',
|
|
...ids.map(i => i.slice(1))
|
|
]
|
|
|
|
return {
|
|
publicPath: '',
|
|
all: entries,
|
|
initial: entries,
|
|
async: [],
|
|
modules: {}
|
|
}
|
|
}
|
|
|
|
function createViteNodeMiddleware (ctx: ViteBuildContext) {
|
|
const app = createApp()
|
|
|
|
app.use('/manifest', defineEventHandler(() => {
|
|
const manifest = getManifest(ctx.ssrServer)
|
|
return manifest
|
|
}))
|
|
|
|
app.use('/module', defineLazyEventHandler(() => {
|
|
const viteServer = ctx.ssrServer
|
|
const node: ViteNodeServer = new ViteNodeServer(viteServer, {
|
|
deps: {
|
|
inline: [
|
|
/\/(nuxt|nuxt3)\//,
|
|
/^#/,
|
|
...ctx.nuxt.options.build.transpile as string[]
|
|
]
|
|
},
|
|
transformMode: {
|
|
ssr: [/.*/],
|
|
web: []
|
|
}
|
|
})
|
|
const externalOpts: ExternalsOptions = {
|
|
inline: [
|
|
/virtual:/,
|
|
/\.ts$/,
|
|
...ExternalsDefaults.inline,
|
|
...viteServer.config.ssr.noExternal as string[]
|
|
],
|
|
external: [
|
|
...viteServer.config.ssr.external,
|
|
/node_modules/
|
|
],
|
|
resolve: {
|
|
type: 'module',
|
|
extensions: ['.ts', '.js', '.json', '.vue', '.mjs', '.jsx', '.tsx', '.wasm']
|
|
}
|
|
}
|
|
const rootDir = ctx.nuxt.options.rootDir
|
|
node.shouldExternalize = async (id: string) => {
|
|
const result = await isExternal(id, rootDir, externalOpts)
|
|
if (result?.external) {
|
|
return resolveModule(result.id, { url: rootDir })
|
|
}
|
|
return false
|
|
}
|
|
|
|
return async (event) => {
|
|
const moduleId = decodeURI(event.req.url).substring(1)
|
|
if (moduleId === '/') {
|
|
throw createError({ statusCode: 400 })
|
|
}
|
|
const module = await node.fetchModule(moduleId) as any
|
|
return module
|
|
}
|
|
}))
|
|
|
|
return app.nodeHandler
|
|
}
|
|
|
|
export async function prepareDevServerEntry (ctx: ViteBuildContext) {
|
|
let entryPath = resolve(ctx.nuxt.options.appDir, 'entry.async.mjs')
|
|
if (!fse.existsSync(entryPath)) {
|
|
entryPath = resolve(ctx.nuxt.options.appDir, 'entry.async')
|
|
}
|
|
|
|
// TODO: Update me
|
|
const host = ctx.nuxt.options.server.host || 'localhost'
|
|
const port = ctx.nuxt.options.server.port || '3000'
|
|
const protocol = ctx.nuxt.options.server.https ? 'https' : 'http'
|
|
|
|
// Serialize and pass vite-node runtime options
|
|
const viteNodeServerOptions = {
|
|
baseURL: `${protocol}://${host}:${port}/__nuxt_vite_node__`,
|
|
rootDir: ctx.nuxt.options.rootDir,
|
|
entryPath,
|
|
base: ctx.ssrServer.config.base || '/_nuxt/'
|
|
}
|
|
process.env.NUXT_VITE_NODE_OPTIONS = JSON.stringify(viteNodeServerOptions)
|
|
|
|
const serverResolvedPath = resolve(distDir, 'runtime/vite-node.mjs')
|
|
const manifestResolvedPath = resolve(distDir, 'runtime/client.manifest.mjs')
|
|
|
|
await fse.writeFile(
|
|
resolve(ctx.nuxt.options.buildDir, 'dist/server/server.mjs'),
|
|
`export { default } from ${JSON.stringify(pathToFileURL(serverResolvedPath).href)}`
|
|
)
|
|
await fse.writeFile(
|
|
resolve(ctx.nuxt.options.buildDir, 'dist/server/client.manifest.mjs'),
|
|
`export { default } from ${JSON.stringify(pathToFileURL(manifestResolvedPath).href)}`
|
|
)
|
|
}
|