UNPKG

vike

Version:

The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.

195 lines (191 loc) 8.75 kB
import '../../assertEnvVite.js'; export { generateVirtualFileGlobalEntryWithOldDesign }; import { assert, assertWarning } from '../../../../utils/assert.js'; import { isVersionMatch } from '../../../../utils/assertVersion.js'; import { debugGlob } from '../../../../utils/debugGlob.js'; import { scriptFileExtensionPattern } from '../../../../utils/isScriptFile.js'; import { assertPosixPath } from '../../../../utils/path.js'; import { parseVirtualFileId } from '../../../../shared-server-node/virtualFileId.js'; import { version as viteVersion } from 'vite'; import { fileTypes } from '../../../../shared-server-client/getPageFiles/fileTypes.js'; import path from 'node:path'; import { generateVirtualFileGlobalEntry } from './generateVirtualFileGlobalEntry.js'; import { getVikeConfigInternal, isV1Design as isV1Design_ } from '../../shared/resolveVikeConfigInternal.js'; import { getOutDirs } from '../../shared/getOutDirs.js'; import { isViteServerSide_extraSafe } from '../../shared/isViteServerSide.js'; import { resolveIncludeAssetsImportedByServer } from '../../../../server/runtime/renderPageServer/getPageAssets/retrievePageAssetsProd.js'; import { VIRTUAL_FILE_ID_constantsGlobalThis } from '../pluginReplaceConstantsGlobalThis.js'; async function generateVirtualFileGlobalEntryWithOldDesign(id, options, config, env, isDev) { const idParsed = parseVirtualFileId(id); assert(idParsed && idParsed.type === 'global-entry'); const { isForClientSide, isClientRouting } = idParsed; assert(isForClientSide === !isViteServerSide_extraSafe(config, env, options)); const code = await getCode(config, isForClientSide, isClientRouting, isDev, id); return code; } async function getCode(config, isForClientSide, isClientRouting, isDev, id) { const { command } = config; assert(command === 'serve' || command === 'build'); const isBuild = command === 'build'; assert(isDev === !isBuild); let content = ''; if (!isForClientSide) { content += `import '${VIRTUAL_FILE_ID_constantsGlobalThis}';\n`; } { const globRoots = getGlobRoots(config); debugGlob('Glob roots: ', globRoots); content += await generateGlobImports(globRoots, isBuild, isForClientSide, isClientRouting, isDev, id); } debugGlob(`Glob imports for ${isForClientSide ? 'client' : 'server'}:\n`, content); return content; } function determineInjection({ fileType, isForClientSide, isClientRouting, isPrerendering, isBuild, }) { if (!isForClientSide) { return { includeImport: fileType === '.page.server' || fileType === '.page' || fileType === '.page.route', includeExportNames: isPrerendering && isBuild ? fileType === '.page.client' || fileType === '.page.server' || fileType === '.page' // We extensively use `PageFile['exportNames']` while pre-rendering, in order to avoid loading page files unnecessarily, and therefore reducing memory usage. : fileType === '.page.client', }; } else { const includeImport = fileType === '.page.client' || fileType === '.css' || fileType === '.page'; if (!isClientRouting) { return { includeImport, includeExportNames: false, }; } else { return { includeImport: includeImport || fileType === '.page.route', includeExportNames: fileType === '.page.client' || fileType === '.page.server' || fileType === '.page', }; } } } async function generateGlobImports(globRoots, isBuild, isForClientSide, isClientRouting, isDev, id) { let fileContent = `// Generated by Vike export const pageFilesLazy = {}; export const pageFilesEager = {}; export const pageFilesExportNamesLazy = {}; export const pageFilesExportNamesEager = {}; export const pageFilesList = []; export const neverLoaded = {}; ${await generateVirtualFileGlobalEntry(isForClientSide, isDev, id, isClientRouting)} `; // We still use import.meta.glob() when using th V1 design in order to not break the V1 design deprecation warning const isV1Design = isV1Design_(); const vikeConfig = await getVikeConfigInternal(); // Old design => no + files => only to enable pre-rendering is setting `vike({prerender})` in vite.config.js const isPrerendering = !!vikeConfig.config.prerender; fileTypes .filter((fileType) => fileType !== '.css') .forEach((fileType) => { const { includeImport, includeExportNames } = determineInjection({ fileType, isForClientSide, isClientRouting, isPrerendering, isBuild, }); if (includeImport) { fileContent += getGlobs(globRoots, isBuild, fileType, null, isV1Design); } if (includeExportNames) { fileContent += getGlobs(globRoots, isBuild, fileType, 'extractExportNames', isV1Design); } }); const includeAssetsImportedByServer = resolveIncludeAssetsImportedByServer(vikeConfig.config); if (includeAssetsImportedByServer && isForClientSide) { fileContent += getGlobs(globRoots, isBuild, '.page.server', 'extractAssets', isV1Design); } return fileContent; } function getGlobs(globRoots, isBuild, fileType, query, isV1Design) { const isEager = isBuild && (query === 'extractExportNames' || fileType === '.page.route'); let pageFilesVar; if (query === 'extractExportNames') { if (!isEager) { pageFilesVar = 'pageFilesExportNamesLazy'; } else { pageFilesVar = 'pageFilesExportNamesEager'; } } else if (query === 'extractAssets') { assert(!isEager); pageFilesVar = 'neverLoaded'; } else if (!query) { if (!isEager) { pageFilesVar = 'pageFilesLazy'; } else { // Used for `.page.route.js` files pageFilesVar = 'pageFilesEager'; } } else { assert(false); } const varNameSuffix = (fileType === '.page' && 'Isomorph') || (fileType === '.page.client' && 'Client') || (fileType === '.page.server' && 'Server') || (fileType === '.page.route' && 'Route'); assert(varNameSuffix); const varName = `${pageFilesVar}${varNameSuffix}`; const varNameLocals = []; return [ ...globRoots.map((globRoot, i) => { const varNameLocal = `${varName}${i + 1}`; varNameLocals.push(varNameLocal); const globIncludePath = `'${getGlobPath(globRoot.includeDir, fileType)}'`; const globExcludePath = globRoot.excludeDir ? `'!${getGlobPath(globRoot.excludeDir, fileType)}'` : null; const globOptions = { eager: isEager }; if (query) { const isNewViteInterface = isVersionMatch(viteVersion, ['5.1.0']); if (isNewViteInterface && // When used for the old design, the new syntax breaks Vike's CI (surprinsigly so). I couldn't reproduce locally (I didn't dig much). isV1Design) { globOptions.query = `?${query}`; } else { globOptions.as = query; const msg = [ "Update to the new V1 design to get rid of Vite's warning:", 'The glob option "as" has been deprecated in favour of "query".', 'See https://vike.dev/migration/v1-design for how to migrate.', ].join(' '); assertWarning(!isNewViteInterface, msg, { onlyOnce: true }); } } const globPaths = globExcludePath ? `[${globIncludePath}, ${globExcludePath}]` : `[${globIncludePath}]`; const globLine = `const ${varNameLocal} = import.meta.glob(${globPaths}, ${JSON.stringify(globOptions)});`; return globLine; }), `const ${varName} = {${varNameLocals.map((varNameLocal) => `...${varNameLocal}`).join(',')}};`, `${pageFilesVar}['${fileType}'] = ${varName};`, '', ].join('\n'); } function getGlobRoots(config) { const globRoots = [ { includeDir: '/', excludeDir: path.posix.relative(config.root, getOutDirs(config, undefined).outDirRoot), }, ]; return globRoots; } function getGlobPath(globRootDir, fileType) { assertPosixPath(globRootDir); let globPath = [...globRootDir.split('/'), '**', `*${fileType}.${scriptFileExtensionPattern}`] .filter(Boolean) .join('/'); if (!globPath.startsWith('/')) { globPath = '/' + globPath; } return globPath; }