chore: move `nuxt-vite` to bridge (#1180)

Co-authored-by: Xin Du (Clark) <clark.duxin@gmail.com>
Co-authored-by: pooya parsa <pyapar@gmail.com>
This commit is contained in:
Anthony Fu 2021-10-26 20:59:05 +08:00 committed by GitHub
parent c672d8990a
commit 46f858dd82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 1385 additions and 74 deletions

View File

@ -80,8 +80,11 @@ jobs:
- name: Build
run: yarn build
- name: Test (presets bridge)
run: yarn test:bridge
- name: Test with webpack
run: yarn test:bridge:webpack
- name: Test with vite
run: yarn test:bridge:vite
build-release:
needs:

View File

@ -21,8 +21,9 @@
"lint": "eslint --ext .vue,.ts,.js .",
"test": "yarn lint && yarn test:presets",
"test:presets": "mocha test/presets/*.mjs",
"test:bridge": "TEST_BRIDGE=1 yarn test:presets",
"test:unit": "mocha -r jiti/register packages/**/test/*.test.*",
"test:bridge:webpack": "TEST_BRIDGE=1 yarn test:presets",
"test:bridge:vite": "TEST_BRIDGE_VITE=1 TEST_BRIDGE=1 yarn test:presets",
"test:unit": "mocha -r jiti/register packages/*/test/*.test.*",
"version": "yarn && git add yarn.lock"
},
"resolutions": {

View File

@ -8,6 +8,7 @@ export default defineBuildConfig({
{ input: 'src/runtime/', outDir: 'dist/runtime', format: 'esm', declaration: true }
],
externals: [
'webpack'
'webpack',
'vite'
]
})

View File

@ -19,32 +19,52 @@
"@nuxt/kit": "3.0.0",
"@nuxt/nitro": "3.0.0",
"@nuxt/postcss8": "^1.1.3",
"@vitejs/plugin-legacy": "^1.6.0",
"@vue/composition-api": "^1.2.4",
"@vueuse/head": "^0.6.0",
"acorn": "^8.5.0",
"consola": "^2.15.3",
"defu": "^5.0.0",
"enhanced-resolve": "^5.8.3",
"estree-walker": "^2.0.2",
"externality": "^0.1.3",
"fs-extra": "^10.0.0",
"globby": "^11.0.4",
"hash-sum": "^2.0.0",
"magic-string": "^0.25.7",
"mlly": "^0.3.1",
"node-fetch": "^3.0.0",
"nuxi": "3.0.0",
"nuxt-vite": "^0.3.5",
"p-debounce": "^4.0.0",
"pathe": "^0.2.0",
"postcss": "^8",
"postcss-import": "^14.0.2",
"postcss-import-resolver": "^2.0.0",
"postcss-preset-env": "^6.7.0",
"postcss-url": "^10.1.3",
"scule": "^0.2.1",
"semver": "^7.3.5",
"ufo": "^0.7.9",
"unplugin": "^0.2.18",
"unplugin-vue2-script-setup": "0.6.12"
"unplugin-vue2-script-setup": "0.6.12",
"vite": "^2.5.7",
"vite-plugin-vue2": "^1.8.2",
"vue-template-compiler": "^2.6.14"
},
"devDependencies": {
"@nuxt/types": "^2.15.8",
"@types/fs-extra": "^9.0.13",
"@types/hash-sum": "^1.0.0",
"@types/node-fetch": "^3.0.2",
"nuxt": "^2",
"unbuild": "latest",
"vue-router": "3"
"vue": "^2",
"vue-router": "^3"
},
"engines": {
"node": "^14.16.0 || ^16.11.0 || ^17.0.0"
},
"installConfig": {
"hoistingLimits": "workspaces"
}
}

View File

@ -9,12 +9,20 @@ export function setupAppBridge (_options: any) {
nuxt.options.alias['#app'] = resolve(distDir, 'runtime/index.mjs')
nuxt.options.alias['#build'] = nuxt.options.buildDir
// Alias vue to a vue3-compat version of vue2
nuxt.options.alias['#vue'] = nuxt.options.alias.vue || resolveModule('vue/dist/vue.runtime.esm.js', { paths: nuxt.options.modulesDir })
// Resolve vue2 builds
nuxt.options.alias.vue2 = resolveModule('vue/dist/vue.runtime.esm.js', { paths: nuxt.options.modulesDir })
nuxt.options.build.transpile.push('vue')
// Alias vue to have identical vue3 exports
nuxt.options.alias['vue2-bridge'] = resolve(distDir, 'runtime/vue2-bridge.mjs')
for (const alias of [
// vue
'vue',
// vue 3 helper packages
'@vue/shared',
'@vue/reactivity',
'@vue/runtime-core',
'@vue/runtime-dom',
...[
// vue 2 dist files
'vue/dist/vue.common.dev',
@ -33,10 +41,8 @@ export function setupAppBridge (_options: any) {
'vue/dist/vue.runtime.min'
].flatMap(m => [m, `${m}.js`])
]) {
nuxt.options.alias[alias] = 'vue'
nuxt.options.alias[alias] = nuxt.options.alias['vue2-bridge']
}
nuxt.options.alias.vue = resolve(distDir, 'runtime/vue.mjs')
nuxt.options.build.transpile.push('vue')
// Deprecate various Nuxt options
if (nuxt.options.globalName !== 'nuxt') {

View File

@ -1,5 +1,11 @@
import { fileURLToPath } from 'url'
import { dirname, resolve } from 'pathe'
import { existsSync } from 'fs'
import { join } from 'path'
import { dirname } from 'pathe'
export const distDir = dirname(fileURLToPath(import.meta.url))
export const pkgDir = resolve(distDir, '..')
let dir = dirname(fileURLToPath(import.meta.url))
while (dir !== '/' && !existsSync(join(dir, 'package.json'))) {
dir = dirname(dir)
}
export const pkgDir = dir
export const distDir = join(pkgDir, 'dist')

View File

@ -51,7 +51,8 @@ export default defineNuxtModule({
await setupAutoImports()
}
if (opts.vite) {
await installModule(nuxt, _require.resolve('nuxt-vite'))
const viteModule = await import('./vite/module')
await installModule(nuxt, viteModule)
}
if (opts.postcss8) {
await installModule(nuxt, _require.resolve('@nuxt/postcss8'))

View File

@ -73,7 +73,7 @@ export function setupNitroBridge () {
serverConfig.plugins = serverConfig.plugins || []
serverConfig.plugins.push(new AsyncLoadingPlugin({
modulesDir: nuxt.options.modulesDir
}))
}) as any)
}
})

View File

