mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 01:15:58 +00:00
fix: sanitize import filenames in generated imports (#2216)
This commit is contained in:
parent
614e87e9f0
commit
29171bd105
@ -38,6 +38,7 @@
|
||||
"globby": "^13.1.1",
|
||||
"h3": "^0.3.9",
|
||||
"hash-sum": "^2.0.0",
|
||||
"knitwork": "^0.1.0",
|
||||
"magic-string": "^0.25.7",
|
||||
"mlly": "^0.4.1",
|
||||
"murmurhash-es": "^0.1.1",
|
||||
|
@ -2,6 +2,7 @@ import hash from 'hash-sum'
|
||||
import { resolve } from 'pathe'
|
||||
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||
import { genImport, genObjectFromRawEntries } from 'knitwork'
|
||||
|
||||
type TemplateContext = {
|
||||
nuxt: Nuxt;
|
||||
@ -24,10 +25,8 @@ export const middlewareTemplate = {
|
||||
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')}
|
||||
}
|
||||
return `${_middleware.map(m => genImport(m.filePath, `$${hash(m.id)}`)).join('\n')}
|
||||
const middleware = ${genObjectFromRawEntries(_middleware.map(m => [m.id, `$${hash(m.id)}`]))}
|
||||
export default middleware`
|
||||
}
|
||||
}
|
||||
@ -49,14 +48,12 @@ export const storeTemplate = {
|
||||
|
||||
return `import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
${_storeModules.map(s => `import * as $${hash(s.id)} from '${s.filePath}'`).join('\n')}
|
||||
${_storeModules.map(s => genImport(s.filePath, { name: '*', as: `$${hash(s.id)}` })).join('\n')}
|
||||
Vue.use(Vuex)
|
||||
|
||||
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
|
||||
|
||||
const storeModules = {
|
||||
${_storeModules.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
|
||||
}
|
||||
const storeModules = ${genObjectFromRawEntries(_storeModules.map(m => [m.id, `$${hash(m.id)}`]))}
|
||||
|
||||
export function createStore() {
|
||||
let store = normalizeRoot(storeModules.root || {})
|
||||
|
@ -20,6 +20,7 @@
|
||||
"globby": "^13.1.1",
|
||||
"hash-sum": "^2.0.0",
|
||||
"jiti": "^1.12.15",
|
||||
"knitwork": "^0.1.0",
|
||||
"lodash.template": "^4.5.0",
|
||||
"mlly": "^0.4.1",
|
||||
"pathe": "^0.2.0",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { pascalCase, kebabCase } from 'scule'
|
||||
import type { ComponentsDir, Component } from '@nuxt/schema'
|
||||
import { genDynamicImport } from 'knitwork'
|
||||
import { useNuxt } from './context'
|
||||
import { assertNuxtCompatibility } from './compatibility'
|
||||
|
||||
@ -43,8 +44,8 @@ export async function addComponent (opts: AddComponentOptions) {
|
||||
shortPath: opts.filePath,
|
||||
async: false,
|
||||
level: 0,
|
||||
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
|
||||
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
|
||||
asyncImport: `${genDynamicImport(opts.filePath)}.then(r => r['${opts.export || 'default'}'])`,
|
||||
import: `require(${JSON.stringify(opts.filePath)})['${opts.export || 'default'}']`,
|
||||
|
||||
...opts
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import lodashTemplate from 'lodash.template'
|
||||
import hash from 'hash-sum'
|
||||
import { camelCase } from 'scule'
|
||||
import { basename, extname } from 'pathe'
|
||||
import { genDynamicImport, genImport } from 'knitwork'
|
||||
|
||||
import type { NuxtTemplate } from '@nuxt/schema'
|
||||
|
||||
@ -23,7 +24,7 @@ export async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
|
||||
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, r => JSON.parse(r).replace(/^{(.*)}$/, '$1'))
|
||||
|
||||
const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`
|
||||
|
||||
@ -33,9 +34,9 @@ const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
||||
}
|
||||
return sources.map((src) => {
|
||||
if (lazy) {
|
||||
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
|
||||
return `const ${importName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`
|
||||
}
|
||||
return `import ${importName(src)} from '${src}'`
|
||||
return genImport(src, importName(src))
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
"http-proxy": "^1.18.1",
|
||||
"is-primitive": "^3.0.1",
|
||||
"jiti": "^1.12.15",
|
||||
"knitwork": "^0.1.0",
|
||||
"listhen": "^0.2.6",
|
||||
"mime": "^3.0.0",
|
||||
"mlly": "^0.4.1",
|
||||
|
@ -2,6 +2,7 @@ import { relative, resolve, join } from 'pathe'
|
||||
import consola from 'consola'
|
||||
import * as rollup from 'rollup'
|
||||
import fse from 'fs-extra'
|
||||
import { genDynamicImport } from 'knitwork'
|
||||
import { printFSTree } from './utils/tree'
|
||||
import { getRollupConfig } from './rollup/config'
|
||||
import { hl, prettyPath, serializeTemplate, writeFile, isDirectory, replaceAll } from './utils'
|
||||
@ -73,7 +74,7 @@ export async function writeTypes (nitroContext: NitroContext) {
|
||||
if (typeof mw.handle !== 'string') { continue }
|
||||
const relativePath = relative(nitroContext._nuxt.buildDir, mw.handle).replace(/\.[a-z]+$/, '')
|
||||
routeTypes[mw.route] = routeTypes[mw.route] || []
|
||||
routeTypes[mw.route].push(`Awaited<ReturnType<typeof import('${relativePath}').default>>`)
|
||||
routeTypes[mw.route].push(`Awaited<ReturnType<typeof ${genDynamicImport(relativePath, { wrapper: false })}.default>>`)
|
||||
}
|
||||
|
||||
const lines = [
|
||||
|
@ -2,6 +2,7 @@ import { existsSync, promises as fsp } from 'fs'
|
||||
import { resolve } from 'pathe'
|
||||
import consola from 'consola'
|
||||
import { joinURL } from 'ufo'
|
||||
import { genString } from 'knitwork'
|
||||
import { extendPreset, prettyPath } from '../utils'
|
||||
import { NitroPreset, NitroContext, NitroInput } from '../context'
|
||||
import { worker } from './worker'
|
||||
@ -13,7 +14,7 @@ export const browser: NitroPreset = extendPreset(worker, (input: NitroInput) =>
|
||||
const script = `<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function () {
|
||||
navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}');
|
||||
navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))});
|
||||
});
|
||||
}
|
||||
</script>`
|
||||
@ -27,7 +28,7 @@ if ('serviceWorker' in navigator) {
|
||||
<link rel="prefetch" href="${joinURL(baseURL, '_server/index.mjs')}">
|
||||
<script>
|
||||
async function register () {
|
||||
const registration = await navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}')
|
||||
const registration = await navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))})
|
||||
await navigator.serviceWorker.ready
|
||||
registration.active.addEventListener('statechange', (event) => {
|
||||
if (event.target.state === 'activated') {
|
||||
@ -64,7 +65,7 @@ if ('serviceWorker' in navigator) {
|
||||
tmpl.contents = tmpl.contents.replace('</body>', script + '</body>')
|
||||
},
|
||||
async 'nitro:compiled' ({ output }: NitroContext) {
|
||||
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts('${joinURL(baseURL, '_server/index.mjs')}');`, 'utf8')
|
||||
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts(${genString(joinURL(baseURL, '_server/index.mjs'))});`, 'utf8')
|
||||
|
||||
// Temp fix
|
||||
if (!existsSync(resolve(output.publicDir, 'index.html'))) {
|
||||
|
@ -18,6 +18,7 @@ import devalue from '@nuxt/devalue'
|
||||
|
||||
import type { Preset } from 'unenv'
|
||||
import { sanitizeFilePath } from 'mlly'
|
||||
import { genImport } from 'knitwork'
|
||||
import { NitroContext } from '../context'
|
||||
import { resolvePath } from '../utils'
|
||||
import { pkgDir } from '../dirs'
|
||||
@ -215,7 +216,7 @@ export const getRollupConfig = (nitroContext: NitroContext) => {
|
||||
|
||||
// Polyfill
|
||||
rollupConfig.plugins.push(virtual({
|
||||
'#polyfill': env.polyfill.map(p => `import '${p}';`).join('\n')
|
||||
'#polyfill': env.polyfill.map(p => genImport(p)).join('\n')
|
||||
}))
|
||||
|
||||
// https://github.com/rollup/plugins/tree/master/packages/alias
|
||||
|
@ -4,6 +4,7 @@ import createEtag from 'etag'
|
||||
import mime from 'mime'
|
||||
import { resolve } from 'pathe'
|
||||
import { globby } from 'globby'
|
||||
import { genDynamicImport, genObjectFromRawEntries } from 'knitwork'
|
||||
import virtual from './virtual'
|
||||
|
||||
export interface AssetOptions {
|
||||
@ -81,9 +82,12 @@ function normalizeKey (key) {
|
||||
|
||||
function getAssetProd (assets: Record<string, Asset>) {
|
||||
return `
|
||||
const _assets = {\n${Object.entries(assets).map(([id, asset]) =>
|
||||
` ['${normalizeKey(id)}']: {\n import: () => import('${asset.fsPath}').then(r => r.default || r),\n meta: ${JSON.stringify(asset.meta)}\n }`
|
||||
).join(',\n')}\n}
|
||||
const _assets = ${genObjectFromRawEntries(
|
||||
Object.entries(assets).map(([id, asset]) => [normalizeKey(id), {
|
||||
import: genDynamicImport(asset.fsPath, { interopDefault: true }),
|
||||
meta: asset.meta
|
||||
}])
|
||||
)}
|
||||
|
||||
${normalizeKey.toString()}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { pathToFileURL } from 'url'
|
||||
import { resolve } from 'pathe'
|
||||
import { globby } from 'globby'
|
||||
import type { Plugin } from 'rollup'
|
||||
import { genDynamicImport, genObjectFromRawEntries, genImport } from 'knitwork'
|
||||
import { serializeImportName } from '../../utils'
|
||||
|
||||
const PLUGIN_NAME = 'dynamic-require'
|
||||
@ -36,7 +37,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
||||
name: PLUGIN_NAME,
|
||||
transform (code: string, _id: string) {
|
||||
return {
|
||||
code: code.replace(DYNAMIC_REQUIRE_RE, `import('${HELPER_DYNAMIC}').then(r => r.default || r).then(dynamicRequire => dynamicRequire($1)).then`),
|
||||
code: code.replace(DYNAMIC_REQUIRE_RE, `${genDynamicImport(HELPER_DYNAMIC, { wrapper: false, interopDefault: true })}.then(dynamicRequire => dynamicRequire($1)).then`),
|
||||
map: null
|
||||
}
|
||||
},
|
||||
@ -89,10 +90,8 @@ async function getWebpackChunkMeta (src: string) {
|
||||
}
|
||||
|
||||
function TMPL_INLINE ({ chunks }: TemplateContext) {
|
||||
return `${chunks.map(i => `import * as ${i.name} from '${i.src}'`).join('\n')}
|
||||
const dynamicChunks = {
|
||||
${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
|
||||
};
|
||||
return `${chunks.map(i => genImport(i.src, { name: '*', as: i.name })).join('\n')}
|
||||
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, i.name]))};
|
||||
|
||||
export default function dynamicRequire(id) {
|
||||
return Promise.resolve(dynamicChunks[id]);
|
||||
@ -101,9 +100,7 @@ export default function dynamicRequire(id) {
|
||||
|
||||
function TMPL_LAZY ({ chunks }: TemplateContext) {
|
||||
return `
|
||||
const dynamicChunks = {
|
||||
${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')}
|
||||
};
|
||||
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, genDynamicImport(i.src)]))};
|
||||
|
||||
export default function dynamicRequire(id) {
|
||||
return dynamicChunks[id]();
|
||||
|
@ -3,6 +3,7 @@ import { relative } from 'pathe'
|
||||
import table from 'table'
|
||||
import isPrimitive from 'is-primitive'
|
||||
import { isDebug } from 'std-env'
|
||||
import { genArrayFromRaw, genDynamicImport, genImport } from 'knitwork'
|
||||
import type { ServerMiddleware } from '../../server/middleware'
|
||||
import virtual from './virtual'
|
||||
|
||||
@ -35,15 +36,18 @@ export function middleware (getMiddleware: () => ServerMiddleware[]) {
|
||||
const lazyImports = unique(middleware.filter(m => m.lazy !== false && !imports.includes(m.handle)).map(m => m.handle))
|
||||
|
||||
return `
|
||||
${imports.map(handle => `import ${getImportId(handle)} from '${handle}';`).join('\n')}
|
||||
${imports.map(handle => `${genImport(handle, getImportId(handle))};`).join('\n')}
|
||||
|
||||
${lazyImports.map(handle => `const ${getImportId(handle)} = () => import('${handle}');`).join('\n')}
|
||||
${lazyImports.map(handle => `const ${getImportId(handle)} = ${genDynamicImport(handle)};`).join('\n')}
|
||||
|
||||
const middleware = [
|
||||
${middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')}
|
||||
];
|
||||
const middleware = ${genArrayFromRaw(middleware.map(m => ({
|
||||
route: JSON.stringify(m.route),
|
||||
handle: getImportId(m.handle),
|
||||
lazy: m.lazy || true,
|
||||
promisify: m.promisify !== undefined ? m.promisify : true
|
||||
})))};
|
||||
|
||||
export default middleware
|
||||
export default middleware
|
||||
`
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import virtual from '@rollup/plugin-virtual'
|
||||
import { genImport, genString } from 'knitwork'
|
||||
import { serializeImportName } from '../../utils'
|
||||
|
||||
export interface StorageOptions {
|
||||
@ -35,13 +36,13 @@ export function storage (opts: StorageOptions) {
|
||||
import { createStorage } from 'unstorage'
|
||||
import { assets } from '#assets'
|
||||
|
||||
${driverImports.map(i => `import ${serializeImportName(i)} from '${i}'`).join('\n')}
|
||||
${driverImports.map(i => genImport(i, serializeImportName(i))).join('\n')}
|
||||
|
||||
export const storage = createStorage({})
|
||||
|
||||
storage.mount('/assets', assets)
|
||||
|
||||
${mounts.map(m => `storage.mount('${m.path}', ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
|
||||
${mounts.map(m => `storage.mount(${genString(m.path)}, ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
|
||||
`
|
||||
})
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
"hash-sum": "^2.0.0",
|
||||
"hookable": "^5.1.1",
|
||||
"ignore": "^5.2.0",
|
||||
"knitwork": "^0.1.0",
|
||||
"mlly": "^0.4.1",
|
||||
"murmurhash-es": "^0.1.1",
|
||||
"nuxi": "3.0.0",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, addPluginTemplate, useNuxt } from '@nuxt/kit'
|
||||
import type { AutoImportsOptions } from '@nuxt/schema'
|
||||
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
|
||||
import { genDynamicImport } from 'knitwork'
|
||||
import { TransformPlugin } from './transform'
|
||||
import { Nuxt3AutoImports } from './imports'
|
||||
import { scanForComposables } from './composables'
|
||||
@ -132,7 +133,7 @@ function generateDts (ctx: AutoImportContext) {
|
||||
write: true,
|
||||
getContents: () => `// Generated by auto imports
|
||||
declare global {
|
||||
${ctx.autoImports.map(i => ` const ${i.as}: typeof import('${r(i.from)}')['${i.name}']`).join('\n')}
|
||||
${ctx.autoImports.map(i => ` const ${i.as}: typeof ${genDynamicImport(r(i.from), { wrapper: false })}['${i.name}']`).join('\n')}
|
||||
}
|
||||
|
||||
export {}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { AutoImport } from '@nuxt/schema'
|
||||
import { genExport, genImport, genString } from 'knitwork'
|
||||
|
||||
export function toImportModuleMap (autoImports: AutoImport[], isCJS = false) {
|
||||
const aliasKeyword = isCJS ? ' : ' : ' as '
|
||||
@ -20,11 +21,11 @@ export function toImports (autoImports: AutoImport[], isCJS = false) {
|
||||
const map = toImportModuleMap(autoImports, isCJS)
|
||||
if (isCJS) {
|
||||
return Object.entries(map)
|
||||
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require('${name}');`)
|
||||
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require(${genString(name)});`)
|
||||
.join('\n')
|
||||
} else {
|
||||
return Object.entries(map)
|
||||
.map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from '${name}';`)
|
||||
.map(([name, imports]) => genImport(name, Array.from(imports)))
|
||||
.join('\n')
|
||||
}
|
||||
}
|
||||
@ -32,7 +33,7 @@ export function toImports (autoImports: AutoImport[], isCJS = false) {
|
||||
export function toExports (autoImports: AutoImport[]) {
|
||||
const map = toImportModuleMap(autoImports, false)
|
||||
return Object.entries(map)
|
||||
.map(([name, imports]) => `export { ${Array.from(imports).join(', ')} } from '${name}';`)
|
||||
.map(([name, imports]) => genExport(name, Array.from(imports)))
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { createUnplugin } from 'unplugin'
|
||||
import { parseQuery, parseURL } from 'ufo'
|
||||
import { Component } from '@nuxt/schema'
|
||||
import { genImport } from 'knitwork'
|
||||
|
||||
interface LoaderOptions {
|
||||
getComponents(): Component[]
|
||||
@ -36,7 +37,7 @@ function transform (content: string, components: Component[]) {
|
||||
if (component) {
|
||||
const identifier = map.get(component) || `__nuxt_component_${num++}`
|
||||
map.set(component, identifier)
|
||||
imports += `import ${identifier} from "${component.filePath}";`
|
||||
imports += genImport(component.filePath, identifier)
|
||||
return ` ${identifier}`
|
||||
}
|
||||
// no matched
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
import { isAbsolute, join, relative } from 'pathe'
|
||||
import type { Component } from '@nuxt/schema'
|
||||
import { genDynamicImport, genObjectFromRawEntries } from 'knitwork'
|
||||
|
||||
export type ComponentsTemplateOptions = {
|
||||
buildDir?: string
|
||||
@ -27,14 +28,12 @@ export const componentsTemplate = {
|
||||
getContents ({ options }: { options: ComponentsTemplateOptions }) {
|
||||
return `import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const components = {
|
||||
${options.components.filter(c => c.global !== false).map((c) => {
|
||||
const components = ${genObjectFromRawEntries(options.components.filter(c => c.global !== false).map((c) => {
|
||||
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`
|
||||
const magicComments = createImportMagicComments(c)
|
||||
const comment = createImportMagicComments(c)
|
||||
|
||||
return ` '${c.pascalName}': defineAsyncComponent(() => import('${c.filePath}' /* ${magicComments} */).then(c => ${exp}))`
|
||||
}).join(',\n')}
|
||||
}
|
||||
return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`]
|
||||
}))}
|
||||
|
||||
export default function (nuxtApp) {
|
||||
for (const name in components) {
|
||||
@ -51,7 +50,7 @@ export const componentsTypeTemplate = {
|
||||
getContents: ({ options }: { options: ComponentsTemplateOptions }) => `// Generated by components discovery
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
${options.components.map(c => ` '${c.pascalName}': typeof import('${isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath}')['${c.export}']`).join(',\n')}
|
||||
${options.components.map(c => ` '${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')}
|
||||
}
|
||||
}
|
||||
export {}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { templateUtils } from '@nuxt/kit'
|
||||
import type { Nuxt, NuxtApp } from '@nuxt/schema'
|
||||
import { genArrayFromRaw, genDynamicImport, genExport, genImport } from 'knitwork'
|
||||
|
||||
import { isAbsolute, join, relative } from 'pathe'
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
@ -24,23 +25,17 @@ export const vueShim = {
|
||||
// TODO: Use an alias
|
||||
export const appComponentTemplate = {
|
||||
filename: 'app-component.mjs',
|
||||
getContents (ctx: TemplateContext) {
|
||||
return `export { default } from '${ctx.app.mainComponent}'`
|
||||
}
|
||||
getContents: (ctx: TemplateContext) => genExport(ctx.app.mainComponent, ['default'])
|
||||
}
|
||||
// TODO: Use an alias
|
||||
export const rootComponentTemplate = {
|
||||
filename: 'root-component.mjs',
|
||||
getContents (ctx: TemplateContext) {
|
||||
return `export { default } from '${ctx.app.rootComponent}'`
|
||||
}
|
||||
getContents: (ctx: TemplateContext) => genExport(ctx.app.rootComponent, ['default'])
|
||||
}
|
||||
|
||||
export const cssTemplate = {
|
||||
filename: 'css.mjs',
|
||||
getContents (ctx: TemplateContext) {
|
||||
return ctx.nuxt.options.css.map(i => `import '${i.src || i}';`).join('\n')
|
||||
}
|
||||
getContents: (ctx: TemplateContext) => ctx.nuxt.options.css.map(i => genImport(i.src || i)).join('\n')
|
||||
}
|
||||
|
||||
export const clientPluginTemplate = {
|
||||
@ -49,9 +44,7 @@ export const clientPluginTemplate = {
|
||||
const clientPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'server')
|
||||
return [
|
||||
templateUtils.importSources(clientPlugins.map(p => p.src)),
|
||||
'export default [',
|
||||
clientPlugins.map(p => templateUtils.importName(p.src)).join(',\n '),
|
||||
']'
|
||||
`export default ${genArrayFromRaw(clientPlugins.map(p => templateUtils.importName(p.src)))}`
|
||||
].join('\n')
|
||||
}
|
||||
}
|
||||
@ -63,10 +56,10 @@ export const serverPluginTemplate = {
|
||||
return [
|
||||
"import preload from '#app/plugins/preload.server'",
|
||||
templateUtils.importSources(serverPlugins.map(p => p.src)),
|
||||
'export default [',
|
||||
' preload,',
|
||||
serverPlugins.map(p => templateUtils.importName(p.src)).join(',\n '),
|
||||
']'
|
||||
`export default ${genArrayFromRaw([
|
||||
'preload',
|
||||
...serverPlugins.map(p => templateUtils.importName(p.src))
|
||||
])}`
|
||||
].join('\n')
|
||||
}
|
||||
}
|
||||
@ -103,7 +96,7 @@ type Decorate<T extends Record<string, any>> = { [K in keyof T as K extends stri
|
||||
|
||||
type InjectionType<A extends Plugin> = A extends Plugin<infer T> ? Decorate<T> : unknown
|
||||
|
||||
type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType<typeof import('${p}').default>`).join(' &\n ')}
|
||||
type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType<typeof ${genDynamicImport(p, { wrapper: false })}.default>`).join(' &\n ')}
|
||||
|
||||
declare module '#app' {
|
||||
interface NuxtApp extends NuxtAppInjections { }
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { existsSync } from 'fs'
|
||||
import { defineNuxtModule, addTemplate, addPlugin, templateUtils, addVitePlugin, addWebpackPlugin } from '@nuxt/kit'
|
||||
import { defineNuxtModule, addTemplate, addPlugin, addVitePlugin, addWebpackPlugin } from '@nuxt/kit'
|
||||
import { resolve } from 'pathe'
|
||||
import { genDynamicImport, genString, genArrayFromRaw, genImport, genObjectFromRawEntries } from 'knitwork'
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
import { distDir } from '../dirs'
|
||||
import { resolveLayouts, resolvePagesRoutes, normalizeRoutes, resolveMiddleware, getImportName } from './utils'
|
||||
@ -80,8 +81,8 @@ export default defineNuxtModule({
|
||||
async getContents () {
|
||||
const pages = await resolvePagesRoutes(nuxt)
|
||||
await nuxt.callHook('pages:extend', pages)
|
||||
const { routes: serializedRoutes, imports } = normalizeRoutes(pages)
|
||||
return [...imports, `export default ${templateUtils.serialize(serializedRoutes)}`].join('\n')
|
||||
const { routes, imports } = normalizeRoutes(pages)
|
||||
return [...imports, `export default ${routes}`].join('\n')
|
||||
}
|
||||
})
|
||||
|
||||
@ -92,11 +93,11 @@ export default defineNuxtModule({
|
||||
const middleware = await resolveMiddleware()
|
||||
const globalMiddleware = middleware.filter(mw => mw.global)
|
||||
const namedMiddleware = middleware.filter(mw => !mw.global)
|
||||
const namedMiddlewareObject = Object.fromEntries(namedMiddleware.map(mw => [mw.name, `{() => import('${mw.path}')}`]))
|
||||
const namedMiddlewareObject = genObjectFromRawEntries(namedMiddleware.map(mw => [mw.name, genDynamicImport(mw.path)]))
|
||||
return [
|
||||
...globalMiddleware.map(mw => `import ${getImportName(mw.name)} from '${mw.path}'`),
|
||||
`export const globalMiddleware = [${globalMiddleware.map(mw => getImportName(mw.name)).join(', ')}]`,
|
||||
`export const namedMiddleware = ${templateUtils.serialize(namedMiddlewareObject)}`
|
||||
...globalMiddleware.map(mw => genImport(mw.path, getImportName(mw.name))),
|
||||
`export const globalMiddleware = ${genArrayFromRaw(globalMiddleware.map(mw => getImportName(mw.name)))}`,
|
||||
`export const namedMiddleware = ${namedMiddlewareObject}`
|
||||
].join('\n')
|
||||
}
|
||||
})
|
||||
@ -109,8 +110,8 @@ export default defineNuxtModule({
|
||||
const namedMiddleware = middleware.filter(mw => !mw.global)
|
||||
return [
|
||||
'import type { NavigationGuard } from \'vue-router\'',
|
||||
`export type MiddlewareKey = ${namedMiddleware.map(mw => `"${mw.name}"`).join(' | ') || 'string'}`,
|
||||
`declare module '${composablesFile}' {`,
|
||||
`export type MiddlewareKey = ${namedMiddleware.map(mw => genString(mw.name)).join(' | ') || 'string'}`,
|
||||
`declare module ${genString(composablesFile)} {`,
|
||||
' interface PageMeta {',
|
||||
' middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>',
|
||||
' }',
|
||||
@ -126,8 +127,8 @@ export default defineNuxtModule({
|
||||
const layouts = await resolveLayouts(nuxt)
|
||||
return [
|
||||
'import { ComputedRef, Ref } from \'vue\'',
|
||||
`export type LayoutKey = ${layouts.map(layout => `"${layout.name}"`).join(' | ') || 'string'}`,
|
||||
`declare module '${composablesFile}' {`,
|
||||
`export type LayoutKey = ${layouts.map(layout => genString(layout.name)).join(' | ') || 'string'}`,
|
||||
`declare module ${genString(composablesFile)} {`,
|
||||
' interface PageMeta {',
|
||||
' layout?: false | LayoutKey | Ref<LayoutKey> | ComputedRef<LayoutKey>',
|
||||
' }',
|
||||
@ -141,12 +142,12 @@ export default defineNuxtModule({
|
||||
filename: 'layouts.mjs',
|
||||
async getContents () {
|
||||
const layouts = await resolveLayouts(nuxt)
|
||||
const layoutsObject = Object.fromEntries(layouts.map(({ name, file }) => {
|
||||
return [name, `{defineAsyncComponent({ suspensible: false, loader: () => import('${file}') })}`]
|
||||
const layoutsObject = genObjectFromRawEntries(layouts.map(({ name, file }) => {
|
||||
return [name, `defineAsyncComponent({ suspensible: false, loader: ${genDynamicImport(file)} })`]
|
||||
}))
|
||||
return [
|
||||
'import { defineAsyncComponent } from \'vue\'',
|
||||
`export default ${templateUtils.serialize(layoutsObject)}`
|
||||
`export default ${layoutsObject}`
|
||||
].join('\n')
|
||||
}
|
||||
})
|
||||
|
@ -3,6 +3,7 @@ import { encodePath } from 'ufo'
|
||||
import type { Nuxt, NuxtMiddleware, NuxtPage } from '@nuxt/schema'
|
||||
import { resolveFiles, useNuxt } from '@nuxt/kit'
|
||||
import { kebabCase, pascalCase } from 'scule'
|
||||
import { genImport, genDynamicImport, genArrayFromRaw } from 'knitwork'
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
|
||||
enum SegmentParserState {
|
||||
@ -225,20 +226,20 @@ export async function resolveLayouts (nuxt: Nuxt) {
|
||||
return layouts
|
||||
}
|
||||
|
||||
export function normalizeRoutes (routes: NuxtPage[], metaImports: Set<string> = new Set()): { imports: Set<string>, routes: NuxtPage[]} {
|
||||
export function normalizeRoutes (routes: NuxtPage[], metaImports: Set<string> = new Set()): { imports: Set<string>, routes: string } {
|
||||
return {
|
||||
imports: metaImports,
|
||||
routes: routes.map((route) => {
|
||||
routes: genArrayFromRaw(routes.map((route) => {
|
||||
const file = normalize(route.file)
|
||||
const metaImportName = getImportName(file) + 'Meta'
|
||||
metaImports.add(`import { meta as ${metaImportName} } from '${file}?macro=true'`)
|
||||
metaImports.add(genImport(`${file}?macro=true`, [{ name: 'meta', as: metaImportName }]))
|
||||
return {
|
||||
...route,
|
||||
...Object.fromEntries(Object.entries(route).map(([key, value]) => [key, JSON.stringify(value)])),
|
||||
children: route.children ? normalizeRoutes(route.children, metaImports).routes : [],
|
||||
meta: route.meta || `{${metaImportName}}` as any,
|
||||
component: `{() => import('${file}')}`
|
||||
meta: route.meta ? JSON.stringify(route.meta) : metaImportName,
|
||||
component: genDynamicImport(file)
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ describe('auto-imports:transform', () => {
|
||||
const transform = (code: string) => transformPlugin.transform.call({ error: null, warn: null }, code, '')
|
||||
|
||||
it('should correct inject', async () => {
|
||||
expect(await transform('const a = ref(0)')).to.equal('import { ref } from \'vue\';const a = ref(0)')
|
||||
expect(await transform('import { computed as ref } from "foo"; const a = ref(0)')).to.include('import { computed } from \'bar\';')
|
||||
expect(await transform('const a = ref(0)')).to.equal('import { ref } from "vue";const a = ref(0)')
|
||||
expect(await transform('import { computed as ref } from "foo"; const a = ref(0)')).to.include('import { computed } from "bar";')
|
||||
})
|
||||
|
||||
it('should ignore existing imported', async () => {
|
||||
@ -43,7 +43,7 @@ describe('auto-imports:transform', () => {
|
||||
|
||||
it('should ignore comments', async () => {
|
||||
const result = await transform('// import { computed } from "foo"\n;const a = computed(0)')
|
||||
expect(result).to.equal('import { computed } from \'bar\';// import { computed } from "foo"\n;const a = computed(0)')
|
||||
expect(result).to.equal('import { computed } from "bar";// import { computed } from "foo"\n;const a = computed(0)')
|
||||
})
|
||||
|
||||
it('should exclude files from transform', () => {
|
||||
|
@ -29,6 +29,7 @@
|
||||
"escape-string-regexp": "^5.0.0",
|
||||
"externality": "^0.1.6",
|
||||
"fs-extra": "^10.0.0",
|
||||
"knitwork": "^0.1.0",
|
||||
"magic-string": "^0.25.7",
|
||||
"mlly": "^0.4.1",
|
||||
"p-debounce": "^4.0.0",
|
||||
|
@ -4,6 +4,7 @@ import { builtinModules } from 'module'
|
||||
import { resolve } from 'pathe'
|
||||
import * as vite from 'vite'
|
||||
import { ExternalsOptions, isExternal as _isExternal, ExternalsDefaults } from 'externality'
|
||||
import { genDynamicImport, genObjectFromRawEntries } from 'knitwork'
|
||||
import { hashId, uniq } from './utils'
|
||||
|
||||
export interface TransformChunk {
|
||||
@ -78,7 +79,7 @@ async function transformRequest (opts: TransformOptions, id: string) {
|
||||
? withoutVersionQuery
|
||||
: pathToFileURL(withoutVersionQuery)
|
||||
return {
|
||||
code: `(global, exports, importMeta, ssrImport, ssrDynamicImport, ssrExportAll) => import('${path}').then(r => { exports.default = r.default; ssrExportAll(r) }).catch(e => { console.error(e); throw new Error('[vite dev] Error loading external "${id}".') })`,
|
||||
code: `(global, exports, importMeta, ssrImport, ssrDynamicImport, ssrExportAll) => ${genDynamicImport(path, { wrapper: false })}.then(r => { exports.default = r.default; ssrExportAll(r) }).catch(e => { console.error(e); throw new Error(${JSON.stringify(`[vite dev] Error loading external "${id}".`)}) })`,
|
||||
deps: [],
|
||||
dynamicDeps: []
|
||||
}
|
||||
@ -131,8 +132,9 @@ export async function bundleRequest (opts: TransformOptions, entryURL: string) {
|
||||
const ${hashId(chunk.id)} = ${chunk.code}
|
||||
`).join('\n')
|
||||
|
||||
const manifestCode = 'const __modules__ = {\n' +
|
||||
chunks.map(chunk => ` '${chunk.id}': ${hashId(chunk.id)}`).join(',\n') + '\n}'
|
||||
const manifestCode = `const __modules__ = ${
|
||||
genObjectFromRawEntries(chunks.map(chunk => [chunk.id, hashId(chunk.id)]))
|
||||
}`
|
||||
|
||||
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/ssr/ssrModuleLoader.ts
|
||||
const ssrModuleLoader = `
|
||||
@ -213,7 +215,7 @@ async function __instantiateModule__(url, urlStack) {
|
||||
chunksCode,
|
||||
manifestCode,
|
||||
ssrModuleLoader,
|
||||
`export default await __ssrLoadModule__('${entryURL}')`
|
||||
`export default await __ssrLoadModule__(${JSON.stringify(entryURL)})`
|
||||
].join('\n\n')
|
||||
|
||||
return {
|
||||
|
12
yarn.lock
12
yarn.lock
@ -2589,6 +2589,7 @@ __metadata:
|
||||
globby: ^13.1.1
|
||||
h3: ^0.3.9
|
||||
hash-sum: ^2.0.0
|
||||
knitwork: ^0.1.0
|
||||
magic-string: ^0.25.7
|
||||
mlly: ^0.4.1
|
||||
murmurhash-es: ^0.1.1
|
||||
@ -2900,6 +2901,7 @@ __metadata:
|
||||
globby: ^13.1.1
|
||||
hash-sum: ^2.0.0
|
||||
jiti: ^1.12.15
|
||||
knitwork: ^0.1.0
|
||||
lodash.template: ^4.5.0
|
||||
mlly: ^0.4.1
|
||||
pathe: ^0.2.0
|
||||
@ -2993,6 +2995,7 @@ __metadata:
|
||||
http-proxy: ^1.18.1
|
||||
is-primitive: ^3.0.1
|
||||
jiti: ^1.12.15
|
||||
knitwork: ^0.1.0
|
||||
listhen: ^0.2.6
|
||||
mime: ^3.0.0
|
||||
mlly: ^0.4.1
|
||||
@ -3265,6 +3268,7 @@ __metadata:
|
||||
escape-string-regexp: ^5.0.0
|
||||
externality: ^0.1.6
|
||||
fs-extra: ^10.0.0
|
||||
knitwork: ^0.1.0
|
||||
magic-string: ^0.25.7
|
||||
mlly: ^0.4.1
|
||||
p-debounce: ^4.0.0
|
||||
@ -12956,6 +12960,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"knitwork@npm:^0.1.0":
|
||||
version: 0.1.0
|
||||
resolution: "knitwork@npm:0.1.0"
|
||||
checksum: 36782ee8fcfb78a18684ff28ab6e829381d45a02cb8eb9efa192b3c521d9f6ff6d1ba3fbc28bdae471a9d251821ea99018a1f3e224e7b3cb62f72bbdb3a4cbd6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"kolorist@npm:^1.5.0":
|
||||
version: 1.5.1
|
||||
resolution: "kolorist@npm:1.5.1"
|
||||
@ -14979,6 +14990,7 @@ __metadata:
|
||||
hash-sum: ^2.0.0
|
||||
hookable: ^5.1.1
|
||||
ignore: ^5.2.0
|
||||
knitwork: ^0.1.0
|
||||
mlly: ^0.4.1
|
||||
murmurhash-es: ^0.1.1
|
||||
nuxi: 3.0.0
|
||||
|
Loading…
Reference in New Issue
Block a user