UNPKG

@dafengzhen/vite-plugin-mp

Version:

vite-plugin-mp 使用 Vite 编译微信小程序

388 lines (387 loc) 12.1 kB
import w from "fs"; import c from "path"; import { glob as B, globSync as $ } from "tinyglobby"; import { mergeConfig as v, normalizePath as D } from "vite"; import j from "crypto"; const O = "vite-plugin-mp-copy"; function _(e = {}) { const o = e.rootDir ?? "miniprogram"; let i = e.outputDir ?? "miniprogram"; const r = e.debug ?? !1, t = e.targets ?? []; if (!Array.isArray(t)) throw new Error('The "targets" option must be an array of objects with "src" and "dest" properties.'); return { apply: "build", configResolved(n) { i = c.join(n.build?.outDir ?? "dist", i); }, async generateBundle() { if (t.length === 0) return; const n = c.resolve(o), s = c.resolve(i), a = (m) => { r && this.info(m); }; a(`OutputDir: ${i}`); for (const m of t) { const { dest: f, src: u } = m; (!u || !f) && this.error('Each target must have both "src" and "dest" properties.'); try { const l = await B(u, { cwd: n }); a(`Found ${l.length} files for pattern "${u}"`); const p = u.split("/")[0]; a(`SrcBase: ${p}`); let d, h; for (const g of l) { const P = c.join(n, g); !p || !g.startsWith(p) ? d = g : d = c.relative(p, g), h = c.join(s, f, d), a(`Copying: ${g}`), a(`SrcPath: ${P}`), a(`DestPath: ${h}`), await w.promises.mkdir(c.dirname(h), { recursive: !0 }), await w.promises.copyFile(P, h); } } catch (l) { this.error( `Failed to copy files from "${u}" to "${f}": ${l instanceof Error ? l.message : String(l)}` ); } } }, name: O }; } const y = "vite-plugin-mp-entry"; function E() { return { config(e) { const o = { build: { rollupOptions: { input: { [y]: y }, onwarn: (i, r) => { if (i.names?.includes(y)) return; const t = e.build?.rollupOptions?.onwarn; typeof t == "function" ? t?.(i, r) : t && r(i); } } } }; return v(e, o); }, generateBundle(e, o) { for (const [i, r] of Object.entries(o)) if (r.name === y) { delete o[i]; break; } }, load(e) { return e === y ? "" : null; }, name: y, resolveId(e) { return e === y ? e : null; } }; } const A = "vite-plugin-mp-json"; function C(e = {}) { const o = e.rootDir ?? "miniprogram", i = e.outputDir ?? "miniprogram", r = e.jsonInclude, t = e.jsonIgnore, n = []; return { buildStart() { const s = [`${o}/**/*.json`, "project.config.json"]; typeof r == "string" ? s.push(r) : Array.isArray(r) && s.push(...r), n.push( ...$(s, { ignore: t }) ); }, async generateBundle() { try { await Promise.all( n.map(async (s) => { try { const a = await w.promises.readFile(s, "utf-8"), m = JSON.parse(a), f = JSON.stringify(m), u = s.startsWith(o), l = u ? c.relative(o, s) : s, p = u ? D(c.join(i, l)) : l; this.emitFile({ fileName: p, source: f, type: "asset" }); } catch (a) { this.warn(`Failed to process ${s}: ${a instanceof Error ? a.message : a}`); } }) ); } catch (s) { this.error(`Failed to find JSON files: ${s instanceof Error ? s.message : s}`); } }, name: A }; } const I = "vite-plugin-mp-tovw", k = (e, o = 750) => e.replace(/:\s*([^;{}]+)rpx/g, (i) => i.replace(/(\d+(\.\d+)?)rpx/g, (r, t) => `${(parseFloat(t) / o * 100).toFixed(3)}vw`)); function R(e = {}) { const o = e.rpxToVw ?? !1, i = e.designWidth ?? 750; return { name: I, transform(r, t) { return o && t.endsWith(".css") && r.includes("rpx") ? { code: k(r, i), map: null } : null; } }; } const T = "vite-plugin-mp-wxjs", b = "wxjs-"; function X(e = {}) { const o = e.rootDir ?? "miniprogram", i = e.outputDir ?? "miniprogram", r = e.isTsProject ?? !0 ? "ts" : "js"; return { config(t) { const s = $(`${o}/**/*.${r}`).reduce( (l, p) => { const d = c.relative(o, p).replace(r === "ts" ? /\.ts$/ : /\.js$/, ""), h = j.createHash("md5").update(p).digest("hex").slice(0, 8), g = `${b}${d}-${h}`; return l[g] = c.resolve(p), l; }, {} ), a = t?.build?.rollupOptions?.output, m = t?.build?.assetsDir ?? `${i}/assets`, f = t?.build?.target ?? ["es2015", "chrome87", "edge88", "firefox78", "safari14"], u = { build: { assetsDir: m, rollupOptions: { input: s, output: { entryFileNames: (l) => { const p = l.name; if (p.startsWith(b)) { const h = p.substring(b.length).replace(/-\w{8}$/, ".js"); return D(c.join(i, h)); } const d = a?.entryFileNames; return typeof d == "function" ? d(l) : typeof d == "string" ? d : "[name].js"; }, format: a?.format ?? "cjs" } }, target: f } }; return v(t, u); }, name: T, transform(t, n) { if (!n.endsWith(`.${r}`)) return null; const s = c.extname(n), a = c.basename(n, s), m = c.dirname(n), f = `${a}.wxml`, u = `${a}.wxss`, l = `${a}.json`, p = []; return w.existsSync(c.join(m, f)) && p.push(`import './${f}?raw';`), w.existsSync(c.join(m, u)) && p.push(`import './${u}?raw';`), w.existsSync(c.join(m, l)) && p.push(`import './${l}?raw';`), p.length === 0 ? null : { code: `${p.join(` `)} ${t}`, id: n }; } }; } const F = "vite-plugin-mp-wxml", S = "wxml-", J = (e) => Object.prototype.toString.call(e) === "[object Uint8Array]", U = (e) => J(e) ? { text: new TextDecoder("utf-8").decode(e), wasBinary: !0 } : { text: e, wasBinary: !1 }, H = async (e, o, i) => { const { text: r, wasBinary: t } = U(e); let n = M(r, o); if (typeof i == "function") { const s = i(t ? new TextEncoder().encode(n) : n); s instanceof Promise ? n = await s : n = s; } return n; }, M = (e, o) => { const i = /<script\b[^>]*>([\s\S]*?)<\/script>/gi; return e.replaceAll(i, (r) => o.some((t) => r.includes(t)) ? "" : r); }; function L(e = {}) { const o = e.rootDir ?? "miniprogram", i = e.outputDir ?? "miniprogram", r = e.compress, t = []; return { config(n) { const m = { build: { rollupOptions: { input: $(`${o}/**/*.wxml`).reduce( (f, u) => { const l = c.relative(o, u).replace(/\.wxml$/, ""), p = j.createHash("md5").update(u).digest("hex").slice(0, 8), d = `${S}${l}-${p}`; return t.push(`${d}.js`), f[d] = c.resolve(u), f; }, {} ), plugins: [ { async generateBundle(f, u) { for (const [l, p] of Object.entries(u)) if (p.type === "asset" && l.endsWith(".html")) { const d = c.relative(o, l).replace(/\.html$/, ".wxml"), h = D(c.join(i, d)); delete u[l]; const g = await H(p.source, t, r); u[d] = { ...p, fileName: h, source: g }; } else p.type === "chunk" && l.endsWith(".js") && l.startsWith(S) && delete u[l]; }, name: "vite-plugin-html-rename" } ] } } }; return v(n, m); }, enforce: "pre", async load(n) { if (!n.endsWith(".html")) return null; const s = n.replace(/\.html$/, ".wxml"); return { code: await w.promises.readFile(s, "utf-8"), map: null, meta: { customData: { now: Date.now(), sourceFile: s, type: "wxml" } } }; }, name: F, resolveId(n, s) { if (!n.endsWith(".wxml")) return null; const a = s ? c.dirname(s) : process.cwd(), m = c.resolve(a, n); return { external: !1, id: m.replace(/\.wxml$/, ".html"), meta: { customData: { fileName: m, now: Date.now(), type: "wxml" } }, moduleSideEffects: !0, resolvedBy: F }; } }; } const V = (e = 8) => { const o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", i = j.randomBytes(e), r = new Array(e); for (let t = 0; t < e; t++) r[t] = o[i[t] % o.length]; return r.join(""); }, W = "vite-plugin-mp-wxss", x = "wxss-"; function z(e = {}) { const o = e.rootDir ?? "miniprogram", i = e.outputDir ?? "miniprogram"; return { config(r) { const s = { build: { rollupOptions: { input: $(`${o}/**/*.wxss`).reduce( (a, m) => { const f = c.relative(o, m).replace(/\.wxss$/, ""), u = j.createHash("md5").update(m).digest("hex").slice(0, 8), l = `${x}${f}-${u}`; return a[l] = c.resolve(m), a; }, {} ), output: { assetFileNames: (a) => { const m = a.names?.[0]; if (m?.startsWith(x)) { const u = m.substring(x.length).replace(/-\w{8}.css$/, ".wxss"); return D(c.join(i, u)); } const f = r?.build?.rollupOptions?.output?.assetFileNames; return typeof f == "function" ? f(a) : typeof f == "string" ? f : "assets/[name]-[hash][extname]"; } } } } }; return v(r, s); }, enforce: "pre", generateBundle(r, t) { for (const [n, s] of Object.entries(t)) if (s.type === "chunk" && n.endsWith(".js") && n.startsWith(x)) delete t[n]; else if (s.type === "asset" && n.endsWith(".wxss") && typeof s.source == "string") { const a = s.source.replace(/\.__wxss_[A-Za-z0-9]{8}__\s*\{\s*color:\s*#fff;?\s*}/gs, ""); t[n] = { ...s, source: a }; } }, async load(r) { if (!r.endsWith(".css")) return null; const t = r.replace(/\.css$/, ".wxss"); return { code: await w.promises.readFile(t, "utf-8"), map: null, meta: { customData: { now: Date.now(), sourceFile: t, type: "wxss" } } }; }, name: W, resolveId(r, t) { if (!r.endsWith(".wxss")) return null; const n = t ? c.dirname(t) : process.cwd(), s = c.resolve(n, r); return { external: !1, id: s.replace(/\.wxss$/, ".css"), meta: { customData: { fileName: s, now: Date.now(), type: "wxss" } }, moduleSideEffects: !0, resolvedBy: W }; }, transform(r, t) { return t.endsWith(".css") && r ? { code: r + `.__wxss_${V()}__ {color:#fff}` } : null; } }; } const N = "vite-plugin-mp", G = `${N}-root-check`; function K(e = {}) { const o = e.rootDir ?? "miniprogram"; return [ Z(o), E(), L(e), z(e), X(e), C(e), _(e), R(e) ]; } function Z(e) { return { async buildStart() { try { const o = c.resolve(e); (await w.promises.readdir(o)).length === 0 && this.warn(`rootDir "${e}" is an empty directory.`); } catch (o) { o.code === "ENOENT" ? this.warn(`rootDir "${e}" does not exist.`) : this.warn(`Failed to check rootDir "${e}": ${String(o)}`); } }, name: G }; } K.resolvedBy = N; export { K as default };