@ -1,5 +1,5 @@
import Vue from 'vue'
import { createHooks } from 'hookable/dist/index.mjs'
import { createHooks } from 'hookable'
import { setNuxtAppInstance } from '#app'
export default (ctx, inject) => {
@ -11,10 +11,10 @@ export default (ctx, inject) => {
},
directive: Vue.directive.bind(Vue),
mixin: Vue.mixin.bind(Vue),
mount: () => {},
mount: () => { },
provide: inject,
unmount: () => {},
use (vuePlugin) {
unmount: () => { },
use(vuePlugin) {
vuePlugin.install(this)
},
version: Vue.version

View File

@ -0,0 +1 @@
export const AbortController = null

View File

@ -0,0 +1 @@
export const ReadableStream = null

View File

@ -0,0 +1,18 @@
export const URL = globalThis.URL
export const URLSearchParams = globalThis.URLSearchParams
function notSupported () {
throw new Error('[nuxt/vite] whatwg-url low level API is not supported yet!')
}
export const parseURL = notSupported
export const basicURLParse = notSupported
export const serializeURL = notSupported
export const serializeHost = notSupported
export const serializeInteger = notSupported
export const serializeURLOrigin = notSupported
export const setTheUsername = notSupported
export const setThePassword = notSupported
export const cannotHaveAUsernamePasswordPort = notSupported
export const percentDecodeBytes = notSupported
export const percentDecodeString = notSupported

View File

@ -1,7 +0,0 @@
import Vue from '#vue'
export * from '@vue/composition-api'
export const isFunction = fn => fn instanceof Function
export { Vue as default }

View File

@ -0,0 +1,8 @@
import Vue from 'vue2'
export { EffectScope, computed, createApp, createRef, customRef, defineAsyncComponent, defineComponent, del, effectScope, getCurrentInstance, getCurrentScope, h, inject, isRaw, isReactive, isReadonly, isRef, markRaw, nextTick, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, provide, proxyRefs, reactive, readonly, ref, set, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, useAttrs, useCSSModule, useCssModule, useSlots, version, warn, watch, watchEffect, watchPostEffect, watchSyncEffect } from '@vue/composition-api'
export const isFunction = fn => fn instanceof Function
export { Vue as default }

View File

@ -0,0 +1,84 @@
import { resolve } from 'pathe'
import * as vite from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
import PluginLegacy from '@vitejs/plugin-legacy'
import consola from 'consola'
import { jsxPlugin } from './plugins/jsx'
import { replace } from './plugins/replace'
import { ViteBuildContext, ViteOptions } from './types'
export async function buildClient (ctx: ViteBuildContext) {
const alias = {}
for (const p of ctx.builder.plugins) {
alias[p.name] = p.mode === 'server'
? `defaultexport:${resolve(ctx.nuxt.options.buildDir, 'empty.js')}`
: `defaultexport:${p.src}`
}
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
define: {
global: 'globalThis'
},
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite/client'),
resolve: {
alias
},
build: {
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/client'),
assetsDir: '.',
rollupOptions: {
input: resolve(ctx.nuxt.options.buildDir, 'client.js')
},
manifest: true,
ssrManifest: true
},
plugins: [
replace({
'process.env': 'import.meta.env',
'process.client': 'true',
'process.server': 'false',
'process.static': 'false',
'module.hot': 'false'
}),
jsxPlugin(),
createVuePlugin(ctx.config.vue),
PluginLegacy()
],
server: {
middlewareMode: true
}
} as ViteOptions)
await ctx.nuxt.callHook('vite:extendConfig', clientConfig, { isClient: true, isServer: false })
// Production build
if (!ctx.nuxt.options.dev) {
const start = Date.now()
consola.info('Building client...')
await vite.build(clientConfig)
consola.success(`Client built in ${Date.now() - start}ms`)
return
}
// Create development server
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
req.url = req.url.replace('/_nuxt/', '/.nuxt/')
if (req.url.includes('@vite/client')) {
req.url = '/@vite/client'
}
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()
})
}

View File

@ -0,0 +1,45 @@
import createResolver from 'postcss-import-resolver'
import defu from 'defu'
import type { Nuxt, ViteOptions } from './types'
// Ref: https://github.com/nuxt/nuxt.js/blob/dev/packages/webpack/src/utils/postcss.js
export function resolveCSSOptions (nuxt: Nuxt): ViteOptions['css'] {
const css: ViteOptions['css'] = {
postcss: {
plugins: []
}
}
const plugins = defu(nuxt.options.build.postcss.plugins, {
// https://github.com/postcss/postcss-import
'postcss-import': {
resolve: createResolver({
alias: { ...nuxt.options.alias },
modules: [
nuxt.options.srcDir,
nuxt.options.rootDir,
...nuxt.options.modulesDir
]
})
},
// https://github.com/postcss/postcss-url
'postcss-url': {},
// https://github.com/csstools/postcss-preset-env
'postcss-preset-env': nuxt.options.build.postcss.preset || {}
})
for (const name in plugins) {
const opts = plugins[name]
if (!opts) {
continue
}
const plugin = nuxt.resolver.requireModule(name)
// @ts-ignore
css.postcss.plugins.push(plugin(opts))
}
return css
}

View File

@ -0,0 +1,172 @@
import { resolve } from 'pathe'
import { readJSON, remove, existsSync, readFile, writeFile, mkdirp } from 'fs-extra'
import { ViteBuildContext } from './types'
import { uniq, isJS, isCSS, hash } from './utils'
const DEFAULT_APP_TEMPLATE = `
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>
`
export async function prepareManifests (ctx: ViteBuildContext) {
const rDist = (...args: string[]): string => resolve(ctx.nuxt.options.buildDir, 'dist', ...args)
await mkdirp(rDist('server'))
const customAppTemplateFile = resolve(ctx.nuxt.options.srcDir, 'app.html')
const APP_TEMPLATE = existsSync(customAppTemplateFile)
? (await readFile(customAppTemplateFile, 'utf-8'))
: DEFAULT_APP_TEMPLATE
const DEV_TEMPLATE = APP_TEMPLATE
.replace(
'</body>',
'<script type="module" src="/@vite/client"></script><script type="module" src="/.nuxt/client.js"></script></body>'
)
const SPA_TEMPLATE = ctx.nuxt.options.dev ? DEV_TEMPLATE : APP_TEMPLATE
const SSR_TEMPLATE = ctx.nuxt.options.dev ? DEV_TEMPLATE : APP_TEMPLATE
await writeFile(rDist('server/index.ssr.html'), SSR_TEMPLATE)
await writeFile(rDist('server/index.spa.html'), SPA_TEMPLATE)
if (ctx.nuxt.options.dev) {
await stubManifest(ctx)
} else {
await generateBuildManifest(ctx)
}
}
// convert vite's manifest to webpack style
export async function generateBuildManifest (ctx: ViteBuildContext) {
const rDist = (...args: string[]): string => resolve(ctx.nuxt.options.buildDir, 'dist', ...args)
const publicPath = ctx.nuxt.options.app.assetsPath // Default: /nuxt/
const viteClientManifest = await readJSON(rDist('client/manifest.json'))
const clientEntries = Object.entries(viteClientManifest)
const asyncEntries = uniq(clientEntries.filter((id: any) => id[1].isDynamicEntry).flatMap(getModuleIds)).filter(Boolean)
const initialEntries = uniq(clientEntries.filter((id: any) => !id[1].isDynamicEntry).flatMap(getModuleIds)).filter(Boolean)
const initialJs = initialEntries.filter(isJS)
const initialAssets = initialEntries.filter(isCSS)
// Search for polyfill file, we don't include it in the client entry
const polyfillName = initialEntries.find(id => id.startsWith('polyfills-legacy.'))
// @vitejs/plugin-legacy uses SystemJS which need to call `System.import` to load modules
const clientImports = initialJs.filter(id => id !== polyfillName).map(id => publicPath + id)
const clientEntryCode = `var imports = ${JSON.stringify(clientImports)}\nimports.reduce((p, id) => p.then(() => System.import(id)), Promise.resolve())`
const clientEntryName = 'entry-legacy.' + hash(clientEntryCode) + '.js'
const clientManifest = {
publicPath,
all: uniq([
polyfillName,
clientEntryName,
...clientEntries.flatMap(getModuleIds)
]).filter(Boolean),
initial: [
polyfillName,
clientEntryName,
...initialAssets
],
async: [
// We move initial entries to the client entry
...initialJs,
...asyncEntries
],
modules: {},
assetsMapping: {}
}
const serverManifest = {
entry: 'server.js',
files: {
'server.js': 'server.js',
...Object.fromEntries(clientEntries.map(([id, entry]) => [id, (entry as any).file]))
},
maps: {}
}
await writeFile(rDist('client', clientEntryName), clientEntryCode, 'utf-8')
await writeClientManifest(clientManifest, ctx.nuxt.options.buildDir)
await writeServerManifest(serverManifest, ctx.nuxt.options.buildDir)
// Remove SSR manifest from public client dir
await remove(rDist('client/manifest.json'))
await remove(rDist('client/ssr-manifest.json'))
}
// stub manifest on dev
export async function stubManifest (ctx: ViteBuildContext) {
const clientManifest = {
publicPath: '',
all: [
'empty.js'
],
initial: [
'empty.js'
],
async: [],
modules: {},
assetsMapping: {}
}
const serverManifest = {
entry: 'server.js',
files: {
'server.js': 'server.js'
},
maps: {}
}
await writeClientManifest(clientManifest, ctx.nuxt.options.buildDir)
await writeServerManifest(serverManifest, ctx.nuxt.options.buildDir)
}
export async function generateDevSSRManifest (ctx: ViteBuildContext) {
const rDist = (...args: string[]): string => resolve(ctx.nuxt.options.buildDir, 'dist', ...args)
const ssrManifest = await readJSON(rDist('server/ssr-manifest.json'))
const css = Object.keys(ssrManifest).filter(isCSS)
const entires = [
'@vite/client',
'entry.mjs',
...css.map(i => `../${i}`)
]
const clientManifest = {
publicPath: '',
all: entires,
initial: entires,
async: [],
modules: {},
assetsMapping: {}
}
await writeClientManifest(clientManifest, ctx.nuxt.options.buildDir)
}
async function writeServerManifest (serverManifest: any, buildDir: string) {
const serverManifestJSON = JSON.stringify(serverManifest, null, 2)
await writeFile(resolve(buildDir, 'dist/server/server.manifest.json'), serverManifestJSON, 'utf-8')
await writeFile(resolve(buildDir, 'dist/server/server.manifest.mjs'), `export default ${serverManifestJSON}`, 'utf-8')
}
async function writeClientManifest (clientManifest: any, buildDir: string) {
const clientManifestJSON = JSON.stringify(clientManifest, null, 2)
await writeFile(resolve(buildDir, 'dist/server/client.manifest.json'), clientManifestJSON, 'utf-8')
await writeFile(resolve(buildDir, 'dist/server/client.manifest.mjs'), `export default ${clientManifestJSON}`, 'utf-8')
}
function getModuleIds ([, value]: [string, any]) {
if (!value) { return [] }
// Only include legacy and css ids
return [value.file, ...value.css || []].filter(id => isCSS(id) || id.match(/-legacy\./))
}

