vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
110 lines (109 loc) • 4.88 kB
JavaScript
import '../../assertEnvVite.js';
export { pluginProdBuildEntry };
export { set_macro_ASSETS_MANIFEST };
import { serverProductionEntryPlugin } from '@brillout/vite-plugin-server-entry/plugin';
import { virtualFileIdGlobalEntryServer } from '../../../../shared-server-node/virtualFileId.js';
import { PROJECT_VERSION } from '../../../../utils/PROJECT_VERSION.js';
import { assert } from '../../../../utils/assert.js';
import { requireResolveDistFile } from '../../../../utils/requireResolve.js';
import fs from 'node:fs/promises';
import path from 'node:path';
import { isUsingClientRouter } from '../pluginExtractExportNames.js';
import { assertBuildInfo } from '../../../../server/runtime/globalContext.js';
import { getOutDirs } from '../../shared/getOutDirs.js';
import { getViteConfigRuntime } from '../../shared/getViteConfigRuntime.js';
const ASSETS_MANIFEST = '__VITE_ASSETS_MANIFEST__';
function pluginProdBuildEntry() {
let config;
return [
{
name: 'vike:build:pluginProdBuildEntry',
apply: 'build',
enforce: 'post',
configResolved: {
async handler(config_) {
config = config_;
},
},
},
...serverProductionEntryPlugin({
getServerProductionEntry: () => {
return getServerProductionEntryCode(config);
},
libraryName: 'Vike',
}),
];
}
function getServerProductionEntryCode(config) {
const importPath = getImportPath(config);
const buildInfo = {
versionAtBuildTime: PROJECT_VERSION,
usesClientRouter: isUsingClientRouter(), // TO-DO/next-major-release: remove
viteConfigRuntime: getViteConfigRuntime(config),
};
assertBuildInfo(buildInfo);
// After the old design is removed, let's maybe simplify and move everything into a single virtual module
const importerCode = [
` import { setGlobalContext_prodBuildEntry } from '${importPath}';`,
` import * as virtualFileExportsGlobalEntry from '${virtualFileIdGlobalEntryServer}';`,
` {`,
// Because of a Rollup bug, we have to assign ASSETS_MANIFEST to a variable before passing it to setGlobalContext_prodBuildEntry()
// - This workaround doesn't work: https://github.com/vikejs/vike/commit/d5f3a4f7aae5a8bc44192e6cbb2bcb9007be188d
` const assetsManifest = ${ASSETS_MANIFEST};`,
` const buildInfo = ${JSON.stringify(buildInfo, null, 2)};`,
' setGlobalContext_prodBuildEntry({',
` virtualFileExportsGlobalEntry,`,
` assetsManifest,`,
` buildInfo,`,
' });',
` }`,
'',
].join('\n');
return importerCode;
}
// Set the value of the ASSETS_MANIFEST constant inside dist/server/entry.js (or dist/server/index.js)
async function set_macro_ASSETS_MANIFEST(assetsJsonFilePath, bundle, outDir) {
assert(outDir);
const chunkPath = find_ASSETS_MANIFEST(bundle);
// Some server builds don't contain __VITE_ASSETS_MANIFEST__ such as dist/rsc/ from vike-react-rsc
if (!chunkPath) {
const noop = true; // no operation
return noop;
}
assert(assetsJsonFilePath);
const chunkFilePath = path.join(outDir, chunkPath);
const [assetsJsonString, chunkFileContent] = await Promise.all([
await fs.readFile(assetsJsonFilePath, 'utf8'),
await fs.readFile(chunkFilePath, 'utf8'),
]);
const serverEntryFileContentPatched = chunkFileContent.replace(ASSETS_MANIFEST, assetsJsonString);
assert(serverEntryFileContentPatched !== chunkFileContent);
await fs.writeFile(chunkFilePath, serverEntryFileContentPatched);
const noop = false;
return noop;
}
function find_ASSETS_MANIFEST(bundle) {
let chunkPath;
for (const filePath in bundle) {
const chunk = bundle[filePath];
if ('code' in chunk && chunk.code.includes(ASSETS_MANIFEST)) {
assert(!chunkPath);
chunkPath = filePath;
}
}
return chunkPath;
}
function getImportPath(config) {
// We resolve filePathAbsolute even if we don't use it: we use require.resolve() as an assertion that the relative path is correct
const filePathAbsolute = requireResolveDistFile('dist/server/__internal/index.js');
if (
// Let's implement a new config if a user needs the import to be a relative path instead of 'vike/__internal' (AFAIK a relative path is needed only if a framework has npm package 'vike' as direct dependency instead of a peer dependency and if the user of that framework uses pnpm)
true) {
return 'vike/__internal';
}
else {
const { outDirServer } = getOutDirs(config, undefined);
const filePathRelative = path.posix.relative(outDirServer, filePathAbsolute);
return filePathRelative;
}
}