UNPKG

vite-plugin-multi-page-css

Version:

143 lines (140 loc) 3.94 kB
import path from 'path'; import fs from 'fs'; import url from 'url'; import fg from 'fast-glob'; import ejs from 'ejs'; function flattenSet(inputSet) { const flatSet = /* @__PURE__ */ new Set(); function recursiveFlatten(set) { set.forEach((item) => { if (item instanceof Set) { recursiveFlatten(item); } else { flatSet.add(item); } }); } recursiveFlatten(inputSet); return flatSet; } function genImportCss(item, container) { const result = /* @__PURE__ */ new Set(); function processImports(imports) { for (const element of imports) { const i = container[element]; if (i.viteMetadata?.importedCss) { result.add(i.viteMetadata.importedCss); } if (i.imports?.length > 0) { processImports(i.imports); } } } if (item.imports?.length > 0) { processImports(item.imports); } return result; } function multiPagePlugin(options = {}) { const { splitCss = false, template = "index.html", pageDir = path.join("src", "pages") //TODO 后续有时间再搞吧 //pages=[], } = options; const dirNames = fg.sync("*/", { cwd: pageDir, onlyDirectories: true }); const htmlNames = dirNames.map((dirName) => `${dirName}.html`); const templatePath = path.join(pageDir, template); const indexHtml = fs.readFileSync(templatePath, "utf8"); const templateUrl = templatePath.split(path.sep).join("/"); let viteConfig = null; return { name: "vite:multi-page", configResolved(resolvedConfig) { viteConfig = resolvedConfig; }, config() { const input = Object.fromEntries( dirNames.map((dirName) => [dirName, `${dirName}.html`]) ); return { build: { rollupOptions: { input } } }; }, resolveId(id) { if (htmlNames.indexOf(id) > -1) { return id; } }, load(id) { if (htmlNames.indexOf(id) > -1) { return indexHtml; } }, configureServer(server) { server.middlewares.use((req, res, next) => { const reqUrl = req.url; const baseName = url.parse(reqUrl).pathname; if (baseName?.endsWith(".html")) { req.url = `/${templateUrl}`; } next(); }); }, transformIndexHtml: { enforce: "pre", async transform(html, ctx) { const name = ctx.originalUrl || ctx.filename; if (!name) return html; const pathname = url.parse(name).pathname; if (!pathname) return html; const pageName = path.basename(pathname, ".html"); const renderedHtml = ejs.render(html, { ctx: viteConfig }); const _html = renderedHtml.replace( /<\/body>/, `<script type="module" src="./${pageDir}/${pageName}/index.tsx"><\/script> </body>` ); return { html: _html, tags: [] }; } }, generateBundle(_options, bundle) { if (!splitCss) { return; } for (const fileName in bundle) { const fileInfo = bundle[fileName]; if (fileName.endsWith(".js") && fileName.indexOf("/") == -1) { const cssAssets = genImportCss(fileInfo, bundle); cssAssets.add(fileInfo.viteMetadata?.importedCss); let cssSource = ""; const importCssSet = flattenSet(cssAssets); if (importCssSet.size > 0) { for (const item of importCssSet) { cssSource += `/** ${item} */ ${bundle[item].source}`; } const fileWithoutExtension = path.parse(fileName).name; const cssFileName = `${fileWithoutExtension}.css`; bundle[cssFileName] = { type: "asset", source: cssSource, fileName: cssFileName }; } } } } }; } export { multiPagePlugin as default };