mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-12 03:38:07 +00:00
feat: initial support for vite bundler (#127)
This commit is contained in:
parent
9c4a14074c
commit
9be282623c
@ -1,3 +1,4 @@
|
|||||||
|
<%= nuxtOptions.vite ? "import('vite/dynamic-import-polyfill')" : '' %>
|
||||||
import { createSSRApp, nextTick } from 'vue'
|
import { createSSRApp, nextTick } from 'vue'
|
||||||
import { createNuxt, applyPlugins } from 'nuxt/app/nuxt'
|
import { createNuxt, applyPlugins } from 'nuxt/app/nuxt'
|
||||||
import plugins from './plugins'
|
import plugins from './plugins'
|
@ -1,5 +1,4 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
|
|
||||||
import { createNuxt, applyPlugins } from 'nuxt/app/nuxt'
|
import { createNuxt, applyPlugins } from 'nuxt/app/nuxt'
|
||||||
import plugins from './plugins'
|
import plugins from './plugins'
|
||||||
import serverPlugins from './plugins.server'
|
import serverPlugins from './plugins.server'
|
@ -5,5 +5,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body {{ BODY_ATTRS }}>
|
<body {{ BODY_ATTRS }}>
|
||||||
<div id="__nuxt">{{ APP }}</div>
|
<div id="__nuxt">{{ APP }}</div>
|
||||||
|
<% if (nuxtOptions.vite && nuxtOptions.dev) { %><script type="module" src="/@vite/client"></script>
|
||||||
|
<script type="module" src="/entry.client.js"></script><% } %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Ref, toRef, onMounted, watch, getCurrentInstance, onUnmounted } from 'vue'
|
import { Ref, toRef, onMounted, watch, getCurrentInstance, onUnmounted } from 'vue'
|
||||||
import { Nuxt, useNuxt } from 'nuxt/app'
|
import { Nuxt, useNuxt } from 'nuxt/app'
|
||||||
import { httpFetch } from '../utils/fetch'
|
import { $fetch } from 'ohmyfetch'
|
||||||
import { useData } from './data'
|
import { useData } from './data'
|
||||||
|
|
||||||
export type HTTPRequest = string | { method: string, url: string }
|
export type HTTPRequest = string | { method: string, url: string }
|
||||||
@ -44,7 +44,7 @@ export function useFetch (defaults?: FetchOptions) {
|
|||||||
options = {
|
options = {
|
||||||
server: true,
|
server: true,
|
||||||
defer: false,
|
defer: false,
|
||||||
fetcher: httpFetch,
|
fetcher: globalThis.$fetch || $fetch,
|
||||||
...defaults,
|
...defaults,
|
||||||
...options
|
...options
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
// TODO: Move to a nuxt-contrib utility
|
|
||||||
import destr from 'destr'
|
|
||||||
|
|
||||||
// TODO: polyfill by env (nuxt) not by util
|
|
||||||
const _fetch = process.server ? require('node-fetch') : global.fetch
|
|
||||||
|
|
||||||
export async function httpFetch (path: string) {
|
|
||||||
const res = await _fetch(path)
|
|
||||||
if (!res.ok) {
|
|
||||||
throw new Error(res)
|
|
||||||
}
|
|
||||||
const data = await res.text()
|
|
||||||
|
|
||||||
return destr(data)
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
import { join, relative } from 'path'
|
import { join, relative } from 'path'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import { BundleBuilder } from 'src/webpack'
|
|
||||||
import { Nuxt } from '../core'
|
import { Nuxt } from '../core'
|
||||||
import { DeterminedGlobals, determineGlobals } from '../utils'
|
import { DeterminedGlobals, determineGlobals } from '../utils'
|
||||||
import {
|
import {
|
||||||
@ -73,6 +72,11 @@ function watch (builder: Builder) {
|
|||||||
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
||||||
// Watch for page changes
|
// Watch for page changes
|
||||||
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
||||||
|
|
||||||
|
// Shared Watcher
|
||||||
|
const watchHookDebounced = debounce((event, file) => builder.nuxt.callHook('builder:watch', event, file), 100)
|
||||||
|
appWatcher.watchAll(watchHookDebounced)
|
||||||
|
nuxtAppWatcher.watchAll(watchHookDebounced)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generate (builder: Builder) {
|
export async function generate (builder: Builder) {
|
||||||
@ -90,5 +94,11 @@ export async function generate (builder: Builder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function bundle ({ nuxt }: Builder) {
|
async function bundle ({ nuxt }: Builder) {
|
||||||
await new BundleBuilder(nuxt).build()
|
// @ts-ignore
|
||||||
|
const useVite = !!nuxt.options.vite
|
||||||
|
const bundle = await (useVite
|
||||||
|
? import('./vite/vite' /* webpackChunkName: "vite" */)
|
||||||
|
: import('./webpack/webpack' /* webpackChunkName: "webpack" */))
|
||||||
|
.then(p => p.bundle)
|
||||||
|
return bundle(nuxt)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@ export interface NuxtTemplate {
|
|||||||
export function templateData (builder) {
|
export function templateData (builder) {
|
||||||
return {
|
return {
|
||||||
globals: builder.globals,
|
globals: builder.globals,
|
||||||
app: builder.app
|
app: builder.app,
|
||||||
|
nuxtOptions: builder.nuxt.options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
129
packages/nuxt3/src/builder/vite/vite.ts
Normal file
129
packages/nuxt3/src/builder/vite/vite.ts
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { resolve } from 'path'
|
||||||
|
import { Nuxt } from 'src/core'
|
||||||
|
import { mkdirp, writeFile } from 'fs-extra'
|
||||||
|
import createRequire from 'create-require'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import consola from 'consola'
|
||||||
|
import * as vite from 'vite'
|
||||||
|
|
||||||
|
interface ViteBuildContext {
|
||||||
|
nuxt: Nuxt
|
||||||
|
config: vite.InlineConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function bundle (nuxt: Nuxt) {
|
||||||
|
const ctx: ViteBuildContext = {
|
||||||
|
nuxt,
|
||||||
|
config: {
|
||||||
|
root: nuxt.options.buildDir,
|
||||||
|
mode: nuxt.options.dev ? 'development' : 'production',
|
||||||
|
alias: {
|
||||||
|
'nuxt/app': nuxt.options.appDir,
|
||||||
|
'~build': nuxt.options.buildDir,
|
||||||
|
'~': nuxt.options.srcDir,
|
||||||
|
'@': nuxt.options.srcDir
|
||||||
|
},
|
||||||
|
clearScreen: false,
|
||||||
|
plugins: [
|
||||||
|
vue({})
|
||||||
|
],
|
||||||
|
build: {
|
||||||
|
emptyOutDir: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await mkdirp(nuxt.options.buildDir)
|
||||||
|
const { dependencies = {}, devDependencies = {} } = createRequire(nuxt.options.rootDir)('package.json')
|
||||||
|
await writeFile(resolve(nuxt.options.buildDir, 'package.json'), JSON.stringify({
|
||||||
|
private: true,
|
||||||
|
description: 'auto generated',
|
||||||
|
devDependencies: { ...dependencies, ...devDependencies }
|
||||||
|
}, null, 2))
|
||||||
|
|
||||||
|
const callBuild = async (fn, name) => {
|
||||||
|
try {
|
||||||
|
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: '.',
|
||||||
|
ssrManifest: true,
|
||||||
|
manifest: true,
|
||||||
|
rollupOptions: {
|
||||||
|
input: resolve(ctx.nuxt.options.buildDir, './entry.client.js')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} 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.js')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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.js"); 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ import { createWebpackConfigContext, applyPresets, getWebpackConfig } from './ut
|
|||||||
|
|
||||||
const glob = pify(Glob)
|
const glob = pify(Glob)
|
||||||
|
|
||||||
export class WebpackBundler {
|
class WebpackBundler {
|
||||||
nuxt: Nuxt
|
nuxt: Nuxt
|
||||||
plugins: Array<string>
|
plugins: Array<string>
|
||||||
|
|
||||||
@ -251,3 +251,8 @@ export class WebpackBundler {
|
|||||||
this.nuxt.options.target = TARGETS.static
|
this.nuxt.options.target = TARGETS.static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function bundle (nuxt: Nuxt) {
|
||||||
|
const bundler = new WebpackBundler(nuxt)
|
||||||
|
return bundler.build()
|
||||||
|
}
|
@ -85,7 +85,8 @@ interface CommonConfiguration {
|
|||||||
_nuxtConfigFile?: string
|
_nuxtConfigFile?: string
|
||||||
alias: Record<string, string>
|
alias: Record<string, string>
|
||||||
appDir: string,
|
appDir: string,
|
||||||
buildDir: string
|
buildDir: string,
|
||||||
|
vite: boolean,
|
||||||
buildModules: NuxtModule[]
|
buildModules: NuxtModule[]
|
||||||
createRequire?: (module: NodeJS.Module) => NodeJS.Require
|
createRequire?: (module: NodeJS.Module) => NodeJS.Require
|
||||||
debug?: boolean
|
debug?: boolean
|
||||||
|
@ -71,11 +71,11 @@ export async function loadNuxtConfig ({
|
|||||||
// Clear cache
|
// Clear cache
|
||||||
clearRequireCache(configFile)
|
clearRequireCache(configFile)
|
||||||
const _require = createRequire(module)
|
const _require = createRequire(module)
|
||||||
const _config: Configuration | ((ctx: Record<string, any>) => Promise<Configuration>) = interopDefault(_require(configFile) || {})
|
let _config: Configuration | ((ctx: Record<string, any>) => Promise<Configuration>) = interopDefault(_require(configFile) || {})
|
||||||
|
|
||||||
if (typeof _config === 'function') {
|
if (typeof _config === 'function') {
|
||||||
try {
|
try {
|
||||||
options = interopDefault(await _config(configContext))
|
_config = interopDefault(await _config(configContext))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consola.error(error)
|
consola.error(error)
|
||||||
consola.fatal('Error while fetching async configuration')
|
consola.fatal('Error while fetching async configuration')
|
||||||
@ -83,7 +83,7 @@ export async function loadNuxtConfig ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't mutate options export
|
// Don't mutate options export
|
||||||
options = { ...options }
|
options = { ..._config }
|
||||||
|
|
||||||
// Keep _nuxtConfigFile for watching
|
// Keep _nuxtConfigFile for watching
|
||||||
options._nuxtConfigFile = configFile
|
options._nuxtConfigFile = configFile
|
||||||
|
@ -442,6 +442,11 @@ function normalizeConfig (_options: CliConfiguration) {
|
|||||||
|
|
||||||
options._majorVersion = 3
|
options._majorVersion = 3
|
||||||
|
|
||||||
|
if (options.vite && !options.dev) {
|
||||||
|
options.vite = false
|
||||||
|
consola.warn('Vite does not support production builds yet! Using webpack...')
|
||||||
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { WebpackBundler as BundleBuilder } from './builder'
|
|
Loading…
Reference in New Issue
Block a user