vite-plugin-react18-pages
Version:
<p> <a href="https://www.npmjs.com/package/vite-plugin-react-pages" target="_blank" rel="noopener"><img src="https://img.shields.io/npm/v/vite-plugin-react-pages.svg" alt="npm package" /></a> </p>
187 lines • 7.97 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ssrBuild = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const vite_1 = require("vite");
const constants_1 = require("../constants");
async function ssrBuild(viteConfig, ssrConfig, argv) {
var _a, _b, _c;
// ssr build should not use hash router
// if (viteOptions?.define?.['__HASH_ROUTER__'])
// viteOptions!.define!['__HASH_ROUTER__'] = false
const root = viteConfig.root;
let outDir = (_b = (_a = viteConfig.build) === null || _a === void 0 ? void 0 : _a.outDir) !== null && _b !== void 0 ? _b : "dist";
outDir = path.resolve(root, outDir);
await fs.emptyDir(outDir);
const ssrOutDir = path.join(outDir, "ssr-tmp");
const clientOutDir = path.join(outDir, "client-tmp");
console.log("\n\npreparing vite pages ssr bundle...");
const ssrOutput = await (0, vite_1.build)({
root,
configFile: viteConfig.configFile,
build: {
ssr: true,
cssCodeSplit: false,
rollupOptions: {
input: path.join(constants_1.CLIENT_PATH, "ssr", "serverRender.js"),
preserveEntrySignatures: "allow-extension",
output: {
format: "cjs",
exports: "named",
entryFileNames: "[name].js",
},
},
outDir: ssrOutDir,
minify: false,
},
// @ts-ignore
ssr: {
external: ["react", "react-router-dom", "react-dom", "react-dom/server"],
noExternal: [
// TODO: remove this
"vite-pages-theme-basic",
"vite-plugin-react18-pages",
"vite-plugin-react18-pages/client",
],
},
});
console.log("\n\nrendering html...");
const { renderToString, ssrData } = require(path.join(ssrOutDir, "serverRender.js"));
const pagePaths = Object.keys(ssrData);
console.log("\n\npreparing vite pages client bundle...");
const _clientResult = await (0, vite_1.build)({
root,
configFile: viteConfig.configFile,
build: {
cssCodeSplit: false,
rollupOptions: {
input: path.join(constants_1.CLIENT_PATH, "ssr", "clientRender.js"),
preserveEntrySignatures: "allow-extension",
},
assetsDir: "assets",
outDir: clientOutDir,
},
});
let clientResult;
if (Array.isArray(_clientResult)) {
if (_clientResult.length !== 1)
throw new Error(`expect viteBuild to have only one BuildResult`);
clientResult = _clientResult[0];
}
else {
clientResult = _clientResult;
}
const entryChunk = (() => {
const _entryChunks = clientResult.output.filter((chunkOrAsset) => {
return chunkOrAsset.type === "chunk" && chunkOrAsset.isEntry;
});
if (_entryChunks.length !== 1) {
throw new Error(`Expect one entryChunk. Got ${_entryChunks.length}.`);
}
return _entryChunks[0];
})();
const cssChunks = clientResult.output.filter((chunk) => {
return chunk.type === "asset" && chunk.fileName.endsWith(".css");
});
const basePath = (_c = viteConfig.base) !== null && _c !== void 0 ? _c : "/";
const htmlCode = await fs.readFile(path.join(root, "index.html"), "utf-8");
const RootElementInjectPoint = '<div id="root"></div>';
if (!htmlCode.includes(RootElementInjectPoint)) {
throw new Error(`Your index.html should contain the RootElementInjectPoint: "${RootElementInjectPoint}" (it must appear exactly as-is)`);
}
const EntryModuleInjectPoint = '<script type="module" src="/@pages-infra/main.js"></script>';
if (!htmlCode.includes(EntryModuleInjectPoint)) {
throw new Error(`Your index.html should contain EntryModuleInjectPoint: "${EntryModuleInjectPoint}" (it must appear exactly as-is)`);
}
const CSSInjectPoint = "</head>";
if (!htmlCode.includes(CSSInjectPoint)) {
throw new Error(`Your index.html should contain CSSInjectPoint: "${CSSInjectPoint}" (it must appear exactly as-is)`);
}
await Promise.all(pagePaths.map(async (pagePath) => {
// currently not support pages with path params
// .e.g /users/:userId
if (pagePath.match(/\/:\w/))
return;
const html = renderHTML(pagePath);
// TODO: injectPreload
// preload data module for this page
// html = injectPreload(html, "path/to/page/data")
const writePath = path.join(clientOutDir, pagePath.replace(/^\//, ""), "index.html");
await fs.ensureDir(path.dirname(writePath));
await fs.writeFile(writePath, html);
if (pagePath !== "/") {
// should write to both /pagePath/index.html and /pagePath.html
const writePath2 = path.join(clientOutDir, pagePath.replace(/^\//, "") + ".html");
await fs.ensureDir(path.dirname(writePath2));
await fs.writeFile(writePath2, html);
}
}));
const html404Path = path.join(clientOutDir, "404.html");
// pass in a pagePath that won't match any defined page
// so the render result will be 404 page
const html404 = renderHTML("/internal-404-page");
await fs.writeFile(html404Path, html404);
// move 404 page to `/` if `/` doesn't exists
if (!pagePaths.includes("/")) {
await fs.copy(html404Path, path.join(clientOutDir, "index.html"));
}
await fs.copy(clientOutDir, outDir);
await fs.remove(clientOutDir);
await fs.remove(ssrOutDir);
console.log("vite pages ssr build finished successfully.");
return;
function renderHTML(pagePath) {
const ssrContent = renderToString(pagePath);
const ssrInfo = {
routePath: pagePath,
};
let html = htmlCode.replace(RootElementInjectPoint,
// let client know the current ssr page
`<script>window._vitePagesSSR=${JSON.stringify(ssrInfo)};</script>
<div id="root">${ssrContent}</div>`);
const cssInject = cssChunks
.map((cssChunk) => {
return `<link rel="stylesheet" href="${basePath}${cssChunk.fileName}" />`;
})
.join("\n");
html = html.replace(CSSInjectPoint, `${cssInject}
${CSSInjectPoint}`);
html = html.replace(EntryModuleInjectPoint, `<script type="module" src="${basePath}${entryChunk.fileName}"></script>`);
return html;
}
}
exports.ssrBuild = ssrBuild;
const injectPreload = (html, filePath) => {
const tag = `<link rel="modulepreload" href="${filePath}" />`;
if (/<\/head>/.test(html)) {
return html.replace(/<\/head>/, `${tag}\n</head>`);
}
else {
return tag + "\n" + html;
}
};
//# sourceMappingURL=index.js.map