mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 17:35:57 +00:00
feat: update vite implementation (#130)
This commit is contained in:
parent
87bee5eb0b
commit
9732d63c74
@ -5,7 +5,8 @@
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": "./dist",
|
||||
"./meta": "./meta.js"
|
||||
"./meta": "./meta.js",
|
||||
"./dist/*": "./dist/*"
|
||||
},
|
||||
"main": "./dist",
|
||||
"module": "./dist",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { $fetch } from 'ohmyfetch'
|
||||
import logs from 'nuxt/app/plugins/logs.client.dev'
|
||||
import progress from 'nuxt/app/plugins/progress.client'
|
||||
import logs from '#app/plugins/logs.client.dev'
|
||||
import progress from '#app/plugins/progress.client'
|
||||
<% const plugins = app.plugins.filter(p => p.mode === 'client').map(p => p.src) %>
|
||||
<%= nxt.importSources(plugins) %>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import head from 'nuxt/app/plugins/head'
|
||||
import router from 'nuxt/app/plugins/router'
|
||||
import vuex from 'nuxt/app/plugins/vuex'
|
||||
import legacy from 'nuxt/app/plugins/legacy'
|
||||
import head from '#app/plugins/head'
|
||||
import router from '#app/plugins/router'
|
||||
import vuex from '#app/plugins/vuex'
|
||||
import legacy from '#app/plugins/legacy'
|
||||
|
||||
<% const plugins = app.plugins.filter(p => p.mode === 'all').map(p => p.src) %>
|
||||
<%= nxt.importSources(plugins) %>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import preload from 'nuxt/app/plugins/preload.server'
|
||||
import preload from '#app/plugins/preload.server'
|
||||
<% const plugins = app.plugins.filter(p => p.mode === 'server').map(p => p.src) %>
|
||||
<%= nxt.importSources(plugins) %>
|
||||
|
||||
|
@ -7,9 +7,9 @@ import {
|
||||
} from 'vue-router'
|
||||
import type { Plugin } from '@nuxt/app'
|
||||
// @ts-ignore
|
||||
import routes from 'nuxt/build/routes'
|
||||
// @ts-ignore
|
||||
import NuxtPage from './NuxtPage.vue'
|
||||
import routes from '#build/routes'
|
||||
// @ts-ignore
|
||||
|
||||
export default <Plugin> function router (nuxt) {
|
||||
const { app } = nuxt
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { join, relative } from 'path'
|
||||
import { join, relative, resolve } from 'upath'
|
||||
import fsExtra from 'fs-extra'
|
||||
import { debounce } from 'lodash'
|
||||
import { Nuxt } from '@nuxt/kit'
|
||||
@ -46,6 +46,7 @@ async function _build (builder: Builder) {
|
||||
if (!nuxt.options.dev) {
|
||||
await fsExtra.emptyDir(nuxt.options.buildDir)
|
||||
}
|
||||
await fsExtra.emptyDir(resolve(nuxt.options.buildDir, 'dist'))
|
||||
await generate(builder)
|
||||
|
||||
if (nuxt.options.dev) {
|
||||
|
@ -11,14 +11,18 @@
|
||||
"prepack": "unbuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/debounce": "^1.2.0",
|
||||
"unbuild": "^0.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "^0.5.3",
|
||||
"@vitejs/plugin-vue": "^1.2.2",
|
||||
"@vue/compiler-sfc": "^3.0.11",
|
||||
"chokidar": "^3.5.1",
|
||||
"consola": "^2.15.3",
|
||||
"debounce": "^1.2.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"upath": "^2.0.1",
|
||||
"vite": "^2.2.3",
|
||||
"vue": "3.0.11"
|
||||
}
|
||||
|
54
packages/vite/src/client.ts
Normal file
54
packages/vite/src/client.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { resolve } from 'path'
|
||||
import * as vite from 'vite'
|
||||
import vitePlugin from '@vitejs/plugin-vue'
|
||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||
import { replace } from './plugins/replace'
|
||||
import { ViteBuildContext, ViteOptions } from './vite'
|
||||
|
||||
export async function buildClient (ctx: ViteBuildContext) {
|
||||
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||
define: {
|
||||
'process.server': false,
|
||||
'process.client': true,
|
||||
'module.hot': false,
|
||||
global: 'globalThis'
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/client',
|
||||
assetsDir: '.',
|
||||
rollupOptions: {
|
||||
input: resolve(ctx.nuxt.options.buildDir, 'client.js')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
replace({ 'process.env': 'import.meta.env' }),
|
||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'client'),
|
||||
vitePlugin(ctx.config.vue)
|
||||
],
|
||||
server: {
|
||||
middlewareMode: true
|
||||
}
|
||||
} as ViteOptions)
|
||||
|
||||
await ctx.nuxt.callHook('vite:extendConfig', clientConfig, { isClient: true, isServer: false })
|
||||
|
||||
const viteServer = await vite.createServer(clientConfig)
|
||||
await ctx.nuxt.callHook('vite:serverCreated', viteServer)
|
||||
|
||||
const viteMiddleware = (req, res, next) => {
|
||||
// Workaround: vite devmiddleware modifies req.url
|
||||
const originalURL = req.url
|
||||
if (req.url === '/_nuxt/client.js') {
|
||||
return res.end('')
|
||||
}
|
||||
viteServer.middlewares.handle(req, res, (err) => {
|
||||
req.url = originalURL
|
||||
next(err)
|
||||
})
|
||||
}
|
||||
await ctx.nuxt.callHook('server:devMiddleware', viteMiddleware)
|
||||
|
||||
ctx.nuxt.hook('close', async () => {
|
||||
await viteServer.close()
|
||||
})
|
||||
}
|
13
packages/vite/src/plugins/cache-dir.ts
Normal file
13
packages/vite/src/plugins/cache-dir.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import type { Plugin } from 'vite'
|
||||
import { resolve } from 'upath'
|
||||
|
||||
export function cacheDirPlugin (rootDir, name: string) {
|
||||
const optimizeCacheDir = resolve(rootDir, 'node_modules/.cache/vite', name)
|
||||
return <Plugin> {
|
||||
name: 'nuxt:cache-dir',
|
||||
configResolved (resolvedConfig) {
|
||||
// @ts-ignore
|
||||
resolvedConfig.optimizeCacheDir = optimizeCacheDir
|
||||
}
|
||||
}
|
||||
}
|
17
packages/vite/src/plugins/replace.ts
Normal file
17
packages/vite/src/plugins/replace.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import type { Plugin } from 'vite'
|
||||
|
||||
export function replace (replacements: Record<string, string>) {
|
||||
return <Plugin>{
|
||||
name: 'nuxt:replace',
|
||||
transform (code) {
|
||||
Object.entries(replacements).forEach(([key, value]) => {
|
||||
const escapedKey = key.replace(/\./g, '\\.')
|
||||
code = code.replace(new RegExp(escapedKey, 'g'), value)
|
||||
})
|
||||
return {
|
||||
code,
|
||||
map: null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
85
packages/vite/src/server.ts
Normal file
85
packages/vite/src/server.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { resolve } from 'path'
|
||||
import * as vite from 'vite'
|
||||
import vuePlugin from '@vitejs/plugin-vue'
|
||||
import { watch } from 'chokidar'
|
||||
import { mkdirp, writeFile } from 'fs-extra'
|
||||
import debounce from 'debounce'
|
||||
import consola from 'consola'
|
||||
import { ViteBuildContext, ViteOptions } from './vite'
|
||||
import { wpfs } from './utils/wpfs'
|
||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||
|
||||
export async function buildServer (ctx: ViteBuildContext) {
|
||||
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||
define: {
|
||||
'process.server': true,
|
||||
'process.client': false,
|
||||
'typeof window': '"undefined"',
|
||||
'typeof document': '"undefined"',
|
||||
'typeof navigator': '"undefined"',
|
||||
'typeof location': '"undefined"',
|
||||
'typeof XMLHttpRequest': '"undefined"'
|
||||
},
|
||||
ssr: {
|
||||
external: [
|
||||
'axios'
|
||||
]
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/server',
|
||||
ssr: true,
|
||||
rollupOptions: {
|
||||
input: resolve(ctx.nuxt.options.buildDir, 'entry.server.mjs'),
|
||||
onwarn (warning, rollupWarn) {
|
||||
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code)) {
|
||||
rollupWarn(warning)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'server'),
|
||||
vuePlugin()
|
||||
]
|
||||
} as ViteOptions)
|
||||
|
||||
await ctx.nuxt.callHook('vite:extendConfig', serverConfig, { isClient: false, isServer: true })
|
||||
|
||||
const serverDist = resolve(ctx.nuxt.options.buildDir, 'dist/server')
|
||||
await mkdirp(serverDist)
|
||||
|
||||
await writeFile(resolve(serverDist, 'server.js'), 'try { module.exports = require("./entry.server") } catch (err) { module.exports = () => { throw err } }', 'utf8')
|
||||
await writeFile(resolve(serverDist, 'client.manifest.json'), 'false', 'utf8')
|
||||
|
||||
const onBuild = () => ctx.nuxt.callHook('build:resources', wpfs)
|
||||
|
||||
if (!ctx.nuxt.options.ssr) {
|
||||
await onBuild()
|
||||
return
|
||||
}
|
||||
|
||||
const build = debounce(async () => {
|
||||
const start = Date.now()
|
||||
await vite.build(serverConfig)
|
||||
await onBuild()
|
||||
consola.info(`Server built in ${Date.now() - start}ms`)
|
||||
}, 300)
|
||||
|
||||
await build()
|
||||
|
||||
const watcher = watch([
|
||||
ctx.nuxt.options.buildDir,
|
||||
ctx.nuxt.options.srcDir,
|
||||
ctx.nuxt.options.rootDir
|
||||
], {
|
||||
ignored: [
|
||||
'**/dist/server/**'
|
||||
]
|
||||
})
|
||||
|
||||
watcher.on('change', () => build())
|
||||
|
||||
ctx.nuxt.hook('close', async () => {
|
||||
await watcher.close()
|
||||
})
|
||||
}
|
15
packages/vite/src/utils/warmup.ts
Normal file
15
packages/vite/src/utils/warmup.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { ViteDevServer } from 'vite'
|
||||
|
||||
export async function warmupViteServer (server: ViteDevServer, entries: string[]) {
|
||||
const warmedUrls = new Set<String>()
|
||||
|
||||
const warmup = async (url: string) => {
|
||||
if (warmedUrls.has(url)) { return undefined }
|
||||
warmedUrls.add(url)
|
||||
await server.transformRequest(url)
|
||||
const deps = Array.from(server.moduleGraph.urlToModuleMap.get(url).importedModules)
|
||||
await Promise.all(deps.map(m => warmup(m.url)))
|
||||
}
|
||||
|
||||
await Promise.all(entries.map(entry => warmup(entry)))
|
||||
}
|
7
packages/vite/src/utils/wpfs.ts
Normal file
7
packages/vite/src/utils/wpfs.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { join } from 'upath'
|
||||
import fsExtra from 'fs-extra'
|
||||
|
||||
export const wpfs = {
|
||||
...fsExtra,
|
||||
join
|
||||
}
|
@ -1,131 +1,74 @@
|
||||
import { resolve } from 'path'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import { mkdirp, writeFile } from 'fs-extra'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import consola from 'consola'
|
||||
import * as vite from 'vite'
|
||||
import consola from 'consola'
|
||||
import type { Nuxt } from '@nuxt/kit'
|
||||
import type { InlineConfig, SSROptions } from 'vite'
|
||||
import type { Options } from '@vitejs/plugin-vue'
|
||||
import { buildClient } from './client'
|
||||
import { buildServer } from './server'
|
||||
import { warmupViteServer } from './utils/warmup'
|
||||
|
||||
interface ViteBuildContext {
|
||||
export interface ViteOptions extends InlineConfig {
|
||||
vue?: Options
|
||||
ssr?: SSROptions
|
||||
}
|
||||
|
||||
export interface ViteBuildContext {
|
||||
nuxt: Nuxt
|
||||
config: vite.InlineConfig
|
||||
config: ViteOptions
|
||||
}
|
||||
|
||||
export async function bundle (nuxt: Nuxt) {
|
||||
const ctx: ViteBuildContext = {
|
||||
nuxt,
|
||||
config: {
|
||||
config: vite.mergeConfig(
|
||||
nuxt.options.vite as any || {},
|
||||
{
|
||||
root: nuxt.options.buildDir,
|
||||
mode: nuxt.options.dev ? 'development' : 'production',
|
||||
logLevel: 'warn',
|
||||
define: {
|
||||
'process.dev': nuxt.options.dev
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
||||
alias: {
|
||||
'nuxt/app': nuxt.options.appDir,
|
||||
'nuxt/build': nuxt.options.buildDir,
|
||||
...nuxt.options.alias,
|
||||
'#build': nuxt.options.buildDir,
|
||||
'#app': nuxt.options.appDir,
|
||||
'~': nuxt.options.srcDir,
|
||||
'@': nuxt.options.srcDir
|
||||
'@': nuxt.options.srcDir,
|
||||
'web-streams-polyfill/ponyfill/es2018': 'unenv/runtime/mock/empty',
|
||||
// Cannot destructure property 'AbortController' of ..
|
||||
'abort-controller': 'unenv/runtime/mock/empty'
|
||||
}
|
||||
},
|
||||
vue: {},
|
||||
css: {},
|
||||
optimizeDeps: {
|
||||
exclude: []
|
||||
},
|
||||
esbuild: {
|
||||
jsxFactory: 'h',
|
||||
jsxFragment: 'Fragment'
|
||||
},
|
||||
clearScreen: false,
|
||||
plugins: [
|
||||
vue({})
|
||||
],
|
||||
build: {
|
||||
emptyOutDir: false
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: []
|
||||
} as ViteOptions
|
||||
)
|
||||
}
|
||||
|
||||
await nuxt.callHook('vite:extend', ctx)
|
||||
|
||||
await mkdirp(nuxt.options.buildDir)
|
||||
await mkdirp(resolve(nuxt.options.buildDir, '.vite/temp'))
|
||||
|
||||
const callBuild = async (fn, name) => {
|
||||
try {
|
||||
nuxt.hook('vite:serverCreated', (server: vite.ViteDevServer) => {
|
||||
const start = Date.now()
|
||||
await fn(ctx)
|
||||
const time = (Date.now() - start) / 1000
|
||||
consola.success(`${name} compiled successfully in ${time}s`)
|
||||
} catch (err) {
|
||||
consola.error(`${name} compiled with errors:`, err)
|
||||
}
|
||||
}
|
||||
|
||||
if (nuxt.options.dev) {
|
||||
await Promise.all([
|
||||
callBuild(buildClient, 'Client'),
|
||||
callBuild(buildServer, 'Server')
|
||||
])
|
||||
} else {
|
||||
await callBuild(buildClient, 'Client')
|
||||
await callBuild(buildServer, 'Server')
|
||||
}
|
||||
}
|
||||
|
||||
async function buildClient (ctx: ViteBuildContext) {
|
||||
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||
define: {
|
||||
'process.server': false,
|
||||
'process.client': true
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/client',
|
||||
assetsDir: '.',
|
||||
rollupOptions: {
|
||||
input: resolve(ctx.nuxt.options.buildDir, './entry.client')
|
||||
}
|
||||
},
|
||||
server: {
|
||||
middlewareMode: true
|
||||
}
|
||||
} as vite.InlineConfig)
|
||||
|
||||
if (ctx.nuxt.options.dev) {
|
||||
const viteServer = await vite.createServer(clientConfig)
|
||||
await ctx.nuxt.callHook('server:devMiddleware', (req, res, next) => {
|
||||
// Workaround: vite devmiddleware modifies req.url
|
||||
const originalURL = req.url
|
||||
viteServer.middlewares.handle(req, res, (err) => {
|
||||
req.url = originalURL
|
||||
next(err)
|
||||
warmupViteServer(server, ['/entry.client.mjs']).then(() => {
|
||||
consola.info(`Vite warmed up in ${Date.now() - start}ms`)
|
||||
}).catch(consola.error)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
await vite.build(clientConfig)
|
||||
}
|
||||
}
|
||||
|
||||
async function buildServer (ctx: ViteBuildContext) {
|
||||
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||
define: {
|
||||
'process.server': true,
|
||||
'process.client': false,
|
||||
window: undefined
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/server',
|
||||
ssr: true,
|
||||
rollupOptions: {
|
||||
input: resolve(ctx.nuxt.options.buildDir, './entry.server'),
|
||||
onwarn (warning, rollupWarn) {
|
||||
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code)) {
|
||||
rollupWarn(warning)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} as vite.InlineConfig)
|
||||
|
||||
const serverDist = resolve(ctx.nuxt.options.buildDir, 'dist/server')
|
||||
await mkdirp(serverDist)
|
||||
await writeFile(resolve(serverDist, 'client.manifest.json'), 'false')
|
||||
await writeFile(resolve(serverDist, 'server.js'), 'const entry = require("./entry.server"); module.exports = entry.default || entry;')
|
||||
|
||||
await vite.build(serverConfig)
|
||||
|
||||
if (ctx.nuxt.options.dev) {
|
||||
ctx.nuxt.hook('builder:watch', () => {
|
||||
vite.build(serverConfig).catch(consola.error)
|
||||
})
|
||||
}
|
||||
|
||||
await buildClient(ctx)
|
||||
await buildServer(ctx)
|
||||
}
|
||||
|
@ -34,8 +34,6 @@ function serverStandalone (ctx: WebpackConfigContext) {
|
||||
// TODO: Refactor this out of webpack
|
||||
const inline = [
|
||||
'src/',
|
||||
'nuxt/app',
|
||||
'nuxt/build',
|
||||
'@nuxt/app',
|
||||
'vuex5',
|
||||
'!',
|
||||
|
@ -109,8 +109,8 @@ function baseAlias (ctx: WebpackConfigContext) {
|
||||
const { options } = ctx
|
||||
|
||||
ctx.alias = {
|
||||
'nuxt/app': options.appDir,
|
||||
'nuxt/build': options.buildDir,
|
||||
'#app': options.appDir,
|
||||
'#build': options.buildDir,
|
||||
...options.alias,
|
||||
...ctx.alias
|
||||
}
|
||||
|
@ -1716,11 +1716,15 @@ __metadata:
|
||||
resolution: "@nuxt/vite-builder@workspace:packages/vite"
|
||||
dependencies:
|
||||
"@nuxt/kit": ^0.5.3
|
||||
"@types/debounce": ^1.2.0
|
||||
"@vitejs/plugin-vue": ^1.2.2
|
||||
"@vue/compiler-sfc": ^3.0.11
|
||||
chokidar: ^3.5.1
|
||||
consola: ^2.15.3
|
||||
debounce: ^1.2.1
|
||||
fs-extra: ^9.1.0
|
||||
unbuild: ^0.2.3
|
||||
upath: ^2.0.1
|
||||
vite: ^2.2.3
|
||||
vue: 3.0.11
|
||||
languageName: unknown
|
||||
|
Loading…
Reference in New Issue
Block a user