@dafengzhen/vite-plugin-mp
Version:
vite-plugin-mp 使用 Vite 编译微信小程序
388 lines (387 loc) • 12.1 kB
JavaScript
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
};