-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathvite.config.ts
160 lines (137 loc) · 5.01 KB
/
vite.config.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import { defineConfig } from "vite";
import path from "node:path";
import fs, { readFileSync, writeFileSync } from "node:fs";
import archiver from "archiver";
import type { Manifest } from "webextension-polyfill";
const TARGET: "chrome" | "firefox" = process.env.TARGET as "chrome" | "firefox";
const FF_ADDON_ID = process.env.FF_ADDON_ID as string;
if (!["chrome", "firefox"].includes(TARGET)) {
throw new Error(`Invalid TARGET: ${TARGET}. Specify TARGET=chrome or TARGET=firefox`);
}
if (TARGET === "firefox" && !FF_ADDON_ID) {
throw new Error(`FF_ADDON_ID is required for firefox builds`);
}
const isFirefox = TARGET === "firefox";
// https://vitejs.dev/config/
export default defineConfig({
build: {
rollupOptions: {
input: {
index: "index.html",
background: "src/background.ts",
},
output: {
entryFileNames: "[name].js",
},
},
minify: false,
emptyOutDir: false,
},
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
optimizeDeps: {
exclude: ["@sqlite.org/sqlite-wasm", "@vlcn.io/crsqlite-wasm"],
},
plugins: [
svelte({
preprocess: vitePreprocess(),
}),
// Watch additional files
{
name: "watch-additional-files",
buildStart() {
for (const pathName of ["src/manifest.json", `src/manifest-${TARGET}.json`]) {
if (fs.existsSync(path.resolve(__dirname, pathName))) {
this.addWatchFile(path.resolve(__dirname, pathName));
}
}
},
},
// Copy assets to dist
{
name: "copy-plugin",
apply: "build",
enforce: "post",
generateBundle() {
const sourceDir = path.resolve(__dirname, "src/assets");
const destinationDir = path.resolve(__dirname, "dist/assets");
fs.mkdirSync(destinationDir, { recursive: true });
const files = fs.readdirSync(sourceDir);
for (const filepath of files) {
const sourcePath = path.join(sourceDir, filepath);
const destinationPath = path.join(destinationDir, filepath);
fs.copyFileSync(sourcePath, destinationPath);
console.log(`[copy-plugin] ${sourcePath} -> ${destinationPath}`);
}
try {
const manifest = JSON.parse(
readFileSync(path.resolve(__dirname, "src/manifest.json"), "utf8")
);
// Mutate the manifest object
delete manifest["$schema"]; // Schema is just provided for autocomplete but chrome doesn't like it
// Handle FF special cases
if (isFirefox) {
// Case 1: FF doesn't support service_worker, it prefers a background.scripts array
manifest.background.scripts = [manifest.background.service_worker];
delete manifest.background.service_worker;
// Case 2: FF requires an id. See: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
manifest.browser_specific_settings = {
gecko: {
id: `{${FF_ADDON_ID}}`, // FF loves those braces
strict_min_version: "109.0", // When they added (partial) MV3 support. No lover for MV3 here, but since it's a hard req for chrome we use it for FF too
},
};
}
writeFileSync(
path.join(__dirname, "dist/manifest.json"),
JSON.stringify(manifest, null, 2)
);
console.log(`[copy-plugin] copied manifest`);
} catch (err) {
console.error("Could not build manifest", err);
}
},
},
// Create zip dist file for upload to chrome web store
{
name: "zip-plugin",
apply: "build",
enforce: "post",
writeBundle() {
const output = fs.createWriteStream(__dirname + `/fttf-${TARGET}.zip`);
const archive = archiver("zip", {
zlib: { level: 9 },
});
// listen for all archive data to be processed
output.on("close", function () {
console.log(archive.pointer() + " total bytes");
console.log("Archiver has been finalized and the output file descriptor has closed.");
});
// good practice to catch warnings (ie stat failures and other non-blocking errors)
archive.on("warning", function (err) {
if (err.code === "ENOENT") {
console.warn("no file", err);
} else {
// throw error
throw err;
}
});
// good practice to catch this error explicitly
archive.on("error", function (err) {
throw err;
});
// pipe archive data to the file
archive.pipe(output);
// append files from a directory
archive.directory(__dirname + "/dist/", false);
// finalize the archive (ie we are done appending files but streams have to finish yet)
archive.finalize();
},
},
],
});