vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
149 lines (148 loc) • 7.29 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.pluginFileEnv = pluginFileEnv;
const utils_js_1 = require("../utils.js");
const pluginExtractAssets_js_1 = require("./pluginExtractAssets.js");
const pluginExtractExportNames_js_1 = require("./pluginExtractExportNames.js");
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
const getFilePath_js_1 = require("../shared/getFilePath.js");
const parseEsModule_js_1 = require("../shared/parseEsModule.js");
const normalizeId_js_1 = require("../shared/normalizeId.js");
const resolveVikeConfigInternal_js_1 = require("../shared/resolveVikeConfigInternal.js");
function pluginFileEnv() {
let config;
let viteDevServer;
return {
name: 'vike:pluginFileEnv',
load(id, options) {
// In build, we use generateBundle() instead of the load() hook. Using load() works for dynamic imports in dev thanks to Vite's lazy transpiling, but it doesn't work in build because Rollup transpiles any dynamically imported module even if it's never actually imported.
if (!viteDevServer)
return;
if (!(0, resolveVikeConfigInternal_js_1.isV1Design)())
return;
if (skip(id))
return;
// For `.vue` files: https://github.com/vikejs/vike/issues/1912#issuecomment-2394981475
if (id.endsWith('?direct'))
id = id.slice(0, -1 * '?direct'.length);
const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
(0, utils_js_1.assert)(moduleInfo);
const importers = Array.from(moduleInfo.importers)
.map((m) => m.id)
.filter((id) => id !== null);
assertFileEnv(id, !!options?.ssr, importers,
// In dev, we only show a warning because we don't want to disrupt when the user plays with settings such as [ssr](https://vike.dev/ssr).
true);
},
// In production, we have to use transform() to replace modules with a runtime error because generateBundle() doesn't work for dynamic imports. In production, dynamic imports can only be verified at runtime.
async transform(code, id, options) {
id = (0, normalizeId_js_1.normalizeId)(id);
// In dev, only using load() is enough as it also works for dynamic imports (see sibling comment).
if (viteDevServer)
return;
if (skip(id))
return;
const isServerSide = !!options?.ssr;
if (!isWrongEnv(id, isServerSide))
return;
const { importers } = this.getModuleInfo(id);
// Throwing a verbose error doesn't waste client-side KBs as dynamic imports are code split.
const errMsg = getErrorMessage(id, isServerSide, importers, false, true);
// We have to inject empty exports to avoid Rollup complaining about missing exports, see https://gist.github.com/brillout/5ea45776e65bd65100a52ecd7bfda3ff
const { exportNames } = await (0, parseEsModule_js_1.getExportNames)(code);
return (0, utils_js_1.rollupSourceMapRemove)([
`throw new Error(${JSON.stringify(errMsg)});`,
...exportNames.map((name) => name === 'default' ? 'export default undefined;' : `export const ${name} = undefined;`),
].join('\n'));
},
generateBundle() {
Array.from(this.getModuleIds())
.filter((id) => !skip(id))
.forEach((moduleId) => {
const mod = this.getModuleInfo(moduleId);
const { importers } = mod;
if (importers.length === 0) {
// Dynamic imports can only be verified at runtime
/* This assertion can fail: https://github.com/vikejs/vike/issues/2227
assert(dynamicImporters.length > 0)
*/
return;
}
assertFileEnv(moduleId, !!config.build.ssr, importers, false);
});
},
configResolved(config_) {
config = config_;
},
configureServer(viteDevServer_) {
viteDevServer = viteDevServer_;
},
};
function assertFileEnv(moduleId, isServerSide, importers, onlyWarn) {
if (!isWrongEnv(moduleId, isServerSide))
return;
const errMsg = getErrorMessage(moduleId, isServerSide, importers, onlyWarn, false);
if (onlyWarn) {
(0, utils_js_1.assertWarning)(false, errMsg, { onlyOnce: true });
}
else {
(0, utils_js_1.assertUsage)(false, errMsg);
}
}
function getErrorMessage(moduleId, isServerSide, importers, onlyWarn, noColor) {
const modulePath = getModulePath(moduleId);
const envActual = isServerSide ? 'server' : 'client';
const envExpect = isServerSide ? 'client' : 'server';
let errMsg;
let modulePathPretty = (0, getFilePath_js_1.getModuleFilePathAbsolute)(modulePath, config);
if (!noColor) {
const suffix = getSuffix(envExpect);
modulePathPretty = modulePathPretty.replaceAll(suffix, picocolors_1.default.bold(suffix));
}
errMsg = `${(0, utils_js_1.capitalizeFirstLetter)(envExpect)}-only file ${modulePathPretty} (https://vike.dev/file-env) imported on the ${envActual}-side`;
{
const importPaths = importers
.filter((importer) =>
// Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
(0, utils_js_1.isFilePathAbsolute)(importer))
.map((importer) => (0, getFilePath_js_1.getModuleFilePathAbsolute)(importer, config));
if (importPaths.length > 0) {
errMsg += ` by ${(0, utils_js_1.joinEnglish)(importPaths, 'and')}`;
}
}
if (onlyWarn) {
errMsg += ' and, therefore, Vike will prevent building your app for production.';
}
return errMsg;
}
function isWrongEnv(moduleId, isServerSide) {
const modulePath = getModulePath(moduleId);
const suffixWrong = getSuffix(isServerSide ? 'client' : 'server');
return modulePath.includes(suffixWrong);
}
function skip(id) {
// TODO/v1-release: remove
if (pluginExtractAssets_js_1.extractAssetsRE.test(id) || pluginExtractExportNames_js_1.extractExportNamesRE.test(id))
return true;
if (!id.includes(getSuffix('client')) && !id.includes(getSuffix('server')))
return true;
if (getModulePath(id).endsWith('.css'))
return true;
// Apply `.server.js` and `.client.js` only to user files
if (id.includes('/node_modules/'))
return true;
// Only user files
if (!id.startsWith(config.root))
return true;
return false;
}
function getSuffix(env) {
return `.${env}.`;
}
function getModulePath(moduleId) {
return moduleId.split('?')[0];
}
}