vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
286 lines (283 loc) • 10.4 kB
JavaScript
/**
* vite-plugin-react-server
* Copyright (c) Nico Brinkkemper
* MIT License
*/
import { DEFAULT_CONFIG } from './defaults.js';
import { join } from 'node:path';
import { pluginRoot } from '../root.js';
import { InlineCssCollector } from '../css-collector-inline.js';
import { CssCollector } from '../css-collector.js';
const resolveAutoDiscoverMatcher = (options, fallback) => {
if (!options) {
if (typeof fallback === "function") {
return fallback;
} else {
return (path) => fallback.test(path);
}
}
if (typeof options === "string") {
const matcher = new RegExp(options);
return (path) => matcher.test(path);
} else if (typeof options === "function") {
return options;
} else {
return (path) => options.test(path);
}
};
const addJS = (path) => {
if (path.endsWith(".js")) return path;
if (path.endsWith("/.")) return path.slice(0, -2) + ".js";
if (path.endsWith(".")) return path + "js";
return path + ".js";
};
const handleSearchQuery = (path) => {
const searchQuery = path.split("?")[1];
if (!searchQuery) return path;
const folder = path.split("/").slice(0, -1).join("/");
const filename = path.split("/").pop();
return `${folder}/${filename}?${searchQuery}`;
};
const applyPattern = (path, _pattern, _fallback) => {
return path;
};
const resolveOptions = (options, isClient) => {
const projectRoot = options.projectRoot ?? process.cwd();
const {
pageExportName = DEFAULT_CONFIG.PAGE_EXPORT_NAME,
propsExportName = DEFAULT_CONFIG.PROPS_EXPORT_NAME
} = options;
const pages = typeof options.build?.pages === "function" ? options.build.pages : Array.isArray(options.build?.pages) ? options.build.pages : DEFAULT_CONFIG.BUILD.pages;
let client = options.build?.client ?? DEFAULT_CONFIG.BUILD.client;
let server = options.build?.server ?? DEFAULT_CONFIG.BUILD.server;
const api = options.build?.api ?? DEFAULT_CONFIG.BUILD.api;
const staticBuild = options.build?.static ?? DEFAULT_CONFIG.BUILD.static;
const outDir = options.build?.outDir ?? DEFAULT_CONFIG.BUILD.outDir;
const assetsDir = options.build?.assetsDir ?? `${DEFAULT_CONFIG.CLIENT_ASSETS_DIR}`;
const ensureModuleBase = (n) => {
if (!n) return "";
return n.startsWith(moduleBase + "/") ? n.slice(moduleBase.length + 1) : n;
};
const hasWrongRoot = !projectRoot.startsWith("/");
if (hasWrongRoot) {
console.warn("projectRoot is not a full path", projectRoot);
}
const wrongRoot = !hasWrongRoot ? projectRoot.slice(1) : projectRoot;
const ensureNoRoot = (n) => {
if (!n) return "";
if (n.startsWith(wrongRoot)) {
return n.slice(wrongRoot.length + 1);
}
return n.startsWith(projectRoot + "/") ? n.slice(projectRoot.length + 1) : n;
};
const testModulePattern = resolveAutoDiscoverMatcher(
options.autoDiscover?.modulePattern,
DEFAULT_CONFIG.AUTO_DISCOVER.modulePattern
);
const testJson = resolveAutoDiscoverMatcher(
options.autoDiscover?.jsonPattern,
DEFAULT_CONFIG.AUTO_DISCOVER.jsonPattern
);
const testCss = resolveAutoDiscoverMatcher(
options.autoDiscover?.cssPattern,
DEFAULT_CONFIG.AUTO_DISCOVER.cssPattern
);
const testHtml = resolveAutoDiscoverMatcher(
options.autoDiscover?.htmlPattern,
DEFAULT_CONFIG.AUTO_DISCOVER.htmlPattern
);
const testClientComponents = resolveAutoDiscoverMatcher(
options.autoDiscover?.clientComponents,
DEFAULT_CONFIG.AUTO_DISCOVER.clientComponents
);
const testServerFunctions = resolveAutoDiscoverMatcher(
options.autoDiscover?.serverFunctions,
DEFAULT_CONFIG.AUTO_DISCOVER.serverFunctions
);
const testPropsPattern = resolveAutoDiscoverMatcher(
options.autoDiscover?.propsPattern,
DEFAULT_CONFIG.AUTO_DISCOVER.propsPattern
);
const testPagePattern = resolveAutoDiscoverMatcher(
options.autoDiscover?.pagePattern,
DEFAULT_CONFIG.AUTO_DISCOVER.pagePattern
);
const testCssModule = resolveAutoDiscoverMatcher(
options.autoDiscover?.cssModulePattern,
DEFAULT_CONFIG.AUTO_DISCOVER.cssModulePattern
);
const testVendor = resolveAutoDiscoverMatcher(
options.autoDiscover?.vendorPattern,
DEFAULT_CONFIG.AUTO_DISCOVER.vendorPattern
);
const preserveModulesRoot = options.build?.preserveModulesRoot ?? DEFAULT_CONFIG.BUILD.preserveModulesRoot;
const hashOption = typeof options.build?.hash === "string" ? options.build.hash : DEFAULT_CONFIG.BUILD.hash;
const hashString = hashOption === "" ? "" : `-[${hashOption}]`;
const hash = (n) => {
if (!n) return "";
if (hashString === "" || !isClient && !n.endsWith(".css") && !n.endsWith(".json")) {
return n;
}
const extensionIndex = n.lastIndexOf(".");
if (extensionIndex !== -1) {
const extension = n.slice(extensionIndex);
const filename = n.slice(0, extensionIndex);
return filename + hashString + extension;
} else {
return n + hashString;
}
};
const getOutputPath = (n) => {
if (!n) return "";
let path = handleSearchQuery(n);
path = path.startsWith(moduleBase + "/") ? path.slice(moduleBase.length + 1) : path;
if (testVendor(path)) {
return path;
}
if (testCssModule(path)) {
return applyPattern(
path,
options.autoDiscover?.cssModulePattern);
}
if (testCss(path)) {
return applyPattern(path, options.autoDiscover?.cssPattern);
}
if (testClientComponents(path)) {
return applyPattern(
path,
options.autoDiscover?.clientComponents);
}
if (testHtml(path)) {
return applyPattern(path, options.autoDiscover?.htmlPattern);
}
if (testJson(path)) {
return applyPattern(path, options.autoDiscover?.jsonPattern);
}
if (testPropsPattern(path)) {
return applyPattern(
path,
options.autoDiscover?.propsPattern,
options.propsExportName?.toLowerCase() ?? DEFAULT_CONFIG.PROPS_EXPORT_NAME.toLowerCase()
);
}
if (testPagePattern(path)) {
return applyPattern(
path,
options.autoDiscover?.pagePattern,
options.pageExportName?.toLowerCase() ?? DEFAULT_CONFIG.PAGE_EXPORT_NAME.toLowerCase()
);
}
if (testServerFunctions(path)) {
return applyPattern(
path,
options.autoDiscover?.serverFunctions);
}
if (testModulePattern(path)) {
return path;
}
return path;
};
const entryFile = (n) => {
if (testVendor(n.name)) {
const search = n.facadeModuleId?.split("?")[1];
if (search) {
return hash(`${n.name}.${search}.js`);
} else {
return hash(`${n.name}.js`);
}
}
return hash(addJS(getOutputPath(ensureModuleBase(ensureNoRoot(n.name)))));
};
const chunkFile = (n) => {
return hash(addJS(getOutputPath(ensureModuleBase(ensureNoRoot("_" + n.name)))));
};
const assetFile = (n) => {
return hash(getOutputPath(ensureModuleBase(ensureNoRoot(n.names[0]))));
};
const build = typeof options.build === "object" && options.build !== null ? {
pages,
client,
server,
static: staticBuild,
outDir,
assetsDir,
api,
hash: hashOption,
preserveModulesRoot,
entryFile: typeof options.build?.entryFile === "function" ? options.build.entryFile : entryFile,
chunkFile: typeof options.build?.chunkFile === "function" ? options.build.chunkFile : chunkFile,
assetFile: typeof options.build?.assetFile === "function" ? options.build.assetFile : assetFile
} : {
pages,
client,
server,
static: staticBuild,
outDir,
assetsDir,
api,
hash: hashOption,
preserveModulesRoot,
entryFile,
chunkFile,
assetFile
};
const moduleBase = typeof options.moduleBase === "string" ? options.moduleBase : DEFAULT_CONFIG.MODULE_BASE;
const moduleBasePath = typeof options.moduleBasePath === "string" ? options.moduleBasePath : DEFAULT_CONFIG.MODULE_BASE_PATH;
const moduleBaseURL = typeof options.moduleBaseURL === "string" ? options.moduleBaseURL : DEFAULT_CONFIG.MODULE_BASE_URL;
const rscWorkerPath = typeof options.rscWorkerPath === "string" ? join(projectRoot, options.rscWorkerPath) : join(pluginRoot, DEFAULT_CONFIG.RSC_WORKER_PATH);
const htmlWorkerPath = typeof options.htmlWorkerPath === "string" ? join(projectRoot, options.htmlWorkerPath) : join(pluginRoot, DEFAULT_CONFIG.HTML_WORKER_PATH);
const loaderPath = typeof options.loaderPath === "string" ? join(projectRoot, options.loaderPath) : join(pluginRoot, DEFAULT_CONFIG.LOADER_PATH);
const autoDiscover = {
modulePattern: testModulePattern,
cssPattern: testCss,
jsonPattern: testJson,
clientComponents: testClientComponents,
serverFunctions: testServerFunctions,
propsPattern: testPropsPattern,
pagePattern: testPagePattern,
cssModulePattern: testCssModule,
vendorPattern: testVendor
};
const inlineCss = options.inlineCss;
const InlineOrLinkCssCollector = options.CssCollector ?? inlineCss ? InlineCssCollector : CssCollector;
try {
return {
type: "success",
userOptions: {
projectRoot,
moduleBase,
moduleBasePath,
moduleBaseURL,
build,
Page: options.Page ?? DEFAULT_CONFIG.PAGE,
props: options.props ?? DEFAULT_CONFIG.PROPS,
Html: options.Html ?? DEFAULT_CONFIG.HTML,
CssCollector: InlineOrLinkCssCollector,
pageExportName,
propsExportName,
collectCss: options.collectCss ?? DEFAULT_CONFIG.COLLECT_CSS,
collectAssets: options.collectAssets ?? DEFAULT_CONFIG.COLLECT_ASSETS,
inlineCss: options.inlineCss ?? DEFAULT_CONFIG.INLINE_CSS,
htmlWorkerPath,
rscWorkerPath,
loaderPath,
clientEntry: options.clientEntry ?? DEFAULT_CONFIG.CLIENT_ENTRY,
serverEntry: options.serverEntry ?? DEFAULT_CONFIG.SERVER_ENTRY,
moduleBaseExceptions: options.moduleBaseExceptions ?? [],
autoDiscover,
pipableStreamOptions: options.pipableStreamOptions ?? {
bootstrapModules: [
options.clientEntry ?? DEFAULT_CONFIG.CLIENT_ENTRY
]
}
}
};
} catch (error) {
return {
type: "error",
error: error instanceof Error ? error : new Error("Failed to resolve options")
};
}
};
export { resolveOptions };
//# sourceMappingURL=resolveOptions.js.map