View File

@ -0,0 +1,66 @@
import consola from 'consola'
import { addPluginTemplate, defineNuxtModule } from '@nuxt/kit'
import { version } from '../../package.json'
import { middlewareTemplate, storeTemplate } from './templates'
import type { ViteOptions } from './types'
export default defineNuxtModule<ViteOptions>({
name: 'nuxt-bridge:vite',
defaults: {},
version,
configKey: 'vite',
setup (viteOptions, nuxt) {
// Only enable for development or production if `build: true` is set
if (!nuxt.options.dev && !viteOptions.build) {
return
}
nuxt.options.cli.badgeMessages.push(`⚡ Vite Mode Enabled (v${version})`)
// eslint-disable-next-line no-console
if (viteOptions.experimentWarning !== false && !nuxt.options.test) {
consola.log(
'🧪 Vite mode is experimental and some nuxt modules might be incompatible\n',
' If found a bug, please report via https://github.com/nuxt/vite/issues with a minimal reproduction.'
)
}
// Disable loading-screen because why have it!
// @ts-expect-error
nuxt.options.build.loadingScreen = false
// @ts-expect-error
nuxt.options.build.indicator = false
nuxt.options._modules = nuxt.options._modules
.filter(m => !(Array.isArray(m) && m[0] === '@nuxt/loading-screen'))
// Mask nuxt-vite to avoid other modules depending on it's existence
// TODO: Move to kit
const getModuleName = (m) => {
if (Array.isArray(m)) { m = m[0] }
return m.meta ? m.meta.name : m
}
const filterModule = modules => modules.filter(m => getModuleName(m) !== 'nuxt-bridge:vite')
nuxt.options.modules = filterModule(nuxt.options.modules)
nuxt.options.buildModules = filterModule(nuxt.options.buildModules)
if (nuxt.options.store) {
addPluginTemplate(storeTemplate)
}
addPluginTemplate(middlewareTemplate)
nuxt.hook('builder:prepared', async (builder) => {
builder.bundleBuilder.close()
delete builder.bundleBuilder
const { ViteBuilder } = await import('./vite')
builder.bundleBuilder = new ViteBuilder(builder)
})
// remove templates from nuxt-app
nuxt.hook('build:templates', (templates) => {
const templatesFiles = templates.templatesFiles.filter((template) => {
return !['store.js', 'middleware.js'].includes(template.dst)
})
templates.templatesFiles.length = 0
templates.templatesFiles.push(...templatesFiles)
})
}
})

View File

@ -0,0 +1,37 @@
import type { Plugin } from 'vite'
import { readFile } from 'fs-extra'
// const PREFIX = 'defaultexport:'
const PREFIX = 'defaultexport:'
const hasPrefix = (id: string = '') => id.startsWith(PREFIX)
const removePrefix = (id: string = '') => hasPrefix(id) ? id.substr(PREFIX.length) : id
const hasDefaultExport = (code: string = '') => code.includes('export default')
const addDefaultExport = (code: string = '') => code + '\n\n' + 'export default () => {}'
export function defaultExportPlugin () {
return <Plugin>{
name: 'nuxt:default-export',
enforce: 'pre',
resolveId (id, importer) {
if (hasPrefix(id)) {
return id
}
if (importer && hasPrefix(importer)) {
return this.resolve(id, removePrefix(importer))
}
return null
},
async load (id) {
if (hasPrefix(id)) {
let code = await readFile(removePrefix(id), 'utf8')
if (!hasDefaultExport(code)) {
code = addDefaultExport(code)
}
return { map: null, code }
}
return null
}
}
}

View File

@ -0,0 +1,20 @@
import type { Plugin } from 'vite'
const needsJsxProcessing = (id: string = '') =>
!id.includes('node_modules') && ['.vue', '.jsx', '.tsx'].some(extension => id.includes(extension))
export function jsxPlugin () {
return <Plugin>{
name: 'nuxt:jsx',
transform (code, id) {
if (!needsJsxProcessing(id)) {
return null
}
return {
code: code.replace(/render\s*\(\s*\)\s*\{/g, 'render(h){'),
map: null
}
}
}
}

View 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
}
}
}
}

View File

@ -0,0 +1,120 @@
import { resolve } from 'pathe'
import * as vite from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
import consola from 'consola'
import { writeFile } from 'fs-extra'
import pDebounce from 'p-debounce'
import { bundleRequest } from '../../../vite/src/dev-bundler'
import { ViteBuildContext, ViteOptions } from './types'
import { wpfs } from './utils/wpfs'
import { jsxPlugin } from './plugins/jsx'
import { generateDevSSRManifest } from './manifest'
export async function buildServer (ctx: ViteBuildContext) {
// Workaround to disable HMR
const _env = process.env.NODE_ENV
process.env.NODE_ENV = 'production'
const vuePlugin = createVuePlugin(ctx.config.vue)
process.env.NODE_ENV = _env
const alias = {}
for (const p of ctx.builder.plugins) {
alias[p.name] = p.mode === 'client'
? `defaultexport:${resolve(ctx.nuxt.options.buildDir, 'empty.js')}`
: `defaultexport:${p.src}`
}
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
define: {
'process.server': true,
'process.client': false,
'process.static': false,
'typeof window': '"undefined"',
'typeof document': '"undefined"',
'typeof navigator': '"undefined"',
'typeof location': '"undefined"',
'typeof XMLHttpRequest': '"undefined"'
},
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite/server'),
resolve: {
alias
},
ssr: {
external: [
'axios'
],
noExternal: [
/\.(es|esm|esm-browser|esm-bundler).js$/,
...ctx.nuxt.options.build.transpile.filter(i => typeof i === 'string')
]
},
build: {
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/server'),
assetsDir: ctx.nuxt.options.app.assetsPath.replace(/^\/|\/$/, ''),
ssr: true,
ssrManifest: true,
rollupOptions: {
input: resolve(ctx.nuxt.options.buildDir, 'server.js'),
output: {
format: 'esm',
entryFileNames: 'server.mjs',
chunkFileNames: 'chunks/[name].mjs'
},
onwarn (warning, rollupWarn) {
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code)) {
rollupWarn(warning)
}
}
}
},
plugins: [
jsxPlugin(),
vuePlugin
]
} as ViteOptions)
await ctx.nuxt.callHook('vite:extendConfig', serverConfig, { isClient: false, isServer: true })
const onBuild = () => ctx.nuxt.callHook('build:resources', wpfs)
// Production build
if (!ctx.nuxt.options.dev) {
const start = Date.now()
consola.info('Building server...')
await vite.build(serverConfig)
await onBuild()
consola.success(`Server built in ${Date.now() - start}ms`)
return
}
// Start development server
const viteServer = await vite.createServer(serverConfig)
ctx.nuxt.hook('close', () => viteServer.close())
// Initialize plugins
await viteServer.pluginContainer.buildStart({})
// Generate manifest files
await writeFile(resolve(ctx.nuxt.options.buildDir, 'dist/server/ssr-manifest.json'), JSON.stringify({}, null, 2), 'utf-8')
await generateDevSSRManifest(ctx)
// Build and watch
const _doBuild = async () => {
const start = Date.now()
const { code } = await bundleRequest({ viteServer }, '/.nuxt/server.js')
await writeFile(resolve(ctx.nuxt.options.buildDir, 'dist/server/server.mjs'), code, 'utf-8')
const time = (Date.now() - start)
consola.info(`Server built in ${time}ms`)
await onBuild()
}
const doBuild = pDebounce(_doBuild, 300)
// Initial build
await _doBuild()
// Watch
viteServer.watcher.on('all', (_event, file) => {
if (file.indexOf(ctx.nuxt.options.buildDir) === 0) { return }
doBuild()
})
}

