vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
72 lines (71 loc) • 3.18 kB
JavaScript
export { pluginReplaceConstants };
import MagicString from 'magic-string';
import { assert, assertPosixPath } from '../utils.js';
import { normalizeId } from '../shared/normalizeId.js';
import { isViteServerBuild_safe } from '../shared/isViteServerBuild.js';
import { applyRegExpWithMagicString } from '../shared/applyRegExWithMagicString.js';
function pluginReplaceConstants() {
let config;
return {
name: 'vike:pluginReplaceConstants',
enforce: 'post',
apply: 'build',
configResolved(config_) {
config = config_;
},
transform(code, id, options) {
id = normalizeId(id);
assertPosixPath(id);
if (id.includes('/node_modules/'))
return;
assertPosixPath(config.root);
if (!id.startsWith(config.root))
return;
if (!code.includes('import.meta.env.'))
return;
const isBuild = config.command === 'build';
assert(isBuild);
// Used by vike.dev
// https://github.com/vikejs/vike/blob/08a1ff55c80ddca64ca6d4417fefd45fefeb4ffb/docs/vite.config.ts#L12
// @ts-expect-error
if (config._skipVikeReplaceConstants?.(id))
return;
const magicString = new MagicString(code);
const constantsMap = [];
constantsMap.push({
constants: ['pageContext.isClientSide', 'globalContext.isClientSide', 'pageContext.globalContext.isClientSide'],
replacement: !isViteServerBuild_safe(config, options),
});
constantsMap.forEach(({ constants, replacement }) => {
if (!constants.some((c) => code.includes(c)))
return;
const regExp = getConstantRegExp(constants);
applyRegExpWithMagicString(magicString, regExp, replacement);
});
if (!magicString.hasChanged())
return null;
return {
code: magicString.toString(),
map: magicString.generateMap({ hires: true, source: id }),
};
},
};
}
// Copied & adapted from:
// https://github.com/rollup/plugins/blob/e1a5ef99f1578eb38a8c87563cb9651db228f3bd/packages/replace/src/index.js#L57-L67
function getConstantRegExp(constants) {
const keys = Object.values(constants).sort(longest).map(escape);
// const delimiters = ['\\b', '\\b(?!\\.)']
const delimiters = ['(?<!\\.)\\b', '\\b(?!\\.)']; // Improved version, to avoid replacing `globalContext.pageContext.isClientSide` with `globalContext.false`
const preventAssignment = false; // Let's try without it first, let's see if a user complains
const lookbehind = preventAssignment ? '(?<!\\b(?:const|let|var)\\s*)' : '';
const lookahead = preventAssignment ? '(?!\\s*=[^=])' : '';
const pattern = new RegExp(`${lookbehind}${delimiters[0]}(${keys.join('|')})${delimiters[1]}${lookahead}`, 'g');
return pattern;
}
function escape(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function longest(a, b) {
return b.length - a.length;
}