vite-plugin-prerelease
Version:
vite plugin prerelease
130 lines (125 loc) • 3.8 kB
JavaScript
import fsp from 'node:fs/promises';
import path from 'node:path';
import { build, normalizePath } from 'vite';
import * as cheerio from 'cheerio';
// src/node/buildtime-env/index.ts
function transformHtml(originHtml, prereleaseHtml) {
if (!originHtml || !prereleaseHtml) return;
const $ = cheerio.load(originHtml);
const pre$ = cheerio.load(prereleaseHtml);
const generateDynamicTags = ($2) => {
return [
...$2("script").filter((_, el) => Boolean($2(el).attr("src"))),
...$2("link").filter((_, el) => Boolean($2(el).attr("href"))),
// legacy
...$2("script").filter((_, el) => Boolean($2(el).data("src") && $2(el).attr("id") === "vite-legacy-entry")),
// log-time
...$2("script").filter((_, el) => typeof $2(el).data("log-time") !== "undefined")
];
};
const dynamicTags = generateDynamicTags($);
const dynamicTagsOfPre = generateDynamicTags(pre$);
dynamicTags.forEach((el) => {
$(el).remove();
});
const createInsertScript = (dynamicTags2) => {
return dynamicTags2.map((e) => {
return {
attribs: e.attribs,
tag: e.tagName,
children: $(e).html()
};
});
};
const code = (
/* js */
`
!(function() {
function insertTags(tags) {
tags.forEach(({ attribs, tag, children }) => {
const element = document.createElement(tag)
for (const key in attribs) {
element.setAttribute(key, attribs[key])
}
if(children) {
element.innerHTML = children
}
document.head.appendChild(element)
})
}
const isPrerelease = window.Cookies.get('prerelease') === 'true'
const attrs = isPrerelease ? ${JSON.stringify(createInsertScript(dynamicTagsOfPre))} : ${JSON.stringify(createInsertScript(dynamicTags))}
insertTags(attrs)
})()
`
);
$("body").after(`<script>${code}</script>`);
return $.html().replace(/^\s*$(?:\r\n?|\n)/gm, "");
}
// src/node/buildtime-env/index.ts
function buildtimeEnv(options) {
const { prereleaseEnv, __debug } = options || {};
const definePlugin = {
name: "vite:plugin-prerelease-define",
apply(_, env) {
return env.mode === prereleaseEnv && env.command === "build" || __debug;
},
config() {
return {
define: {
"import.meta.env.PRERELEASE": "true"
}
};
}
};
let config;
let originalHtml;
let prereleaseHtml;
const buildPlugin = {
name: "vite:plugin-prerelease-build",
enforce: "post",
apply(_, env) {
if (env.mode === prereleaseEnv) return false;
return env.command === "build";
},
configResolved(resolvedConfig) {
config = resolvedConfig;
},
transformIndexHtml: {
order: "post",
handler(html) {
originalHtml = html;
}
},
async closeBundle() {
config.logger.info("Building prerelease...");
await build({
configFile: config.configFile,
mode: prereleaseEnv,
base: normalizePath(`${config.base}/prerelease`),
build: {
outDir: normalizePath(`${config.build.outDir}/prerelease`)
},
plugins: [
{
name: "vite:plugin-prerelease-html",
enforce: "post",
transformIndexHtml: {
order: "post",
handler(html) {
prereleaseHtml = html;
}
}
}
]
});
const transformedHtml = transformHtml(originalHtml, prereleaseHtml);
if (transformedHtml) {
await fsp.writeFile(path.join(config.build.outDir, "index.html"), transformedHtml);
}
config.logger.info("Prerelease build complete");
}
};
return [definePlugin, buildPlugin];
}
export { buildtimeEnv };