View File

@ -0,0 +1,135 @@
import hash from 'hash-sum'
import { resolve } from 'pathe'
import type { Nuxt, NuxtApp } from '@nuxt/kit'
type TemplateContext = {
nuxt: Nuxt;
app: NuxtApp & { templateVars: Record<string, any> };
}
// TODO: Use an alias
export const middlewareTemplate = {
filename: 'middleware.js',
src: '',
getContents (ctx: TemplateContext) {
const { dir, router: { middleware }, srcDir } = ctx.nuxt.options
const _middleware = ((typeof middleware !== 'undefined' && middleware) || []).map(m => ({
filePath: resolve(srcDir, dir.middleware, m.src),
id: m.name || m.src.replace(/[\\/]/g, '/').replace(/\.(js|ts)$/, '')
}))
return `${_middleware.map(m => `import $${hash(m.id)} from '${m.filePath}'`).join('\n')}
const middleware = {
${_middleware.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
export default middleware`
}
}
export const storeTemplate = {
filename: 'store.js',
src: '',
getContents (ctx: TemplateContext) {
const { dir, srcDir } = ctx.nuxt.options
const { templateVars: { storeModules = [] } } = ctx.app
const _storeModules = storeModules.map(s => ({
filePath: resolve(srcDir, dir.store, s.src),
id: (s.src
.replace(/\.(js|ts)$/, '')
.replace(/[\\/]/g, '/')
.replace(/index/, '')
) || 'root'
}))
return `import Vue from 'vue'
import Vuex from 'vuex'
${_storeModules.map(s => `import * as $${hash(s.id)} from '${s.filePath}'`).join('\n')}
Vue.use(Vuex)
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
const storeModules = {
${_storeModules.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
export function createStore() {
let store = normalizeRoot(storeModules.root || {})
delete storeModules.root
for (const id in storeModules) {
resolveStoreModules(store, storeModules[id], id)
}
if (typeof store === 'function') {
return store
}
return new Vuex.Store(Object.assign({
strict: (process.env.NODE_ENV !== 'production')
}, store))
}
function normalizeRoot (moduleData, id) {
moduleData = moduleData.default || moduleData
if (moduleData.commit) {
throw new Error(\`[nuxt] \${id} should export a method that returns a Vuex instance.\`)
}
if (typeof moduleData !== 'function') {
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys
moduleData = { ...moduleData }
}
moduleData.modules = moduleData.modules || {}
return moduleData
}
function resolveStoreModules (store, moduleData, id) {
moduleData = moduleData.default || moduleData
const namespaces = id.split('/').filter(Boolean)
let moduleName = namespaces[namespaces.length - 1]
// If src is a known Vuex property
if (VUEX_PROPERTIES.includes(moduleName)) {
const property = moduleName
const propertyStoreModule = getStoreModule(store, namespaces, { isProperty: true })
// Replace state since it's a function
mergeProperty(propertyStoreModule, moduleData, property)
return
}
const storeModule = getStoreModule(store, namespaces)
for (const property of VUEX_PROPERTIES) {
mergeProperty(storeModule, moduleData[property], property)
}
if (moduleData.namespaced === false) {
delete storeModule.namespaced
}
}
function getStoreModule (storeModule, namespaces, { isProperty = false } = {}) {
// If ./mutations.js
if (!namespaces.length || (isProperty && namespaces.length === 1)) {
return storeModule
}
const namespace = namespaces.shift()
storeModule.modules[namespace] = storeModule.modules[namespace] || {}
storeModule.modules[namespace].namespaced = true
storeModule.modules[namespace].modules = storeModule.modules[namespace].modules || {}
return getStoreModule(storeModule.modules[namespace], namespaces, { isProperty })
}
function mergeProperty (storeModule, moduleData, property) {
if (!moduleData) {
return
}
if (property === 'state') {
storeModule.state = moduleData || storeModule.state
} else {
storeModule[property] = { ...storeModule[property], ...moduleData }
}
}`
}
}

View File

@ -0,0 +1,32 @@
import type { InlineConfig, SSROptions } from 'vite'
import type { VueViteOptions } from 'vite-plugin-vue2'
export interface Nuxt {
options: any;
resolver: any;
hook: Function;
callHook: Function;
}
export interface ViteOptions extends Omit<InlineConfig, 'build'> {
/**
* Options for vite-plugin-vue2
*
* @see https://github.com/underfin/vite-plugin-vue2
*/
vue?: VueViteOptions
ssr?: boolean | SSROptions
build?: boolean | InlineConfig['build']
experimentWarning?: boolean
}
export interface ViteBuildContext {
nuxt: Nuxt;
builder: {
plugins: { name: string; mode?: 'client' | 'server'; src: string; }[];
};
config: ViteOptions;
}

View File

@ -0,0 +1,34 @@
import { createHash } from 'crypto'
export function uniq<T> (arr: T[]): T[] {
return Array.from(new Set(arr))
}
// Copied from vue-bundle-renderer utils
const IS_JS_RE = /\.[cm]?js(\?[^.]+)?$/
const IS_MODULE_RE = /\.mjs(\?[^.]+)?$/
const HAS_EXT_RE = /[^./]+\.[^./]+$/
const IS_CSS_RE = /\.css(\?[^.]+)?$/
export function isJS (file: string) {
return IS_JS_RE.test(file) || !HAS_EXT_RE.test(file)
}
export function isModule (file: string) {
return IS_MODULE_RE.test(file) || !HAS_EXT_RE.test(file)
}
export function isCSS (file: string) {
return IS_CSS_RE.test(file)
}
export function hashId (id: string) {
return '$id_' + hash(id)
}
export function hash (input: string, length = 8) {
return createHash('sha256')
.update(input)
.digest('hex')
.substr(0, length)
}

View File

@ -0,0 +1,20 @@
import type { ViteDevServer } from 'vite'
import consola from 'consola'
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)
try {
await server.transformRequest(url)
} catch (e) {
consola.debug('Warmup for %s failed with: %s', url, e)
}
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)))
}

View File

@ -0,0 +1,7 @@
import { join } from 'pathe'
import fsExtra from 'fs-extra'
export const wpfs: any = {
...fsExtra,
join
}

View File

