From e5d18474266f51197000ed48501805217bca9e54 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 29 Nov 2021 11:44:13 +0000 Subject: [PATCH 01/12] fix: sanitize import filenames in generated imports --- packages/bridge/src/vite/templates.ts | 4 ++-- packages/kit/src/components.ts | 4 ++-- packages/kit/src/internal/template.ts | 4 ++-- packages/nitro/src/build.ts | 2 +- packages/nitro/src/rollup/plugins/assets.ts | 2 +- packages/nitro/src/rollup/plugins/dynamic-require.ts | 6 +++--- packages/nitro/src/rollup/plugins/middleware.ts | 4 ++-- packages/nitro/src/rollup/plugins/storage.ts | 2 +- packages/nuxt3/src/auto-imports/module.ts | 2 +- packages/nuxt3/src/auto-imports/utils.ts | 4 ++-- packages/nuxt3/src/components/templates.ts | 4 ++-- packages/nuxt3/src/core/templates.ts | 8 ++++---- packages/nuxt3/src/pages/module.ts | 2 +- packages/nuxt3/src/pages/utils.ts | 2 +- packages/vite/src/dev-bundler.ts | 2 +- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/bridge/src/vite/templates.ts b/packages/bridge/src/vite/templates.ts index 845980bc7ea..8604a986685 100644 --- a/packages/bridge/src/vite/templates.ts +++ b/packages/bridge/src/vite/templates.ts @@ -24,7 +24,7 @@ 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')} + return `${_middleware.map(m => `import $${hash(m.id)} from ${JSON.stringify(m.filePath)}`).join('\n')} const middleware = { ${_middleware.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')} } @@ -49,7 +49,7 @@ 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 => `import * as $${hash(s.id)} from ${JSON.stringify(s.filePath)}`).join('\n')} Vue.use(Vuex) const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations'] diff --git a/packages/kit/src/components.ts b/packages/kit/src/components.ts index 6b8486ca231..e6c17b69549 100644 --- a/packages/kit/src/components.ts +++ b/packages/kit/src/components.ts @@ -43,8 +43,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: `() => import(${JSON.stringify(opts.filePath)}).then(r => r['${opts.export || 'default'}'])`, + import: `require(${JSON.stringify(opts.filePath)})['${opts.export || 'default'}']`, ...opts } diff --git a/packages/kit/src/internal/template.ts b/packages/kit/src/internal/template.ts index 46d63d02862..08472faa676 100644 --- a/packages/kit/src/internal/template.ts +++ b/packages/kit/src/internal/template.ts @@ -33,9 +33,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)} = () => import(${JSON.stringify(src)} /* webpackChunkName: ${JSON.stringify(src)} */)` } - return `import ${importName(src)} from '${src}'` + return `import ${importName(src)} from ${JSON.stringify(src)}` }).join('\n') } diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 1e8e9e5f7b6..e5e57cf027d 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -73,7 +73,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>`) + routeTypes[mw.route].push(`Awaited>`) } const lines = [ diff --git a/packages/nitro/src/rollup/plugins/assets.ts b/packages/nitro/src/rollup/plugins/assets.ts index 21ca09178fe..0d520846716 100644 --- a/packages/nitro/src/rollup/plugins/assets.ts +++ b/packages/nitro/src/rollup/plugins/assets.ts @@ -82,7 +82,7 @@ function normalizeKey (key) { function getAssetProd (assets: Record) { 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 }` + ` ['${normalizeKey(id)}']: {\n import: () => import(${JSON.stringify(asset.fsPath)}).then(r => r.default || r),\n meta: ${JSON.stringify(asset.meta)}\n }` ).join(',\n')}\n} ${normalizeKey.toString()} diff --git a/packages/nitro/src/rollup/plugins/dynamic-require.ts b/packages/nitro/src/rollup/plugins/dynamic-require.ts index 3c5e2e80f65..4013f0d13fd 100644 --- a/packages/nitro/src/rollup/plugins/dynamic-require.ts +++ b/packages/nitro/src/rollup/plugins/dynamic-require.ts @@ -36,7 +36,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, `import(${JSON.stringify(HELPER_DYNAMIC)}).then(r => r.default || r).then(dynamicRequire => dynamicRequire($1)).then`), map: null } }, @@ -89,7 +89,7 @@ async function getWebpackChunkMeta (src: string) { } function TMPL_INLINE ({ chunks }: TemplateContext) { - return `${chunks.map(i => `import * as ${i.name} from '${i.src}'`).join('\n')} + return `${chunks.map(i => `import * as ${i.name} from ${JSON.stringify(i.src)}`).join('\n')} const dynamicChunks = { ${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} }; @@ -102,7 +102,7 @@ export default function dynamicRequire(id) { function TMPL_LAZY ({ chunks }: TemplateContext) { return ` const dynamicChunks = { -${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')} +${chunks.map(i => ` ['${i.id}']: () => import(${JSON.stringify(i.src)})`).join(',\n')} }; export default function dynamicRequire(id) { diff --git a/packages/nitro/src/rollup/plugins/middleware.ts b/packages/nitro/src/rollup/plugins/middleware.ts index 895ca03f00c..5358e3dff27 100644 --- a/packages/nitro/src/rollup/plugins/middleware.ts +++ b/packages/nitro/src/rollup/plugins/middleware.ts @@ -35,9 +35,9 @@ 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 => `import ${getImportId(handle)} from ${JSON.stringify(handle)};`).join('\n')} - ${lazyImports.map(handle => `const ${getImportId(handle)} = () => import('${handle}');`).join('\n')} + ${lazyImports.map(handle => `const ${getImportId(handle)} = () => import(${JSON.stringify(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')} diff --git a/packages/nitro/src/rollup/plugins/storage.ts b/packages/nitro/src/rollup/plugins/storage.ts index 63d96214f2a..85441c1b5c5 100644 --- a/packages/nitro/src/rollup/plugins/storage.ts +++ b/packages/nitro/src/rollup/plugins/storage.ts @@ -35,7 +35,7 @@ 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 => `import ${serializeImportName(i)} from ${JSON.stringify(i)}`).join('\n')} export const storage = createStorage({}) diff --git a/packages/nuxt3/src/auto-imports/module.ts b/packages/nuxt3/src/auto-imports/module.ts index 4674298cd7a..c4b17621b66 100644 --- a/packages/nuxt3/src/auto-imports/module.ts +++ b/packages/nuxt3/src/auto-imports/module.ts @@ -132,7 +132,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 import(${JSON.stringify(r(i.from))})['${i.name}']`).join('\n')} } export {} diff --git a/packages/nuxt3/src/auto-imports/utils.ts b/packages/nuxt3/src/auto-imports/utils.ts index 872d179fa57..1c073558ca2 100644 --- a/packages/nuxt3/src/auto-imports/utils.ts +++ b/packages/nuxt3/src/auto-imports/utils.ts @@ -20,11 +20,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(${JSON.stringify(name)});`) .join('\n') } else { return Object.entries(map) - .map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from '${name}';`) + .map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from ${JSON.stringify(name)};`) .join('\n') } } diff --git a/packages/nuxt3/src/components/templates.ts b/packages/nuxt3/src/components/templates.ts index 1652796b6fb..2e8df9576c7 100644 --- a/packages/nuxt3/src/components/templates.ts +++ b/packages/nuxt3/src/components/templates.ts @@ -32,7 +32,7 @@ ${options.components.filter(c => c.global !== false).map((c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const magicComments = createImportMagicComments(c) - return ` '${c.pascalName}': defineAsyncComponent(() => import('${c.filePath}' /* ${magicComments} */).then(c => ${exp}))` + return ` '${c.pascalName}': defineAsyncComponent(() => import(${JSON.stringify(c.filePath)} /* ${magicComments} */).then(c => ${exp}))` }).join(',\n')} } @@ -52,7 +52,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('${relative(options.buildDir, c.filePath)}')['${c.export}']`).join(',\n')} +${options.components.map(c => ` '${c.pascalName}': typeof import(${JSON.stringify(relative(options.buildDir, c.filePath))})['${c.export}']`).join(',\n')} } } export {} diff --git a/packages/nuxt3/src/core/templates.ts b/packages/nuxt3/src/core/templates.ts index 5955095b0ae..a27db8832a2 100644 --- a/packages/nuxt3/src/core/templates.ts +++ b/packages/nuxt3/src/core/templates.ts @@ -25,21 +25,21 @@ export const vueShim = { export const appComponentTemplate = { filename: 'app-component.mjs', getContents (ctx: TemplateContext) { - return `export { default } from '${ctx.app.mainComponent}'` + return `export { default } from ${JSON.stringify(ctx.app.mainComponent)}` } } // TODO: Use an alias export const rootComponentTemplate = { filename: 'root-component.mjs', getContents (ctx: TemplateContext) { - return `export { default } from '${ctx.app.rootComponent}'` + return `export { default } from ${JSON.stringify(ctx.app.rootComponent)}` } } export const cssTemplate = { filename: 'css.mjs', getContents (ctx: TemplateContext) { - return ctx.nuxt.options.css.map(i => `import '${i.src || i}';`).join('\n') + return ctx.nuxt.options.css.map(i => `import ${JSON.stringify(i.src || i)};`).join('\n') } } @@ -104,7 +104,7 @@ type Decorate> = { [K in keyof T as K extends stri type InjectionType = A extends Plugin ? Decorate : unknown -type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType`).join(' &\n ')} +type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType`).join(' &\n ')} declare module '#app' { interface NuxtApp extends NuxtAppInjections { } diff --git a/packages/nuxt3/src/pages/module.ts b/packages/nuxt3/src/pages/module.ts index 85300296a63..b3983c5ec92 100644 --- a/packages/nuxt3/src/pages/module.ts +++ b/packages/nuxt3/src/pages/module.ts @@ -122,7 +122,7 @@ export default defineNuxtModule({ async getContents () { const layouts = await resolveLayouts(nuxt) const layoutsObject = Object.fromEntries(layouts.map(({ name, file }) => { - return [name, `{defineAsyncComponent({ suspensible: false, loader: () => import('${file}') })}`] + return [name, `{defineAsyncComponent({ suspensible: false, loader: () => import(${JSON.stringify(file)}) })}`] })) return [ 'import { defineAsyncComponent } from \'vue\'', diff --git a/packages/nuxt3/src/pages/utils.ts b/packages/nuxt3/src/pages/utils.ts index 2a166169abe..c8cdd61ff1a 100644 --- a/packages/nuxt3/src/pages/utils.ts +++ b/packages/nuxt3/src/pages/utils.ts @@ -233,7 +233,7 @@ export function normalizeRoutes (routes: NuxtPage[], metaImports: Set = ...route, children: route.children ? normalizeRoutes(route.children, metaImports).routes : [], meta: route.meta || `{${metaImportName}}` as any, - component: `{() => import('${file}')}` + component: `{() => import(${JSON.stringify(file)})}` } }) } diff --git a/packages/vite/src/dev-bundler.ts b/packages/vite/src/dev-bundler.ts index c13e5f0697f..3ba7a2eb765 100644 --- a/packages/vite/src/dev-bundler.ts +++ b/packages/vite/src/dev-bundler.ts @@ -78,7 +78,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) => import(${JSON.stringify(path)}).then(r => { exports.default = r.default; ssrExportAll(r) }).catch(e => { console.error(e); throw new Error('[vite dev] Error loading external "${id}".') })`, deps: [], dynamicDeps: [] } From ea07b7b8bc392129ccac9eaaea98dfed6a0d0688 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 29 Nov 2021 14:08:04 +0000 Subject: [PATCH 02/12] fix: handle other cases --- packages/bridge/src/vite/templates.ts | 4 ++-- packages/vite/src/dev-bundler.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/bridge/src/vite/templates.ts b/packages/bridge/src/vite/templates.ts index 8604a986685..a28527b0946 100644 --- a/packages/bridge/src/vite/templates.ts +++ b/packages/bridge/src/vite/templates.ts @@ -26,7 +26,7 @@ export const middlewareTemplate = { }) return `${_middleware.map(m => `import $${hash(m.id)} from ${JSON.stringify(m.filePath)}`).join('\n')} const middleware = { -${_middleware.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')} +${_middleware.map(m => ` [${JSON.stringify(m.id)}]: $${hash(m.id)}`).join(',\n')} } export default middleware` } @@ -55,7 +55,7 @@ Vue.use(Vuex) const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations'] const storeModules = { -${_storeModules.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')} +${_storeModules.map(m => ` [${JSON.stringify(m.id)}]: $${hash(m.id)}`).join(',\n')} } export function createStore() { diff --git a/packages/vite/src/dev-bundler.ts b/packages/vite/src/dev-bundler.ts index 3ba7a2eb765..665a2922517 100644 --- a/packages/vite/src/dev-bundler.ts +++ b/packages/vite/src/dev-bundler.ts @@ -78,7 +78,7 @@ async function transformRequest (opts: TransformOptions, id: string) { ? withoutVersionQuery : pathToFileURL(withoutVersionQuery) return { - code: `(global, exports, importMeta, ssrImport, ssrDynamicImport, ssrExportAll) => import(${JSON.stringify(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) => import(${JSON.stringify(path)}).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: [] } @@ -132,7 +132,7 @@ const ${hashId(chunk.id)} = ${chunk.code} `).join('\n') const manifestCode = 'const __modules__ = {\n' + - chunks.map(chunk => ` '${chunk.id}': ${hashId(chunk.id)}`).join(',\n') + '\n}' + chunks.map(chunk => ` ${JSON.stringify(chunk.id)}: ${hashId(chunk.id)}`).join(',\n') + '\n}' // https://github.com/vitejs/vite/blob/main/packages/vite/src/node/ssr/ssrModuleLoader.ts const ssrModuleLoader = ` @@ -213,7 +213,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 { From ccc404e624493b0fc0fdea3f5d1681ee16f3e202 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 29 Nov 2021 14:10:08 +0000 Subject: [PATCH 03/12] test: update snapshots --- packages/nuxt3/test/auto-imports.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nuxt3/test/auto-imports.test.ts b/packages/nuxt3/test/auto-imports.test.ts index 4481da4325f..37679ad3a30 100644 --- a/packages/nuxt3/test/auto-imports.test.ts +++ b/packages/nuxt3/test/auto-imports.test.ts @@ -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', async () => { From ba43b87f6ea001bc7a6396dd5955d5710c616d16 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 29 Nov 2021 14:41:05 +0000 Subject: [PATCH 04/12] fix: handled escaped characters within deserialized json --- packages/kit/src/internal/template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/internal/template.ts b/packages/kit/src/internal/template.ts index 08472faa676..1dda65b655a 100644 --- a/packages/kit/src/internal/template.ts +++ b/packages/kit/src/internal/template.ts @@ -23,7 +23,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)}` From 666d7a7fe16eb82bd8e934044e6aee8bfa22dd02 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 29 Nov 2021 16:09:29 +0000 Subject: [PATCH 05/12] fix: correct isExternal syntax error --- packages/vite/src/dev-bundler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/dev-bundler.ts b/packages/vite/src/dev-bundler.ts index 665a2922517..b5f607cc38b 100644 --- a/packages/vite/src/dev-bundler.ts +++ b/packages/vite/src/dev-bundler.ts @@ -78,7 +78,7 @@ async function transformRequest (opts: TransformOptions, id: string) { ? withoutVersionQuery : pathToFileURL(withoutVersionQuery) return { - code: `(global, exports, importMeta, ssrImport, ssrDynamicImport, ssrExportAll) => import(${JSON.stringify(path)}).then(r => { exports.default = r.default; ssrExportAll(r) }).catch(e => { console.error(e); throw new Error(${JSON.stringify(`[vite dev] Error loading external "${id}".`)})`, + code: `(global, exports, importMeta, ssrImport, ssrDynamicImport, ssrExportAll) => import(${JSON.stringify(path)}).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: [] } From e52cb3d74d66693e5799c9469ac3d07f4975b000 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 30 Nov 2021 14:51:09 +0000 Subject: [PATCH 06/12] refactor: use `mlly` utilities https://github.com/unjs/mlly/pull/24 --- packages/bridge/src/vite/templates.ts | 13 ++++----- packages/kit/src/components.ts | 3 ++- packages/kit/src/internal/template.ts | 5 ++-- packages/nitro/src/build.ts | 3 ++- packages/nitro/src/rollup/config.ts | 4 +-- packages/nitro/src/rollup/plugins/assets.ts | 10 ++++--- .../src/rollup/plugins/dynamic-require.ts | 13 ++++----- .../nitro/src/rollup/plugins/middleware.ts | 16 ++++++----- packages/nitro/src/rollup/plugins/storage.ts | 3 ++- packages/nuxt3/src/auto-imports/module.ts | 3 ++- packages/nuxt3/src/auto-imports/utils.ts | 5 ++-- packages/nuxt3/src/components/loader.ts | 3 ++- packages/nuxt3/src/components/templates.ts | 13 +++++---- packages/nuxt3/src/core/templates.ts | 27 +++++++------------ packages/nuxt3/src/pages/module.ts | 9 ++++--- packages/nuxt3/src/pages/utils.ts | 9 ++++--- packages/vite/src/dev-bundler.ts | 8 +++--- 17 files changed, 76 insertions(+), 71 deletions(-) diff --git a/packages/bridge/src/vite/templates.ts b/packages/bridge/src/vite/templates.ts index a28527b0946..f1febcc3835 100644 --- a/packages/bridge/src/vite/templates.ts +++ b/packages/bridge/src/vite/templates.ts @@ -2,6 +2,7 @@ import hash from 'hash-sum' import { resolve } from 'pathe' import type { Nuxt, NuxtApp } from '@nuxt/schema' +import { genImport, genObjectFromRawEntries } from 'mlly' 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 ${JSON.stringify(m.filePath)}`).join('\n')} -const middleware = { -${_middleware.map(m => ` [${JSON.stringify(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 ${JSON.stringify(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 => ` [${JSON.stringify(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 || {}) diff --git a/packages/kit/src/components.ts b/packages/kit/src/components.ts index e6c17b69549..bc872f86a30 100644 --- a/packages/kit/src/components.ts +++ b/packages/kit/src/components.ts @@ -1,5 +1,6 @@ import { pascalCase, kebabCase } from 'scule' import type { ComponentsDir, Component } from '@nuxt/schema' +import { genDynamicImport } from 'mlly' import { useNuxt } from './context' import { assertNuxtCompatibility } from './compatibility' @@ -43,7 +44,7 @@ export async function addComponent (opts: AddComponentOptions) { shortPath: opts.filePath, async: false, level: 0, - asyncImport: `() => import(${JSON.stringify(opts.filePath)}).then(r => r['${opts.export || 'default'}'])`, + asyncImport: `${genDynamicImport(opts.filePath)}.then(r => r['${opts.export || 'default'}'])`, import: `require(${JSON.stringify(opts.filePath)})['${opts.export || 'default'}']`, ...opts diff --git a/packages/kit/src/internal/template.ts b/packages/kit/src/internal/template.ts index 1dda65b655a..6eabf35de87 100644 --- a/packages/kit/src/internal/template.ts +++ b/packages/kit/src/internal/template.ts @@ -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 'mlly' import type { NuxtTemplate } from '@nuxt/schema' @@ -33,9 +34,9 @@ const importSources = (sources: string | string[], { lazy = false } = {}) => { } return sources.map((src) => { if (lazy) { - return `const ${importName(src)} = () => import(${JSON.stringify(src)} /* webpackChunkName: ${JSON.stringify(src)} */)` + return `const ${importName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}` } - return `import ${importName(src)} from ${JSON.stringify(src)}` + return genImport(src, importName(src)) }).join('\n') } diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index e5e57cf027d..38e55260bb5 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -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 'mlly' 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>`) + routeTypes[mw.route].push(`Awaited>`) } const lines = [ diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 57fcbb2553e..55f266ae535 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -17,7 +17,7 @@ import * as unenv from 'unenv' import devalue from '@nuxt/devalue' import type { Preset } from 'unenv' -import { sanitizeFilePath } from 'mlly' +import { sanitizeFilePath, genImport } from 'mlly' import { NitroContext } from '../context' import { resolvePath } from '../utils' import { pkgDir } from '../dirs' @@ -215,7 +215,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 diff --git a/packages/nitro/src/rollup/plugins/assets.ts b/packages/nitro/src/rollup/plugins/assets.ts index 0d520846716..b516b6aebcd 100644 --- a/packages/nitro/src/rollup/plugins/assets.ts +++ b/packages/nitro/src/rollup/plugins/assets.ts @@ -4,6 +4,7 @@ import createEtag from 'etag' import mime from 'mime' import { resolve } from 'pathe' import { globby } from 'globby' +import { genDynamicImport, genObjectFromRawEntries } from 'mlly' import virtual from './virtual' export interface AssetOptions { @@ -81,9 +82,12 @@ function normalizeKey (key) { function getAssetProd (assets: Record) { return ` -const _assets = {\n${Object.entries(assets).map(([id, asset]) => - ` ['${normalizeKey(id)}']: {\n import: () => import(${JSON.stringify(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()} diff --git a/packages/nitro/src/rollup/plugins/dynamic-require.ts b/packages/nitro/src/rollup/plugins/dynamic-require.ts index 4013f0d13fd..da65f0cbbd7 100644 --- a/packages/nitro/src/rollup/plugins/dynamic-require.ts +++ b/packages/nitro/src/rollup/plugins/dynamic-require.ts @@ -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 'mlly' 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(${JSON.stringify(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 ${JSON.stringify(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(${JSON.stringify(i.src)})`).join(',\n')} -}; +const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, genDynamicImport(i.src)]))}; export default function dynamicRequire(id) { return dynamicChunks[id](); diff --git a/packages/nitro/src/rollup/plugins/middleware.ts b/packages/nitro/src/rollup/plugins/middleware.ts index 5358e3dff27..e15920a46ae 100644 --- a/packages/nitro/src/rollup/plugins/middleware.ts +++ b/packages/nitro/src/rollup/plugins/middleware.ts @@ -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 'mlly' 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 ${JSON.stringify(handle)};`).join('\n')} +${imports.map(handle => `${genImport(handle, getImportId(handle))};`).join('\n')} - ${lazyImports.map(handle => `const ${getImportId(handle)} = () => import(${JSON.stringify(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 ` } } diff --git a/packages/nitro/src/rollup/plugins/storage.ts b/packages/nitro/src/rollup/plugins/storage.ts index 85441c1b5c5..d508c60ad2b 100644 --- a/packages/nitro/src/rollup/plugins/storage.ts +++ b/packages/nitro/src/rollup/plugins/storage.ts @@ -1,4 +1,5 @@ import virtual from '@rollup/plugin-virtual' +import { genImport } from 'mlly' import { serializeImportName } from '../../utils' export interface StorageOptions { @@ -35,7 +36,7 @@ export function storage (opts: StorageOptions) { import { createStorage } from 'unstorage' import { assets } from '#assets' -${driverImports.map(i => `import ${serializeImportName(i)} from ${JSON.stringify(i)}`).join('\n')} +${driverImports.map(i => genImport(i, serializeImportName(i))).join('\n')} export const storage = createStorage({}) diff --git a/packages/nuxt3/src/auto-imports/module.ts b/packages/nuxt3/src/auto-imports/module.ts index c4b17621b66..b3d650603a6 100644 --- a/packages/nuxt3/src/auto-imports/module.ts +++ b/packages/nuxt3/src/auto-imports/module.ts @@ -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 'mlly' 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(${JSON.stringify(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 {} diff --git a/packages/nuxt3/src/auto-imports/utils.ts b/packages/nuxt3/src/auto-imports/utils.ts index 1c073558ca2..c73da253a35 100644 --- a/packages/nuxt3/src/auto-imports/utils.ts +++ b/packages/nuxt3/src/auto-imports/utils.ts @@ -1,4 +1,5 @@ import type { AutoImport } from '@nuxt/schema' +import { genExport, genImport } from 'mlly' export function toImportModuleMap (autoImports: AutoImport[], isCJS = false) { const aliasKeyword = isCJS ? ' : ' : ' as ' @@ -24,7 +25,7 @@ export function toImports (autoImports: AutoImport[], isCJS = false) { .join('\n') } else { return Object.entries(map) - .map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from ${JSON.stringify(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, imports)) .join('\n') } diff --git a/packages/nuxt3/src/components/loader.ts b/packages/nuxt3/src/components/loader.ts index 7477d178552..573c8223f2a 100644 --- a/packages/nuxt3/src/components/loader.ts +++ b/packages/nuxt3/src/components/loader.ts @@ -1,6 +1,7 @@ import { createUnplugin } from 'unplugin' import { parseQuery, parseURL } from 'ufo' import { Component } from '@nuxt/schema' +import { genImport } from 'mlly' 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 diff --git a/packages/nuxt3/src/components/templates.ts b/packages/nuxt3/src/components/templates.ts index 2e8df9576c7..52a4bc98786 100644 --- a/packages/nuxt3/src/components/templates.ts +++ b/packages/nuxt3/src/components/templates.ts @@ -1,6 +1,7 @@ import { relative } from 'pathe' import type { Component } from '@nuxt/schema' +import { genDynamicImport, genObjectFromRawEntries } from 'mlly' 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(${JSON.stringify(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) { @@ -52,7 +51,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(${JSON.stringify(relative(options.buildDir, c.filePath))})['${c.export}']`).join(',\n')} +${options.components.map(c => ` '${c.pascalName}': typeof ${genDynamicImport(relative(options.buildDir, c.filePath), { wrapper: false })}['${c.export}']`).join(',\n')} } } export {} diff --git a/packages/nuxt3/src/core/templates.ts b/packages/nuxt3/src/core/templates.ts index a27db8832a2..b21b7ff8951 100644 --- a/packages/nuxt3/src/core/templates.ts +++ b/packages/nuxt3/src/core/templates.ts @@ -1,5 +1,6 @@ import { templateUtils } from '@nuxt/kit' import type { Nuxt, NuxtApp } from '@nuxt/schema' +import { genArrayFromRaw, genDynamicImport, genExport, genImport } from 'mlly' import { relative } from 'pathe' @@ -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 ${JSON.stringify(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 ${JSON.stringify(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 ${JSON.stringify(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') } } @@ -104,7 +97,7 @@ type Decorate> = { [K in keyof T as K extends stri type InjectionType = A extends Plugin ? Decorate : unknown -type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType`).join(' &\n ')} +type NuxtAppInjections = \n ${tsImports.map(p => `InjectionType`).join(' &\n ')} declare module '#app' { interface NuxtApp extends NuxtAppInjections { } diff --git a/packages/nuxt3/src/pages/module.ts b/packages/nuxt3/src/pages/module.ts index b3983c5ec92..0b8bd99ec77 100644 --- a/packages/nuxt3/src/pages/module.ts +++ b/packages/nuxt3/src/pages/module.ts @@ -1,6 +1,7 @@ import { existsSync } from 'fs' import { defineNuxtModule, addTemplate, addPlugin, templateUtils, addVitePlugin, addWebpackPlugin } from '@nuxt/kit' import { resolve } from 'pathe' +import { genDynamicImport, genObjectFromRawEntries } from 'mlly' import { distDir } from '../dirs' import { resolveLayouts, resolvePagesRoutes, normalizeRoutes, resolveMiddleware, getImportName } from './utils' import { TransformMacroPlugin, TransformMacroPluginOptions } from './macros' @@ -74,7 +75,7 @@ export default defineNuxtModule({ 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') + return [...imports, `export default ${serializedRoutes}`].join('\n') } }) @@ -121,12 +122,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(${JSON.stringify(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') } }) diff --git a/packages/nuxt3/src/pages/utils.ts b/packages/nuxt3/src/pages/utils.ts index c8cdd61ff1a..36197aed7d6 100644 --- a/packages/nuxt3/src/pages/utils.ts +++ b/packages/nuxt3/src/pages/utils.ts @@ -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 { genDynamicImport, genArrayFromRaw } from 'mlly' enum SegmentParserState { initial, @@ -225,17 +226,17 @@ export async function resolveLayouts (nuxt: Nuxt) { export function normalizeRoutes (routes: NuxtPage[], metaImports: Set = new Set()): { imports: Set, routes: NuxtPage[]} { 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'`) 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(${JSON.stringify(file)})}` + component: genDynamicImport(file) } - }) + })) } } diff --git a/packages/vite/src/dev-bundler.ts b/packages/vite/src/dev-bundler.ts index b5f607cc38b..f0b01b7ed17 100644 --- a/packages/vite/src/dev-bundler.ts +++ b/packages/vite/src/dev-bundler.ts @@ -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 'mlly' 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(${JSON.stringify(path)}).then(r => { exports.default = r.default; ssrExportAll(r) }).catch(e => { console.error(e); throw new Error(${JSON.stringify(`[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 => ` ${JSON.stringify(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 = ` From e5b9ea04e9f72a37031b6c3f4df183ac29ccad9a Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 25 Jan 2022 15:20:14 +0000 Subject: [PATCH 07/12] refactor: migrate to `knitwork` --- packages/bridge/src/vite/templates.ts | 4 ++-- packages/kit/package.json | 1 + packages/kit/src/components.ts | 2 +- packages/kit/src/internal/template.ts | 2 +- packages/nitro/package.json | 1 + packages/nitro/src/build.ts | 2 +- packages/nitro/src/rollup/config.ts | 3 ++- packages/nitro/src/rollup/plugins/assets.ts | 2 +- packages/nitro/src/rollup/plugins/dynamic-require.ts | 2 +- packages/nitro/src/rollup/plugins/middleware.ts | 2 +- packages/nitro/src/rollup/plugins/storage.ts | 2 +- packages/nuxt3/build.config.ts | 1 + packages/nuxt3/package.json | 1 + packages/nuxt3/src/auto-imports/module.ts | 2 +- packages/nuxt3/src/auto-imports/utils.ts | 2 +- packages/nuxt3/src/components/loader.ts | 2 +- packages/nuxt3/src/components/templates.ts | 2 +- packages/nuxt3/src/core/templates.ts | 2 +- packages/nuxt3/src/pages/module.ts | 2 +- packages/vite/package.json | 1 + packages/vite/src/dev-bundler.ts | 2 +- yarn.lock | 11 +++++++++++ 22 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/bridge/src/vite/templates.ts b/packages/bridge/src/vite/templates.ts index f1febcc3835..ac5971bdce0 100644 --- a/packages/bridge/src/vite/templates.ts +++ b/packages/bridge/src/vite/templates.ts @@ -2,7 +2,7 @@ import hash from 'hash-sum' import { resolve } from 'pathe' import type { Nuxt, NuxtApp } from '@nuxt/schema' -import { genImport, genObjectFromRawEntries } from 'mlly' +import { genImport, genObjectFromRawEntries } from 'knitwork' type TemplateContext = { nuxt: Nuxt; @@ -25,7 +25,7 @@ export const middlewareTemplate = { id: m.name || m.src.replace(/[\\/]/g, '/').replace(/\.(js|ts)$/, '') } }) - return `${_middleware.map(m => genImport(m.filePath,`$${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` } diff --git a/packages/kit/package.json b/packages/kit/package.json index 4627a6cb0d3..54bbdb6c1e1 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -20,6 +20,7 @@ "globby": "^13.1.0", "hash-sum": "^2.0.0", "jiti": "^1.12.9", + "knitwork": "^0.1.0", "lodash.template": "^4.5.0", "mlly": "^0.4.0", "pathe": "^0.2.0", diff --git a/packages/kit/src/components.ts b/packages/kit/src/components.ts index bc872f86a30..44092da047b 100644 --- a/packages/kit/src/components.ts +++ b/packages/kit/src/components.ts @@ -1,6 +1,6 @@ import { pascalCase, kebabCase } from 'scule' import type { ComponentsDir, Component } from '@nuxt/schema' -import { genDynamicImport } from 'mlly' +import { genDynamicImport } from 'knitwork' import { useNuxt } from './context' import { assertNuxtCompatibility } from './compatibility' diff --git a/packages/kit/src/internal/template.ts b/packages/kit/src/internal/template.ts index 6eabf35de87..863aa87f630 100644 --- a/packages/kit/src/internal/template.ts +++ b/packages/kit/src/internal/template.ts @@ -3,7 +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 'mlly' +import { genDynamicImport, genImport } from 'knitwork' import type { NuxtTemplate } from '@nuxt/schema' diff --git a/packages/nitro/package.json b/packages/nitro/package.json index 53a0e405b3d..e4d79b0170c 100644 --- a/packages/nitro/package.json +++ b/packages/nitro/package.json @@ -48,6 +48,7 @@ "http-proxy": "^1.18.1", "is-primitive": "^3.0.1", "jiti": "^1.12.9", + "knitwork": "^0.1.0", "listhen": "^0.2.6", "mime": "^3.0.0", "mlly": "^0.4.0", diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 38e55260bb5..d7e5cd0fc20 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -2,7 +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 'mlly' +import { genDynamicImport } from 'knitwork' import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' import { hl, prettyPath, serializeTemplate, writeFile, isDirectory, replaceAll } from './utils' diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 55f266ae535..60e12413434 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -17,7 +17,8 @@ import * as unenv from 'unenv' import devalue from '@nuxt/devalue' import type { Preset } from 'unenv' -import { sanitizeFilePath, genImport } from 'mlly' +import { sanitizeFilePath } from 'mlly' +import { genImport } from 'knitwork' import { NitroContext } from '../context' import { resolvePath } from '../utils' import { pkgDir } from '../dirs' diff --git a/packages/nitro/src/rollup/plugins/assets.ts b/packages/nitro/src/rollup/plugins/assets.ts index b516b6aebcd..1c5d9bfaeee 100644 --- a/packages/nitro/src/rollup/plugins/assets.ts +++ b/packages/nitro/src/rollup/plugins/assets.ts @@ -4,7 +4,7 @@ import createEtag from 'etag' import mime from 'mime' import { resolve } from 'pathe' import { globby } from 'globby' -import { genDynamicImport, genObjectFromRawEntries } from 'mlly' +import { genDynamicImport, genObjectFromRawEntries } from 'knitwork' import virtual from './virtual' export interface AssetOptions { diff --git a/packages/nitro/src/rollup/plugins/dynamic-require.ts b/packages/nitro/src/rollup/plugins/dynamic-require.ts index da65f0cbbd7..54bcbc9fee3 100644 --- a/packages/nitro/src/rollup/plugins/dynamic-require.ts +++ b/packages/nitro/src/rollup/plugins/dynamic-require.ts @@ -2,7 +2,7 @@ import { pathToFileURL } from 'url' import { resolve } from 'pathe' import { globby } from 'globby' import type { Plugin } from 'rollup' -import { genDynamicImport, genObjectFromRawEntries, genImport } from 'mlly' +import { genDynamicImport, genObjectFromRawEntries, genImport } from 'knitwork' import { serializeImportName } from '../../utils' const PLUGIN_NAME = 'dynamic-require' diff --git a/packages/nitro/src/rollup/plugins/middleware.ts b/packages/nitro/src/rollup/plugins/middleware.ts index e15920a46ae..493ce598e8f 100644 --- a/packages/nitro/src/rollup/plugins/middleware.ts +++ b/packages/nitro/src/rollup/plugins/middleware.ts @@ -3,7 +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 'mlly' +import { genArrayFromRaw, genDynamicImport, genImport } from 'knitwork' import type { ServerMiddleware } from '../../server/middleware' import virtual from './virtual' diff --git a/packages/nitro/src/rollup/plugins/storage.ts b/packages/nitro/src/rollup/plugins/storage.ts index d508c60ad2b..1cd5fcf557c 100644 --- a/packages/nitro/src/rollup/plugins/storage.ts +++ b/packages/nitro/src/rollup/plugins/storage.ts @@ -1,5 +1,5 @@ import virtual from '@rollup/plugin-virtual' -import { genImport } from 'mlly' +import { genImport } from 'knitwork' import { serializeImportName } from '../../utils' export interface StorageOptions { diff --git a/packages/nuxt3/build.config.ts b/packages/nuxt3/build.config.ts index 4ee95be9092..df88ce24fb5 100644 --- a/packages/nuxt3/build.config.ts +++ b/packages/nuxt3/build.config.ts @@ -21,6 +21,7 @@ export default defineBuildConfig({ externals: [ '@vue/reactivity', '@vue/shared', + 'knitwork', '@vueuse/head', 'vue-meta' ] diff --git a/packages/nuxt3/package.json b/packages/nuxt3/package.json index fcf474af3ab..a8a665779b0 100644 --- a/packages/nuxt3/package.json +++ b/packages/nuxt3/package.json @@ -38,6 +38,7 @@ "hash-sum": "^2.0.0", "hookable": "^5.1.1", "ignore": "^5.2.0", + "knitwork": "^0.1.0", "mlly": "^0.4.0", "murmurhash-es": "^0.1.1", "nuxi": "3.0.0", diff --git a/packages/nuxt3/src/auto-imports/module.ts b/packages/nuxt3/src/auto-imports/module.ts index b3d650603a6..6be862f76c0 100644 --- a/packages/nuxt3/src/auto-imports/module.ts +++ b/packages/nuxt3/src/auto-imports/module.ts @@ -1,7 +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 'mlly' +import { genDynamicImport } from 'knitwork' import { TransformPlugin } from './transform' import { Nuxt3AutoImports } from './imports' import { scanForComposables } from './composables' diff --git a/packages/nuxt3/src/auto-imports/utils.ts b/packages/nuxt3/src/auto-imports/utils.ts index c73da253a35..31f33acaa1b 100644 --- a/packages/nuxt3/src/auto-imports/utils.ts +++ b/packages/nuxt3/src/auto-imports/utils.ts @@ -1,5 +1,5 @@ import type { AutoImport } from '@nuxt/schema' -import { genExport, genImport } from 'mlly' +import { genExport, genImport } from 'knitwork' export function toImportModuleMap (autoImports: AutoImport[], isCJS = false) { const aliasKeyword = isCJS ? ' : ' : ' as ' diff --git a/packages/nuxt3/src/components/loader.ts b/packages/nuxt3/src/components/loader.ts index 573c8223f2a..e8162ca277b 100644 --- a/packages/nuxt3/src/components/loader.ts +++ b/packages/nuxt3/src/components/loader.ts @@ -1,7 +1,7 @@ import { createUnplugin } from 'unplugin' import { parseQuery, parseURL } from 'ufo' import { Component } from '@nuxt/schema' -import { genImport } from 'mlly' +import { genImport } from 'knitwork' interface LoaderOptions { getComponents(): Component[] diff --git a/packages/nuxt3/src/components/templates.ts b/packages/nuxt3/src/components/templates.ts index 52a4bc98786..2b9137d2c0a 100644 --- a/packages/nuxt3/src/components/templates.ts +++ b/packages/nuxt3/src/components/templates.ts @@ -1,7 +1,7 @@ import { relative } from 'pathe' import type { Component } from '@nuxt/schema' -import { genDynamicImport, genObjectFromRawEntries } from 'mlly' +import { genDynamicImport, genObjectFromRawEntries } from 'knitwork' export type ComponentsTemplateOptions = { buildDir?: string diff --git a/packages/nuxt3/src/core/templates.ts b/packages/nuxt3/src/core/templates.ts index b21b7ff8951..80da827af06 100644 --- a/packages/nuxt3/src/core/templates.ts +++ b/packages/nuxt3/src/core/templates.ts @@ -1,6 +1,6 @@ import { templateUtils } from '@nuxt/kit' import type { Nuxt, NuxtApp } from '@nuxt/schema' -import { genArrayFromRaw, genDynamicImport, genExport, genImport } from 'mlly' +import { genArrayFromRaw, genDynamicImport, genExport, genImport } from 'knitwork' import { relative } from 'pathe' diff --git a/packages/nuxt3/src/pages/module.ts b/packages/nuxt3/src/pages/module.ts index 0b8bd99ec77..96eb45d3dd2 100644 --- a/packages/nuxt3/src/pages/module.ts +++ b/packages/nuxt3/src/pages/module.ts @@ -1,7 +1,7 @@ import { existsSync } from 'fs' import { defineNuxtModule, addTemplate, addPlugin, templateUtils, addVitePlugin, addWebpackPlugin } from '@nuxt/kit' import { resolve } from 'pathe' -import { genDynamicImport, genObjectFromRawEntries } from 'mlly' +import { genDynamicImport, genObjectFromRawEntries } from 'knitwork' import { distDir } from '../dirs' import { resolveLayouts, resolvePagesRoutes, normalizeRoutes, resolveMiddleware, getImportName } from './utils' import { TransformMacroPlugin, TransformMacroPluginOptions } from './macros' diff --git a/packages/vite/package.json b/packages/vite/package.json index dce2c990bd0..bf708a563c1 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -28,6 +28,7 @@ "esbuild": "^0.14.13", "externality": "^0.1.6", "fs-extra": "^10.0.0", + "knitwork": "^0.1.0", "magic-string": "^0.25.7", "mlly": "^0.4.0", "p-debounce": "^4.0.0", diff --git a/packages/vite/src/dev-bundler.ts b/packages/vite/src/dev-bundler.ts index f0b01b7ed17..dfb37480a1a 100644 --- a/packages/vite/src/dev-bundler.ts +++ b/packages/vite/src/dev-bundler.ts @@ -4,7 +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 'mlly' +import { genDynamicImport, genObjectFromRawEntries } from 'knitwork' import { hashId, uniq } from './utils' export interface TransformChunk { diff --git a/yarn.lock b/yarn.lock index 4b6c454f5a9..ed3ae2c5b2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2871,6 +2871,7 @@ __metadata: globby: ^13.1.0 hash-sum: ^2.0.0 jiti: ^1.12.9 + knitwork: ^0.1.0 lodash.template: ^4.5.0 mlly: ^0.4.0 pathe: ^0.2.0 @@ -2965,6 +2966,7 @@ __metadata: http-proxy: ^1.18.1 is-primitive: ^3.0.1 jiti: ^1.12.9 + knitwork: ^0.1.0 listhen: ^0.2.6 mime: ^3.0.0 mlly: ^0.4.0 @@ -3234,6 +3236,7 @@ __metadata: esbuild: ^0.14.13 externality: ^0.1.6 fs-extra: ^10.0.0 + knitwork: ^0.1.0 magic-string: ^0.25.7 mlly: ^0.4.0 p-debounce: ^4.0.0 @@ -13784,6 +13787,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" @@ -15841,6 +15851,7 @@ __metadata: hash-sum: ^2.0.0 hookable: ^5.1.1 ignore: ^5.2.0 + knitwork: ^0.1.0 mlly: ^0.4.0 murmurhash-es: ^0.1.1 nuxi: 3.0.0 From 5a03f35d717ebe0330df5a2111d46acb46acf53f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 26 Jan 2022 13:38:39 +0000 Subject: [PATCH 08/12] fix: apply to more areas of framework --- packages/nitro/src/presets/browser.ts | 7 +++--- packages/nitro/src/rollup/plugins/storage.ts | 4 ++-- packages/nuxt3/src/pages/module.ts | 24 ++++++++++---------- packages/nuxt3/src/pages/utils.ts | 8 +++---- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index 5cc7a5d840f..5d9c8bf527c 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -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 = `` @@ -27,7 +28,7 @@ if ('serviceWorker' in navigator) {