2020-11-20 00:16:31 +00:00
|
|
|
import fetch from 'node-fetch'
|
|
|
|
import { resolve } from 'upath'
|
2021-07-28 12:00:39 +00:00
|
|
|
import { move, readFile, writeFile } from 'fs-extra'
|
2021-01-22 19:53:40 +00:00
|
|
|
import { build, generate, prepare } from './build'
|
2021-01-22 19:55:59 +00:00
|
|
|
import { getNitroContext, NitroContext } from './context'
|
2021-02-18 16:06:58 +00:00
|
|
|
import { createDevServer } from './server/dev'
|
2021-01-22 19:53:40 +00:00
|
|
|
import { wpfs } from './utils/wpfs'
|
2021-02-18 16:06:58 +00:00
|
|
|
import { resolveMiddleware } from './server/middleware'
|
2021-01-21 13:07:48 +00:00
|
|
|
|
2021-01-22 19:53:40 +00:00
|
|
|
export default function nuxt2CompatModule () {
|
|
|
|
const { nuxt } = this
|
|
|
|
|
2021-03-05 11:13:35 +00:00
|
|
|
// Ensure we're not just building with 'static' target
|
|
|
|
if (!nuxt.options.dev && nuxt.options.target === 'static' && !nuxt.options._export && !nuxt.options._legacyGenerate) {
|
|
|
|
throw new Error('[nitro] Please use `nuxt generate` for static target')
|
|
|
|
}
|
|
|
|
|
2021-01-22 19:53:40 +00:00
|
|
|
// Disable loading-screen
|
|
|
|
nuxt.options.build.loadingScreen = false
|
|
|
|
nuxt.options.build.indicator = false
|
2020-11-20 00:16:31 +00:00
|
|
|
|
|
|
|
// Create contexts
|
2021-04-19 20:39:11 +00:00
|
|
|
const nitroOptions = (nuxt.options as any).nitro || {}
|
|
|
|
const nitroContext = getNitroContext(nuxt.options, nitroOptions)
|
|
|
|
const nitroDevContext = getNitroContext(nuxt.options, { ...nitroOptions, preset: 'dev' })
|
2020-11-20 00:16:31 +00:00
|
|
|
|
2021-08-09 18:24:52 +00:00
|
|
|
// Normalize Nuxt directories
|
|
|
|
for (const context of [nitroContext, nitroDevContext]) {
|
|
|
|
context._nuxt.rootDir = resolve(context._nuxt.rootDir)
|
|
|
|
context._nuxt.srcDir = resolve(context._nuxt.srcDir)
|
|
|
|
context._nuxt.buildDir = resolve(context._nuxt.buildDir)
|
|
|
|
context._nuxt.generateDir = resolve(context._nuxt.generateDir)
|
|
|
|
}
|
|
|
|
|
2020-11-20 02:22:22 +00:00
|
|
|
// Connect hooks
|
2021-01-22 19:55:59 +00:00
|
|
|
nuxt.addHooks(nitroContext.nuxtHooks)
|
|
|
|
nuxt.hook('close', () => nitroContext._internal.hooks.callHook('close'))
|
2021-06-16 11:48:16 +00:00
|
|
|
nitroContext._internal.hooks.hook('nitro:document', template => nuxt.callHook('nitro:document', template))
|
2020-11-20 02:22:22 +00:00
|
|
|
|
2021-01-22 19:55:59 +00:00
|
|
|
nuxt.addHooks(nitroDevContext.nuxtHooks)
|
|
|
|
nuxt.hook('close', () => nitroDevContext._internal.hooks.callHook('close'))
|
2021-06-16 11:48:16 +00:00
|
|
|
nitroDevContext._internal.hooks.hook('nitro:document', template => nuxt.callHook('nitro:document', template))
|
2021-01-22 19:55:59 +00:00
|
|
|
nitroDevContext._internal.hooks.hook('renderLoading',
|
2020-11-20 02:22:22 +00:00
|
|
|
(req, res) => nuxt.callHook('server:nuxt:renderLoading', req, res))
|
2020-11-20 00:16:31 +00:00
|
|
|
|
2021-01-22 19:55:59 +00:00
|
|
|
// Expose process.env.NITRO_PRESET
|
|
|
|
nuxt.options.env.NITRO_PRESET = nitroContext.preset
|
2020-11-20 14:34:47 +00:00
|
|
|
|
2020-11-28 21:11:14 +00:00
|
|
|
// .ts is supported for serverMiddleware
|
|
|
|
nuxt.options.extensions.push('ts')
|
|
|
|
|
2020-11-20 00:16:31 +00:00
|
|
|
// Replace nuxt server
|
|
|
|
if (nuxt.server) {
|
|
|
|
nuxt.server.__closed = true
|
2021-01-22 19:55:59 +00:00
|
|
|
nuxt.server = createNuxt2DevServer(nitroDevContext)
|
2020-11-20 00:16:31 +00:00
|
|
|
}
|
|
|
|
|
2021-01-24 20:30:20 +00:00
|
|
|
// Disable server sourceMap, esbuild will generate for it.
|
2021-01-24 21:12:07 +00:00
|
|
|
nuxt.hook('webpack:config', (webpackConfigs) => {
|
2021-01-30 22:05:40 +00:00
|
|
|
const serverConfig = webpackConfigs.find(config => config.name === 'server')
|
2021-07-21 20:05:22 +00:00
|
|
|
if (serverConfig) {
|
|
|
|
serverConfig.devtool = false
|
|
|
|
}
|
2021-01-24 21:12:07 +00:00
|
|
|
})
|
2021-01-24 20:30:20 +00:00
|
|
|
|
2021-01-22 19:55:59 +00:00
|
|
|
// Nitro client plugin
|
2021-01-22 19:53:40 +00:00
|
|
|
this.addPlugin({
|
2021-07-15 09:38:06 +00:00
|
|
|
fileName: 'nitro.client.mjs',
|
|
|
|
src: resolve(nitroContext._internal.runtimeDir, 'app/nitro.client.mjs')
|
2020-11-20 13:31:14 +00:00
|
|
|
})
|
|
|
|
|
2021-07-15 11:28:04 +00:00
|
|
|
// Nitro server plugin (for vue-meta)
|
|
|
|
this.addPlugin({
|
|
|
|
fileName: 'nitro-compat.server.js',
|
|
|
|
src: resolve(nitroContext._internal.runtimeDir, 'app/nitro-compat.server.js')
|
|
|
|
})
|
|
|
|
|
2021-04-06 12:57:10 +00:00
|
|
|
// Fix module resolution
|
|
|
|
nuxt.hook('webpack:config', (configs) => {
|
|
|
|
for (const config of configs) {
|
2021-07-15 09:38:06 +00:00
|
|
|
config.resolve.alias.ufo = 'ufo/dist/index.mjs'
|
|
|
|
config.resolve.alias.ohmyfetch = 'ohmyfetch/dist/index.mjs'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Generate mjs resources
|
|
|
|
nuxt.hook('build:compiled', async ({ name }) => {
|
|
|
|
if (name === 'server') {
|
2021-07-28 12:00:39 +00:00
|
|
|
const jsServerEntry = resolve(nuxt.options.buildDir, 'dist/server/server.js')
|
|
|
|
await move(jsServerEntry, jsServerEntry.replace(/.js$/, '.cjs'))
|
|
|
|
await writeFile(jsServerEntry.replace(/.js$/, '.mjs'), 'export { default } from "./server.cjs"', 'utf8')
|
2021-07-15 09:38:06 +00:00
|
|
|
} else if (name === 'client') {
|
|
|
|
const manifest = await readFile(resolve(nuxt.options.buildDir, 'dist/server/client.manifest.json'), 'utf8')
|
|
|
|
await writeFile(resolve(nuxt.options.buildDir, 'dist/server/client.manifest.mjs'), 'export default ' + manifest, 'utf8')
|
2021-04-06 12:57:10 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-04-19 20:39:11 +00:00
|
|
|
// Wait for all modules to be ready
|
|
|
|
nuxt.hook('modules:done', async () => {
|
|
|
|
// Extend nitro with modules
|
|
|
|
await nuxt.callHook('nitro:context', nitroContext)
|
|
|
|
await nuxt.callHook('nitro:context', nitroDevContext)
|
|
|
|
|
|
|
|
// Resolve middleware
|
2021-04-04 17:54:12 +00:00
|
|
|
const { middleware, legacyMiddleware } = resolveMiddleware(nuxt)
|
2021-01-24 19:18:20 +00:00
|
|
|
if (nuxt.server) {
|
|
|
|
nuxt.server.setLegacyMiddleware(legacyMiddleware)
|
|
|
|
}
|
2021-01-22 19:55:59 +00:00
|
|
|
nitroContext.middleware.push(...middleware)
|
|
|
|
nitroDevContext.middleware.push(...middleware)
|
2020-11-20 00:16:31 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// nuxt build/dev
|
|
|
|
nuxt.options.build._minifyServer = false
|
|
|
|
nuxt.options.build.standalone = false
|
|
|
|
nuxt.hook('build:done', async () => {
|
2020-11-20 02:22:22 +00:00
|
|
|
if (nuxt.options.dev) {
|
2021-01-22 19:55:59 +00:00
|
|
|
await build(nitroDevContext)
|
|
|
|
} else if (!nitroContext._nuxt.isStatic) {
|
|
|
|
await prepare(nitroContext)
|
|
|
|
await generate(nitroContext)
|
|
|
|
await build(nitroContext)
|
2020-11-20 02:22:22 +00:00
|
|
|
}
|
2020-11-20 00:16:31 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// nude dev
|
|
|
|
if (nuxt.options.dev) {
|
2021-01-22 19:55:59 +00:00
|
|
|
nitroDevContext._internal.hooks.hook('nitro:compiled', () => { nuxt.server.watch() })
|
2020-11-20 00:16:31 +00:00
|
|
|
nuxt.hook('build:compile', ({ compiler }) => { compiler.outputFileSystem = wpfs })
|
|
|
|
nuxt.hook('server:devMiddleware', (m) => { nuxt.server.setDevMiddleware(m) })
|
|
|
|
}
|
|
|
|
|
|
|
|
// nuxt generate
|
2021-01-22 19:55:59 +00:00
|
|
|
nuxt.options.generate.dir = nitroContext.output.publicDir
|
2020-12-02 13:19:18 +00:00
|
|
|
nuxt.options.generate.manifest = false
|
2020-11-20 00:16:31 +00:00
|
|
|
nuxt.hook('generate:cache:ignore', (ignore: string[]) => {
|
2021-01-22 19:55:59 +00:00
|
|
|
ignore.push(nitroContext.output.dir)
|
|
|
|
ignore.push(nitroContext.output.serverDir)
|
|
|
|
if (nitroContext.output.publicDir) {
|
|
|
|
ignore.push(nitroContext.output.publicDir)
|
2020-11-20 02:22:22 +00:00
|
|
|
}
|
2021-01-22 19:55:59 +00:00
|
|
|
ignore.push(...nitroContext.ignore)
|
2020-11-20 00:16:31 +00:00
|
|
|
})
|
2020-11-20 11:55:55 +00:00
|
|
|
nuxt.hook('generate:before', async () => {
|
2021-01-22 19:55:59 +00:00
|
|
|
await prepare(nitroContext)
|
2020-11-20 11:55:55 +00:00
|
|
|
})
|
2020-11-20 00:16:31 +00:00
|
|
|
nuxt.hook('generate:extendRoutes', async () => {
|
2021-01-22 19:55:59 +00:00
|
|
|
await build(nitroDevContext)
|
2020-11-20 00:16:31 +00:00
|
|
|
await nuxt.server.reload()
|
|
|
|
})
|
2020-11-20 01:38:06 +00:00
|
|
|
nuxt.hook('generate:done', async () => {
|
|
|
|
await nuxt.server.close()
|
2021-01-22 19:55:59 +00:00
|
|
|
await build(nitroContext)
|
2020-11-20 01:38:06 +00:00
|
|
|
})
|
2020-11-20 00:16:31 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 19:55:59 +00:00
|
|
|
function createNuxt2DevServer (nitroContext: NitroContext) {
|
|
|
|
const server = createDevServer(nitroContext)
|
2020-11-20 00:16:31 +00:00
|
|
|
|
|
|
|
const listeners = []
|
|
|
|
async function listen (port) {
|
2021-01-22 20:32:29 +00:00
|
|
|
const listener = await server.listen(port, {
|
|
|
|
showURL: false,
|
|
|
|
isProd: true
|
|
|
|
})
|
2020-11-20 00:16:31 +00:00
|
|
|
listeners.push(listener)
|
2021-01-22 20:32:29 +00:00
|
|
|
return listener
|
2020-11-20 00:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function renderRoute (route = '/', renderContext = {}) {
|
|
|
|
const [listener] = listeners
|
|
|
|
if (!listener) {
|
|
|
|
throw new Error('There is no server listener to call `server.renderRoute()`')
|
|
|
|
}
|
|
|
|
const html = await fetch(listener.url + route, {
|
|
|
|
headers: { 'nuxt-render-context': encodeQuery(renderContext) }
|
|
|
|
}).then(r => r.text())
|
|
|
|
|
|
|
|
return { html }
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
...server,
|
|
|
|
listeners,
|
|
|
|
renderRoute,
|
|
|
|
listen,
|
|
|
|
serverMiddlewarePaths () { return [] },
|
2021-01-22 19:53:40 +00:00
|
|
|
ready () { }
|
2020-11-20 00:16:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function encodeQuery (obj) {
|
|
|
|
return Object.entries(obj).map(
|
|
|
|
([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`
|
|
|
|
).join('&')
|
|
|
|
}
|