@ -0,0 +1,112 @@
import { resolve } from 'pathe'
import * as vite from 'vite'
import consola from 'consola'
import { distDir } from '../dirs'
import { buildClient } from './client'
import { buildServer } from './server'
import { defaultExportPlugin } from './plugins/default-export'
import { jsxPlugin } from './plugins/jsx'
import { replace } from './plugins/replace'
import { resolveCSSOptions } from './css'
import { warmupViteServer } from './utils/warmup'
import type { Nuxt, ViteBuildContext, ViteOptions } from './types'
import { prepareManifests } from './manifest'
async function bundle (nuxt: Nuxt, builder: any) {
for (const p of builder.plugins) {
p.src = nuxt.resolver.resolvePath(resolve(nuxt.options.buildDir, p.src))
}
const ctx: ViteBuildContext = {
nuxt,
builder,
config: vite.mergeConfig(
nuxt.options.vite || {},
{
root: nuxt.options.rootDir,
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.options.alias,
'#build': nuxt.options.buildDir,
'.nuxt': nuxt.options.buildDir,
'/.nuxt/entry.mjs': resolve(nuxt.options.buildDir, 'client.js'),
'~': nuxt.options.srcDir,
'@': nuxt.options.srcDir,
'web-streams-polyfill/ponyfill/es2018': resolve(distDir, 'runtime/vite/mock/web-streams-polyfill.mjs'),
'whatwg-url': resolve(distDir, 'runtime/vite/mock/whatwg-url.mjs'),
// Cannot destructure property 'AbortController' of ..
'abort-controller': resolve(distDir, 'runtime/vite/mock/abort-controller.mjs')
}
},
vue: {},
server: {
fs: {
strict: false
}
},
css: resolveCSSOptions(nuxt),
optimizeDeps: {
exclude: [
'ufo',
'date-fns',
'nanoid',
'vue',
'vue2',
'vue2-bridge'
]
},
esbuild: {
jsxFactory: 'h',
jsxFragment: 'Fragment'
},
publicDir: resolve(nuxt.options.srcDir, nuxt.options.dir.static),
clearScreen: false,
build: {
emptyOutDir: false
},
plugins: [
replace({
__webpack_public_path__: 'globalThis.__webpack_public_path__'
}),
jsxPlugin(),
defaultExportPlugin()
]
} as ViteOptions
)
}
await ctx.nuxt.callHook('vite:extend', ctx)
if (nuxt.options.dev) {
ctx.nuxt.hook('vite:serverCreated', (server: vite.ViteDevServer) => {
const start = Date.now()
warmupViteServer(server, ['/.nuxt/entry.mjs']).then(() => {
consola.info(`Vite warmed up in ${Date.now() - start}ms`)
}).catch(consola.error)
})
}
await buildClient(ctx)
await prepareManifests(ctx)
await buildServer(ctx)
}
export class ViteBuilder {
builder: any
nuxt: Nuxt
constructor (builder: any) {
this.builder = builder
this.nuxt = builder.nuxt
}
build () {
return bundle(this.nuxt, this.builder)
}
}

View File

@ -83,7 +83,8 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (input: NuxtMod
templates: [
...templates.templatesFiles,
...virtualTemplates
]
],
templateVars: templates.templateVars
}
}
for await (const template of virtualTemplates) {

View File

@ -124,7 +124,7 @@ const ${hashId(chunk.id)} = ${chunk.code}
const ssrModuleLoader = `
const __pendingModules__ = new Map()
const __pendingImports__ = new Map()
const __ssrContext__ = { global: {} }
const __ssrContext__ = { global: globalThis }
function __ssrLoadModule__(url, urlStack = []) {
const pendingModule = __pendingModules__.get(url)

View File

@ -19,6 +19,8 @@ export default defineNuxtConfig({
output: { dir: process.env.NITRO_OUTPUT_DIR }
},
bridge: {
meta: true
}
meta: true,
vite: !!process.env.TEST_BRIDGE_VITE
},
vite: process.env.TEST_BRIDGE_VITE ? { build: {} } : undefined
})

View File

@ -6,6 +6,7 @@
"build": "nuxt build"
},
"devDependencies": {
"@nuxt/bridge": "*",
"core-js": "^3",
"nuxt": "^2",
"vue": "^2"

429
yarn.lock
View File

@ -343,7 +343,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/parser@npm:^7.15.0, @babel/parser@npm:^7.15.4, @babel/parser@npm:^7.15.6, @babel/parser@npm:^7.15.8":
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.15.0, @babel/parser@npm:^7.15.4, @babel/parser@npm:^7.15.6, @babel/parser@npm:^7.15.8":
version: 7.15.8
resolution: "@babel/parser@npm:7.15.8"
bin:
@ -1311,7 +1311,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.15.4, @babel/types@npm:^7.15.6, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.15.4, @babel/types@npm:^7.15.6, @babel/types@npm:^7.3.0, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
version: 7.15.6
resolution: "@babel/types@npm:7.15.6"
dependencies:
@ -2374,7 +2374,7 @@ __metadata:
languageName: node
linkType: hard
"@nuxt/bridge@workspace:packages/bridge":
"@nuxt/bridge@*, @nuxt/bridge@workspace:packages/bridge":
version: 0.0.0-use.local
resolution: "@nuxt/bridge@workspace:packages/bridge"
dependencies:
@ -2382,28 +2382,45 @@ __metadata:
"@nuxt/kit": 3.0.0
"@nuxt/nitro": 3.0.0
"@nuxt/postcss8": ^1.1.3
"@nuxt/types": ^2.15.8
"@types/fs-extra": ^9.0.13
"@types/hash-sum": ^1.0.0
"@types/node-fetch": ^3.0.2
"@vitejs/plugin-legacy": ^1.6.0
"@vue/composition-api": ^1.2.4
"@vueuse/head": ^0.6.0
acorn: ^8.5.0
consola: ^2.15.3
defu: ^5.0.0
enhanced-resolve: ^5.8.3
estree-walker: ^2.0.2
externality: ^0.1.3
fs-extra: ^10.0.0
globby: ^11.0.4
hash-sum: ^2.0.0
magic-string: ^0.25.7
mlly: ^0.3.1
node-fetch: ^3.0.0
nuxi: 3.0.0
nuxt-vite: ^0.3.5
nuxt: ^2
p-debounce: ^4.0.0
pathe: ^0.2.0
postcss: ^8
postcss-import: ^14.0.2
postcss-import-resolver: ^2.0.0
postcss-preset-env: ^6.7.0
postcss-url: ^10.1.3
scule: ^0.2.1
semver: ^7.3.5
ufo: ^0.7.9
unbuild: latest
unplugin: ^0.2.18
unplugin-vue2-script-setup: 0.6.12
vue-router: 3
vite: ^2.5.7
vite-plugin-vue2: ^1.8.2
vue: ^2
vue-router: ^3
vue-template-compiler: ^2.6.14
languageName: unknown
linkType: soft
@ -2762,6 +2779,33 @@ __metadata:
languageName: node
linkType: hard
"@nuxt/types@npm:^2.15.8":
version: 2.15.8
resolution: "@nuxt/types@npm:2.15.8"
dependencies:
"@types/autoprefixer": 9.7.2
"@types/babel__core": 7.1.14
"@types/compression": 1.7.0
"@types/connect": 3.4.34
"@types/etag": 1.8.0
"@types/file-loader": 5.0.0
"@types/html-minifier": 4.0.0
"@types/less": 3.0.2
"@types/node": 12.20.12
"@types/optimize-css-assets-webpack-plugin": 5.0.3
"@types/pug": 2.0.4
"@types/sass-loader": 8.0.1
"@types/serve-static": 1.13.9
"@types/terser-webpack-plugin": 4.2.1
"@types/webpack": 4.41.28
"@types/webpack-bundle-analyzer": 3.9.3
"@types/webpack-dev-middleware": 4.1.2
"@types/webpack-hot-middleware": 2.25.4
sass-loader: 10.1.1
checksum: 4195d528fdd93d23879ff7009bc30e4c5bde4851f204c679a761c958c3c46af41c85183f321513c6223f9d8fe24a26459c45e2dc271f7f88a54a015e61465604
languageName: node
linkType: hard
"@nuxt/utils@npm:2.15.8":
version: 2.15.8
resolution: "@nuxt/utils@npm:2.15.8"
@ -3314,6 +3358,13 @@ __metadata:
languageName: node
linkType: hard
"@types/anymatch@npm:*":
version: 1.3.1
resolution: "@types/anymatch@npm:1.3.1"
checksum: 1eeb16286102a98eda415e1ade6fb980ff0a001fc21e777af8932001ebbd324d0d2fbbd5ef51c828346ff71847ba00af3f73d1dfea434efb9b72467b8cf0343a
languageName: node
linkType: hard
"@types/asn1js@npm:^2.0.2":
version: 2.0.2
resolution: "@types/asn1js@npm:2.0.2"
@ -3321,6 +3372,74 @@ __metadata:
languageName: node
linkType: hard
"@types/autoprefixer@npm:9.7.2":
version: 9.7.2
resolution: "@types/autoprefixer@npm:9.7.2"
dependencies:
"@types/browserslist": "*"
postcss: 7.x.x
checksum: 7370a9b126cc5a2f4f20c5e1acb8b4ab17790f1d0108735fc732c3043314b0c7260c262d41bcaa3330b93432873063810662054d2483b786094afa76af467d8e
languageName: node
linkType: hard
"@types/babel__core@npm:7.1.14":
version: 7.1.14
resolution: "@types/babel__core@npm:7.1.14"
dependencies:
"@babel/parser": ^7.1.0
"@babel/types": ^7.0.0
"@types/babel__generator": "*"
"@types/babel__template": "*"
"@types/babel__traverse": "*"
checksum: de4a1a4905e4fb66e9b5ea185704b209892fa104b6aec8705021a3ddf0ff017234c41a1b0bffb0acf2c361afd5352c2d216e3548c8a702ba2558ab63f0bf2200
languageName: node
linkType: hard
"@types/babel__generator@npm:*":
version: 7.6.3
resolution: "@types/babel__generator@npm:7.6.3"
dependencies:
"@babel/types": ^7.0.0
checksum: 0aa1881c47e3e471cabb9183ae42176591b168a6fe4714d205aec33a7e480d65a8a1ba7fcd9678337aadc34059dc5baa04841e5adfbbe67ae33bad79e7633b8e
languageName: node
linkType: hard
"@types/babel__template@npm:*":
version: 7.4.1
resolution: "@types/babel__template@npm:7.4.1"
dependencies:
"@babel/parser": ^7.1.0
"@babel/types": ^7.0.0
checksum: 649fe8b42c2876be1fd28c6ed9b276f78152d5904ec290b6c861d9ef324206e0a5c242e8305c421ac52ecf6358fa7e32ab7a692f55370484825c1df29b1596ee
languageName: node
linkType: hard
"@types/babel__traverse@npm:*":
version: 7.14.2
resolution: "@types/babel__traverse@npm:7.14.2"
dependencies:
"@babel/types": ^7.3.0
checksum: a797ea09c72307569e3ee08aa3900ca744ce3091114084f2dc59b67a45ee7d01df7865252790dbfa787a7915ce892cdc820c9b920f3683292765fc656b08dc63
languageName: node
linkType: hard
"@types/body-parser@npm:*":
version: 1.19.1
resolution: "@types/body-parser@npm:1.19.1"
dependencies:
"@types/connect": "*"
"@types/node": "*"
checksum: 2990656ea2de81f3529a3359a79a13b67feb4c627caf7a367fdc0017a178e567b0cc410546bdd219104ad7197c5ee5a90b70193f5253839ea43d9cdb2d2dacee
languageName: node
linkType: hard
"@types/browserslist@npm:*":
version: 4.8.0
resolution: "@types/browserslist@npm:4.8.0"
checksum: 78b2126f9bc2f65bce74afdffd46988a5a734f935ff1f457c64bcc64158bf8a380ce68e0ca079d7ca6da34e4ea78bfee9e03d148e0439c92a489442422be7804
languageName: node
linkType: hard
"@types/chai@npm:^4.2.22":
version: 4.2.22
resolution: "@types/chai@npm:4.2.22"
@ -3328,6 +3447,16 @@ __metadata:
languageName: node
linkType: hard
"@types/clean-css@npm:*":
version: 4.2.5
resolution: "@types/clean-css@npm:4.2.5"
dependencies:
"@types/node": "*"
source-map: ^0.6.0
checksum: 640f0c47ecda76fa15d1d4ea0cd49c6f617f080147b09aae009cafe90bd69362d018abbe61823ac3b867b1057ef7b2c64162ce9fbf876c524800d80c9f87a9e2
languageName: node
linkType: hard
"@types/clear@npm:^0":
version: 0.1.2
resolution: "@types/clear@npm:0.1.2"
@ -3335,6 +3464,15 @@ __metadata:
languageName: node
linkType: hard
"@types/compression@npm:1.7.0":
version: 1.7.0
resolution: "@types/compression@npm:1.7.0"
dependencies:
"@types/express": "*"
checksum: bf0559b93df9a7058c442013c52d4205c3290fdf4d5b71d129668be4eb35139bdcaafb06974ca1527c6c4ce73e1bc256e21ab112a089cce00e5bb016a662ed28
languageName: node
linkType: hard
"@types/connect@npm:*":
version: 3.4.35
resolution: "@types/connect@npm:3.4.35"
@ -3344,6 +3482,15 @@ __metadata:
languageName: node
linkType: hard
"@types/connect@npm:3.4.34":
version: 3.4.34
resolution: "@types/connect@npm:3.4.34"
dependencies:
"@types/node": "*"
checksum: c6e2aa299cf3979c00602f48ce9163700f0cbfec6ba2a8e1506d08f51da0279805a478ea094252fad7c369a563ee033b359c708ab34b1763397c58d7e2df07ad
languageName: node
linkType: hard
"@types/eslint-scope@npm:^3.7.0":
version: 3.7.1
resolution: "@types/eslint-scope@npm:3.7.1"
@ -3378,6 +3525,47 @@ __metadata:
languageName: node
linkType: hard
"@types/etag@npm:1.8.0":
version: 1.8.0
resolution: "@types/etag@npm:1.8.0"
dependencies:
"@types/node": "*"
checksum: bdb85a4f647f0ea8ebd7c3121de869a07d9f45626a5c4a1a373876a69eb2227d92033cfb8ae98a0dbe9bbb35e7fdc9c39c39c666fc62516e4d92056459044849
languageName: node
linkType: hard
"@types/express-serve-static-core@npm:^4.17.18":
version: 4.17.24
resolution: "@types/express-serve-static-core@npm:4.17.24"
dependencies:
"@types/node": "*"
"@types/qs": "*"
"@types/range-parser": "*"
checksum: 2f0b4711261d663bf93df4dbd6f0270e84d1624278e2f3722cf050e2e6be521b6d385bb69bd0eac14abbf1119d4b308a731ec746fb2c3848697658e9e49e5676
languageName: node
linkType: hard
"@types/express@npm:*":
version: 4.17.13
resolution: "@types/express@npm:4.17.13"
dependencies:
"@types/body-parser": "*"
"@types/express-serve-static-core": ^4.17.18
"@types/qs": "*"
"@types/serve-static": "*"
checksum: 12a2a0e6c4b993fc0854bec665906788aea0d8ee4392389d7a98a5de1eefdd33c9e1e40a91f3afd274011119c506f7b4126acb97fae62ae20b654974d44cba12
languageName: node
linkType: hard
"@types/file-loader@npm:5.0.0":
version: 5.0.0
resolution: "@types/file-loader@npm:5.0.0"
dependencies:
"@types/webpack": ^4
checksum: 6de7b3a6c07460fdbc31953610cf1ad11bda1c65cbd4ac943a95f773bb67fa26c834b56d6f7cbd2e490be3f42b59a9ba762fdf311b6004cdee39a39c602e4095
languageName: node
linkType: hard
"@types/fs-extra@npm:^9.0.13":
version: 9.0.13
resolution: "@types/fs-extra@npm:9.0.13"
@ -3411,6 +3599,17 @@ __metadata:
languageName: node
linkType: hard
"@types/html-minifier@npm:4.0.0":
version: 4.0.0
resolution: "@types/html-minifier@npm:4.0.0"
dependencies:
"@types/clean-css": "*"
"@types/relateurl": "*"
"@types/uglify-js": "*"
checksum: 45ba14fe76e4b057d16bda585ce2e037b27533e8c91ca6a2f5562cdaba56825cb1563804330fc0478a0d58c01d4d68abdd7d5087f32fdaa9648fbbfab6afd336
languageName: node
linkType: hard
"@types/http-proxy@npm:^1.17.7":
version: 1.17.7
resolution: "@types/http-proxy@npm:1.17.7"
@ -3445,6 +3644,13 @@ __metadata:
languageName: node
linkType: hard
"@types/less@npm:3.0.2":
version: 3.0.2
resolution: "@types/less@npm:3.0.2"
checksum: f425e5d3980ddc4ab9f77aef176caf2944f70ab47106f510545beadab137aea2955bb49993be111bf69f5a7757be8a589bbe9cd3b07895a37dd7acde181672db
languageName: node
linkType: hard
"@types/lodash.template@npm:^4":
version: 4.5.0
resolution: "@types/lodash.template@npm:4.5.0"
@ -3505,6 +3711,15 @@ __metadata:
languageName: node
linkType: hard
"@types/node-sass@npm:*":
version: 4.11.2
resolution: "@types/node-sass@npm:4.11.2"
dependencies:
"@types/node": "*"
checksum: c3d3e02d5bd5ed57ff84bb48e94794c249cc11a8b87e1c6460cc27977f255e105b4c088b3e4cd20e5bca1b3101df2cb1b17368eea55c9a2ff8e36b0f5e211bba
languageName: node
linkType: hard
"@types/node@npm:*":
version: 16.11.1
resolution: "@types/node@npm:16.11.1"
@ -3512,6 +3727,13 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:12.20.12":
version: 12.20.12
resolution: "@types/node@npm:12.20.12"
checksum: 9e4ef12f52bbf6c1df7534e750c28edd7b49ac0793e2a8cf0ddfe02fcdc68740ebc349a727b8c584e60006ec63e6c9fa5123210ab52898e69b91835f1ac38afd
languageName: node
linkType: hard
"@types/node@npm:^14.17.29":
version: 14.17.29
resolution: "@types/node@npm:14.17.29"
@ -3540,6 +3762,15 @@ __metadata:
languageName: node
linkType: hard
"@types/optimize-css-assets-webpack-plugin@npm:5.0.3":
version: 5.0.3
resolution: "@types/optimize-css-assets-webpack-plugin@npm:5.0.3"
dependencies:
"@types/webpack": ^4
checksum: 73cbacca6a683e21ca41ae221c17dff62e4b42d1ec1ddb79b2e165dc5c024d6a2bd6dfbd1cda066e523e8e330e8e4d73f892dc4bc455d4de309590d991bb5b6e
languageName: node
linkType: hard
"@types/parse-json@npm:^4.0.0":
version: 4.0.0
resolution: "@types/parse-json@npm:4.0.0"
@ -3561,6 +3792,13 @@ __metadata:
languageName: node
linkType: hard
"@types/pug@npm:2.0.4":
version: 2.0.4
resolution: "@types/pug@npm:2.0.4"
checksum: 26743ea4d778e9c429af62aa396a0454086c01e3d2d1a8961b9a35e2a219856a8d917196a93b56b41f44f9169c4481e0bbd983a502df41dc395129bf4e93fe16
languageName: node
linkType: hard
"@types/q@npm:^1.5.1":
version: 1.5.5
resolution: "@types/q@npm:1.5.5"
@ -3568,6 +3806,27 @@ __metadata:
languageName: node
linkType: hard
"@types/qs@npm:*":
version: 6.9.7
resolution: "@types/qs@npm:6.9.7"
checksum: 7fd6f9c25053e9b5bb6bc9f9f76c1d89e6c04f7707a7ba0e44cc01f17ef5284adb82f230f542c2d5557d69407c9a40f0f3515e8319afd14e1e16b5543ac6cdba
languageName: node
linkType: hard
"@types/range-parser@npm:*":
version: 1.2.4
resolution: "@types/range-parser@npm:1.2.4"
checksum: b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95
languageName: node
linkType: hard
"@types/relateurl@npm:*":
version: 0.2.29
resolution: "@types/relateurl@npm:0.2.29"
checksum: 33226abf47dc03523f88dacb6c2acd185285e754a8e64dd832156fcfbeee053b3c9c63dcb01c06aa263f6e7cb1e53f819718d41dbf7ede38b9d00893cec4a6f6
languageName: node
linkType: hard
"@types/resolve@npm:1.17.1":
version: 1.17.1
resolution: "@types/resolve@npm:1.17.1"
@ -3587,6 +3846,26 @@ __metadata:
languageName: node
linkType: hard
"@types/sass-loader@npm:8.0.1":
version: 8.0.1
resolution: "@types/sass-loader@npm:8.0.1"
dependencies:
"@types/node-sass": "*"
"@types/sass": "*"
"@types/webpack": ^4
checksum: 08d0ade9c79f8ee5baf1776186fb082dceeedc3c83503ebca1807bd2bb85796b9e3ec9f9fdac3847be4ac62edaba614e355e1f5a96804c1dacba4ec0c35c14d5
languageName: node
linkType: hard
"@types/sass@npm:*":
version: 1.16.1
resolution: "@types/sass@npm:1.16.1"
dependencies:
"@types/node": "*"
checksum: 3f86d2eaf4988a2775fc0fc164d35e73ce82d71228191da7b11d97ad5e8ac129f1c5f798307e31482f8cfebab758bd3b24e731860bed81afe5a1bbe13fa2b2df
languageName: node
linkType: hard
"@types/semver@npm:^7":
version: 7.3.9
resolution: "@types/semver@npm:7.3.9"
@ -3594,7 +3873,7 @@ __metadata:
languageName: node
linkType: hard
"@types/serve-static@npm:^1.13.10":
"@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10":
version: 1.13.10
resolution: "@types/serve-static@npm:1.13.10"
dependencies:
@ -3604,6 +3883,16 @@ __metadata:
languageName: node
linkType: hard
"@types/serve-static@npm:1.13.9":
version: 1.13.9
resolution: "@types/serve-static@npm:1.13.9"
dependencies:
"@types/mime": ^1
"@types/node": "*"
checksum: 5c5f3b64e9fe7c51fb428ef70f1f2365b897fc3c8400be6d6afc8db0f152639182b360361ebd3d0cbaeb607b125dee03bf0c50bf7e08642ff150028f05bb7381
languageName: node
linkType: hard
"@types/source-list-map@npm:*":
version: 0.1.2
resolution: "@types/source-list-map@npm:0.1.2"
@ -3625,6 +3914,16 @@ __metadata:
languageName: node
linkType: hard
"@types/terser-webpack-plugin@npm:4.2.1":
version: 4.2.1
resolution: "@types/terser-webpack-plugin@npm:4.2.1"
dependencies:
"@types/webpack": ^4
terser: ^4.6.13
checksum: d120ddafc8993c8861526ea93ea2668c945aa00739fc465430be8882c58df17e72e42fed0d6306f4ad6b697a68ea39ce79424370fb8a9e373f516a7ae9ba94a9
languageName: node
linkType: hard
"@types/terser-webpack-plugin@npm:^5.0.4":
version: 5.0.4
resolution: "@types/terser-webpack-plugin@npm:5.0.4"
@ -3658,6 +3957,15 @@ __metadata:
languageName: node
linkType: hard
"@types/webpack-bundle-analyzer@npm:3.9.3":
version: 3.9.3
resolution: "@types/webpack-bundle-analyzer@npm:3.9.3"
dependencies:
"@types/webpack": ^4
checksum: a0aaa85fd2d06bfc2a200bae4051449bd1f35d1d6c7964b181f113b5d9997d3bde6efeb2749e8a422870ac6e90d95b6fbf8c5b6e5638c674541693b09e2e1c38
languageName: node
linkType: hard
"@types/webpack-bundle-analyzer@npm:^4.4.1":
version: 4.4.1
resolution: "@types/webpack-bundle-analyzer@npm:4.4.1"
@ -3669,6 +3977,16 @@ __metadata:
languageName: node
linkType: hard
"@types/webpack-dev-middleware@npm:4.1.2":
version: 4.1.2
resolution: "@types/webpack-dev-middleware@npm:4.1.2"
dependencies:
"@types/connect": "*"
"@types/webpack": ^4
checksum: 1912e2de5cd188acb1a4cba223a5f3e62415e265334ecd1dcb213869bbdcdaad2edbcd66b325d23ce5af665587852f3926dda930b387dd228f2ff453b0a4fc9b
languageName: node
linkType: hard
"@types/webpack-dev-middleware@npm:^5.0.2":
version: 5.0.2
resolution: "@types/webpack-dev-middleware@npm:5.0.2"
@ -3680,6 +3998,16 @@ __metadata:
languageName: node
linkType: hard
"@types/webpack-hot-middleware@npm:2.25.4":
version: 2.25.4
resolution: "@types/webpack-hot-middleware@npm:2.25.4"
dependencies:
"@types/connect": "*"
"@types/webpack": ^4
checksum: 486027794a3a5d8dd5e559b42b8e4bffeb8c7961025e6de2e865bc17400bdaf8d258f6bd9ddadbd3d55a75e886c78a618900323f470ecaae806f6653b123a09c
languageName: node
linkType: hard
"@types/webpack-hot-middleware@npm:^2.25.5":
version: 2.25.5
resolution: "@types/webpack-hot-middleware@npm:2.25.5"
@ -3710,6 +4038,20 @@ __metadata:
languageName: node
linkType: hard
"@types/webpack@npm:4.41.28":
version: 4.41.28
resolution: "@types/webpack@npm:4.41.28"
dependencies:
"@types/anymatch": "*"
"@types/node": "*"
"@types/tapable": ^1
"@types/uglify-js": "*"
"@types/webpack-sources": "*"
source-map: ^0.6.0
checksum: d9a99bb2a3c958d4a797734cba89ac489256cfb7fede7b8970b55291bca936c448851297ebaddb5b871e48fc028fa83e31856ec5f57695e9cbbd2ceda72fc499
languageName: node
linkType: hard
"@types/webpack@npm:^4, @types/webpack@npm:^4.41.8":
version: 4.41.31
resolution: "@types/webpack@npm:4.41.31"
@ -9886,6 +10228,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "fixture-basic@workspace:test/fixtures/bridge"
dependencies:
"@nuxt/bridge": "*"
core-js: ^3
nuxt: ^2
vue: ^2
@ -14004,27 +14347,6 @@ fsevents@~2.3.2:
languageName: unknown
linkType: soft
"nuxt-vite@npm:^0.3.5":
version: 0.3.5
resolution: "nuxt-vite@npm:0.3.5"
dependencies:
"@vitejs/plugin-legacy": ^1.6.0
consola: ^2.15.3
defu: ^5.0.0
fs-extra: ^10.0.0
pathe: ^0.2.0
postcss-import: ^14.0.2
postcss-import-resolver: ^2.0.0
postcss-preset-env: ^6.7.0
postcss-url: ^10.1.3
semver: ^7.3.5
ufo: ^0.7.9
vite: ^2.5.7
vite-plugin-vue2: ^1.8.2
checksum: 787f833cbbb75c65da1987f88c371d62da843f07a49055642a886cfab66eb8a78eff537128b1f3e1c2204567c85b1f4281c9d43aea1f6f9e67323230d129c6e6
languageName: node
linkType: hard
"nuxt3@workspace:./packages/nuxt3, nuxt3@workspace:packages/nuxt3":
version: 0.0.0-use.local
resolution: "nuxt3@workspace:packages/nuxt3"
@ -16098,7 +16420,7 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"postcss@npm:^7.0.0, postcss@npm:^7.0.1, postcss@npm:^7.0.14, postcss@npm:^7.0.17, postcss@npm:^7.0.2, postcss@npm:^7.0.27, postcss@npm:^7.0.32, postcss@npm:^7.0.36, postcss@npm:^7.0.5, postcss@npm:^7.0.6":
"postcss@npm:7.x.x, postcss@npm:^7.0.0, postcss@npm:^7.0.1, postcss@npm:^7.0.14, postcss@npm:^7.0.17, postcss@npm:^7.0.2, postcss@npm:^7.0.27, postcss@npm:^7.0.32, postcss@npm:^7.0.36, postcss@npm:^7.0.5, postcss@npm:^7.0.6":
version: 7.0.39
resolution: "postcss@npm:7.0.39"
dependencies:
@ -16108,6 +16430,17 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"postcss@npm:^8, postcss@npm:^8.3.11":
version: 8.3.11
resolution: "postcss@npm:8.3.11"
dependencies:
nanoid: ^3.1.30
picocolors: ^1.0.0
source-map-js: ^0.6.2
checksum: 1a230553d74c66aa9585c90781ed8ea75f19cefea405d2117b67fbeb24b5b5e0e17be2e0c5a07db31dd085643a13394127ab2222e940771b70498331bf20f35e
languageName: node
linkType: hard
"postcss@npm:^8.1.10, postcss@npm:^8.2.15, postcss@npm:^8.3.5, postcss@npm:^8.3.8":
version: 8.3.10
resolution: "postcss@npm:8.3.10"
@ -16119,17 +16452,6 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"postcss@npm:^8.3.11":
version: 8.3.11
resolution: "postcss@npm:8.3.11"
dependencies:
nanoid: ^3.1.30
picocolors: ^1.0.0
source-map-js: ^0.6.2
checksum: 1a230553d74c66aa9585c90781ed8ea75f19cefea405d2117b67fbeb24b5b5e0e17be2e0c5a07db31dd085643a13394127ab2222e940771b70498331bf20f35e
languageName: node
linkType: hard
"prelude-ls@npm:^1.2.1":
version: 1.2.1
resolution: "prelude-ls@npm:1.2.1"
@ -17309,6 +17631,31 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"sass-loader@npm:10.1.1":
version: 10.1.1
resolution: "sass-loader@npm:10.1.1"
dependencies:
klona: ^2.0.4
loader-utils: ^2.0.0
neo-async: ^2.6.2
schema-utils: ^3.0.0
semver: ^7.3.2
peerDependencies:
fibers: ">= 3.1.0"
node-sass: ^4.0.0 || ^5.0.0
sass: ^1.3.0
webpack: ^4.36.0 || ^5.0.0
peerDependenciesMeta:
fibers:
optional: true
node-sass:
optional: true
sass:
optional: true
checksum: dbd4ba06e2a7de50db4588c9e84e38fb458ca4a44e1fccdf6eded728662b6fe0bd556249970876f13b47424e4285f5c6a8953933f83d47fd1448cad5884f84a5
languageName: node
linkType: hard
"sax@npm:^1.2.4, sax@npm:~1.2.4":
version: 1.2.4
resolution: "sax@npm:1.2.4"
@ -18510,7 +18857,7 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"terser@npm:^4.1.2, terser@npm:^4.6.3":
"terser@npm:^4.1.2, terser@npm:^4.6.13, terser@npm:^4.6.3":
version: 4.8.0
resolution: "terser@npm:4.8.0"
dependencies:
@ -19728,7 +20075,7 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"vue-router@npm:3, vue-router@npm:^3.5.1":
"vue-router@npm:^3, vue-router@npm:^3.5.1":
version: 3.5.2
resolution: "vue-router@npm:3.5.2"
checksum: 342049e7cb0e4974879c57f9ecce342c180a1abce8df71137f902b201faa18d0a65c44936cbd4e9d62d5770d8f95395d73a5e05efa255475817f350bf7a094d1