@crxjs/vite-plugin 2.0.0-beta.11 → 2.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +44 -8
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { simple } from 'acorn-walk';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
-
import debug$
|
|
3
|
+
import debug$3 from 'debug';
|
|
4
4
|
import v8 from 'v8';
|
|
5
5
|
import { posix } from 'path';
|
|
6
6
|
import { Subject, filter, ReplaySubject, switchMap, of, startWith, map, mergeMap, firstValueFrom, takeUntil, first, toArray, retry, concatWith, Subscription, buffer } from 'rxjs';
|
|
@@ -24,8 +24,10 @@ const pluginOptionsProvider = (options) => {
|
|
|
24
24
|
name: pluginName$1,
|
|
25
25
|
api: {
|
|
26
26
|
crx: {
|
|
27
|
+
// during testing this can be null, we don't provide options through the test config
|
|
27
28
|
options
|
|
28
29
|
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
31
|
}
|
|
30
32
|
};
|
|
31
33
|
};
|
|
@@ -58,7 +60,7 @@ function isCrxPlugin(p) {
|
|
|
58
60
|
|
|
59
61
|
var workerHmrClient = "const ownOrigin = new URL(chrome.runtime.getURL(\"/\")).origin;\nself.addEventListener(\"fetch\", (fetchEvent) => {\n const url = new URL(fetchEvent.request.url);\n if (url.origin === ownOrigin) {\n fetchEvent.respondWith(sendToServer(url));\n }\n});\nasync function sendToServer(url) {\n url.protocol = \"http:\";\n url.host = \"localhost\";\n url.port = __SERVER_PORT__;\n url.searchParams.set(\"t\", Date.now().toString());\n const response = await fetch(url.href.replace(/=$|=(?=&)/g, \"\"));\n return new Response(response.body, {\n headers: {\n \"Content-Type\": response.headers.get(\"Content-Type\") ?? \"text/javascript\"\n }\n });\n}\nconst ports = /* @__PURE__ */ new Set();\nchrome.runtime.onConnect.addListener((port) => {\n if (port.name === \"@crx/client\") {\n ports.add(port);\n port.onDisconnect.addListener((port2) => ports.delete(port2));\n port.onMessage.addListener((message) => {\n });\n port.postMessage({ data: JSON.stringify({ type: \"connected\" }) });\n }\n});\nfunction notifyContentScripts(payload) {\n const data = JSON.stringify(payload);\n for (const port of ports)\n port.postMessage({ data });\n}\nconsole.log(\"[vite] connecting...\");\nconst socketProtocol = __HMR_PROTOCOL__ || (location.protocol === \"https:\" ? \"wss\" : \"ws\");\nconst socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`;\nconst socket = new WebSocket(`${socketProtocol}://${socketHost}`, \"vite-hmr\");\nconst base = __BASE__ || \"/\";\nsocket.addEventListener(\"message\", async ({ data }) => {\n handleSocketMessage(JSON.parse(data));\n});\nfunction isCrxHmrPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nfunction handleSocketMessage(payload) {\n if (isCrxHmrPayload(payload)) {\n handleCrxHmrPayload(payload);\n } else if (payload.type === \"connected\") {\n console.log(`[vite] connected.`);\n const interval = setInterval(() => socket.send(\"ping\"), __HMR_TIMEOUT__);\n socket.addEventListener(\"close\", () => clearInterval(interval));\n }\n}\nfunction handleCrxHmrPayload(payload) {\n notifyContentScripts(payload);\n switch (payload.event) {\n case \"crx:runtime-reload\":\n console.log(\"[crx] runtime reload\");\n chrome.runtime.reload();\n break;\n }\n}\nasync function waitForSuccessfulPing(ms = 1e3) {\n while (true) {\n try {\n await fetch(`${base}__vite_ping`);\n break;\n } catch (e) {\n await new Promise((resolve) => setTimeout(resolve, ms));\n }\n }\n}\nsocket.addEventListener(\"close\", async ({ wasClean }) => {\n if (wasClean)\n return;\n console.log(`[vite] server connection lost. polling for restart...`);\n await waitForSuccessfulPing();\n handleCrxHmrPayload({\n type: \"custom\",\n event: \"crx:runtime-reload\"\n });\n});\n";
|
|
60
62
|
|
|
61
|
-
const _debug = (id) => debug$
|
|
63
|
+
const _debug = (id) => debug$3("crx").extend(id);
|
|
62
64
|
const structuredClone = (obj) => {
|
|
63
65
|
return v8.deserialize(v8.serialize(obj));
|
|
64
66
|
};
|
|
@@ -204,7 +206,7 @@ function formatFileData(script) {
|
|
|
204
206
|
return script;
|
|
205
207
|
}
|
|
206
208
|
function getFileName({ type, id }) {
|
|
207
|
-
let fileName = id.replace(/t=\d+&/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
209
|
+
let fileName = id.replace(/t=\d+&/, "").replace(/\?t=\d+$/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
208
210
|
if (fileName.includes("node_modules/")) {
|
|
209
211
|
fileName = `vendor/${fileName.split("node_modules/").pop().replace(/\//g, "-")}`;
|
|
210
212
|
} else if (fileName.startsWith("@")) {
|
|
@@ -292,6 +294,7 @@ const pluginBackground = () => {
|
|
|
292
294
|
},
|
|
293
295
|
{
|
|
294
296
|
name: "crx:background-loader-file",
|
|
297
|
+
// this should happen after other plugins; the loader file is an implementation detail
|
|
295
298
|
enforce: "post",
|
|
296
299
|
configResolved(_config) {
|
|
297
300
|
config = _config;
|
|
@@ -318,6 +321,7 @@ const pluginBackground = () => {
|
|
|
318
321
|
}
|
|
319
322
|
const refId = this.emitFile({
|
|
320
323
|
type: "asset",
|
|
324
|
+
// fileName b/c service worker must be at root of crx
|
|
321
325
|
fileName: getFileName({ type: "loader", id: "service-worker" }),
|
|
322
326
|
source: loader
|
|
323
327
|
});
|
|
@@ -426,6 +430,7 @@ function prepAsset(fileName, { id, source }) {
|
|
|
426
430
|
}
|
|
427
431
|
function prepScript(fileName, script) {
|
|
428
432
|
return ($) => $.pipe(
|
|
433
|
+
// get script contents from dev server
|
|
429
434
|
mergeMap(async ({ server }) => {
|
|
430
435
|
const target = getOutputPath(server, fileName);
|
|
431
436
|
const viteUrl = getViteUrl(script);
|
|
@@ -435,7 +440,9 @@ function prepScript(fileName, script) {
|
|
|
435
440
|
const { code, deps = [], dynamicDeps = [] } = transformResult;
|
|
436
441
|
return { target, code, deps: [...deps, ...dynamicDeps].flat(), server };
|
|
437
442
|
}),
|
|
443
|
+
// retry in case of dependency rebundle
|
|
438
444
|
retry({ count: 10, delay: 100 }),
|
|
445
|
+
// patch content scripts
|
|
439
446
|
mergeMap(async ({ target, server, ...rest }) => {
|
|
440
447
|
const plugins = server.config.plugins;
|
|
441
448
|
let { code, deps } = rest;
|
|
@@ -451,10 +458,14 @@ function prepScript(fileName, script) {
|
|
|
451
458
|
const [imports] = lexer.parse(code, fileName);
|
|
452
459
|
const depSet = new Set(deps);
|
|
453
460
|
const magic = new MagicString(code);
|
|
461
|
+
const now = Date.now();
|
|
454
462
|
for (const i of imports)
|
|
455
463
|
if (i.n) {
|
|
456
464
|
depSet.add(i.n);
|
|
457
|
-
|
|
465
|
+
let fileName2 = getFileName({ type: "module", id: i.n });
|
|
466
|
+
if (!fileName2.startsWith("vendor")) {
|
|
467
|
+
fileName2 = `${fileName2}?t=${now}`;
|
|
468
|
+
}
|
|
458
469
|
const fullImport = code.substring(i.s, i.e);
|
|
459
470
|
magic.overwrite(i.s, i.e, fullImport.replace(i.n, `/${fileName2}`));
|
|
460
471
|
}
|
|
@@ -466,7 +477,7 @@ async function allFilesReady() {
|
|
|
466
477
|
await firstValueFrom(allFilesReady$);
|
|
467
478
|
}
|
|
468
479
|
|
|
469
|
-
const { outputFile } = fsx;
|
|
480
|
+
const { outputFile, remove } = fsx;
|
|
470
481
|
_debug("file-writer");
|
|
471
482
|
async function start({
|
|
472
483
|
server
|
|
@@ -487,6 +498,8 @@ async function start({
|
|
|
487
498
|
dir: outDir,
|
|
488
499
|
format: "es"
|
|
489
500
|
};
|
|
501
|
+
if (server.config.build.emptyOutDir)
|
|
502
|
+
await remove(server.config.build.outDir);
|
|
490
503
|
fileWriterEvent$.next({ type: "build_start" });
|
|
491
504
|
const build = await rollup(inputOptions);
|
|
492
505
|
await build.write(outputOptions);
|
|
@@ -527,8 +540,11 @@ function update(_id) {
|
|
|
527
540
|
async function write(fileId) {
|
|
528
541
|
const start2 = performance.now();
|
|
529
542
|
const deps = await firstValueFrom(
|
|
543
|
+
// wait for start event
|
|
530
544
|
start$.pipe(
|
|
545
|
+
// prepare either asset or script contents
|
|
531
546
|
prepFileData(fileId),
|
|
547
|
+
// output file and add dependencies to file writer
|
|
532
548
|
mergeMap(async ({ target, source, deps: deps2 }) => {
|
|
533
549
|
const files = deps2.map((id) => {
|
|
534
550
|
const r = [add({ id, type: "module" })];
|
|
@@ -544,6 +560,7 @@ async function write(fileId) {
|
|
|
544
560
|
await outputFile(target, source, { encoding: "utf8" });
|
|
545
561
|
return files;
|
|
546
562
|
}),
|
|
563
|
+
// abort write operation on close event
|
|
547
564
|
takeUntil(close$),
|
|
548
565
|
concatWith(of([]))
|
|
549
566
|
)
|
|
@@ -816,6 +833,12 @@ const pluginDynamicContentScripts = () => {
|
|
|
816
833
|
{
|
|
817
834
|
name: "crx:dynamic-content-scripts-build",
|
|
818
835
|
apply: "build",
|
|
836
|
+
/**
|
|
837
|
+
* Replace dynamic script placeholders during build.
|
|
838
|
+
*
|
|
839
|
+
* Can't use `renderChunk` b/c pre plugin crx:content-scripts uses
|
|
840
|
+
* `generateBundle` to emit loaders. Must come after "enforce: pre".
|
|
841
|
+
*/
|
|
819
842
|
generateBundle(options, bundle) {
|
|
820
843
|
for (const chunk of Object.values(bundle))
|
|
821
844
|
if (chunk.type === "chunk") {
|
|
@@ -982,11 +1005,13 @@ const pluginFileWriterPublic = () => {
|
|
|
982
1005
|
};
|
|
983
1006
|
};
|
|
984
1007
|
|
|
985
|
-
_debug("file-writer").extend("hmr");
|
|
986
|
-
const
|
|
1008
|
+
const debug$2 = _debug("file-writer").extend("hmr");
|
|
1009
|
+
const isCustomPayload = (p) => {
|
|
1010
|
+
return p.type === "custom";
|
|
1011
|
+
};
|
|
987
1012
|
const hmrPayload$ = new Subject();
|
|
988
1013
|
const crxHMRPayload$ = hmrPayload$.pipe(
|
|
989
|
-
filter((p) => !
|
|
1014
|
+
filter((p) => !isCustomPayload(p)),
|
|
990
1015
|
buffer(allFilesReady$),
|
|
991
1016
|
mergeMap((pps) => {
|
|
992
1017
|
let fullReload;
|
|
@@ -1045,6 +1070,7 @@ const crxHMRPayload$ = hmrPayload$.pipe(
|
|
|
1045
1070
|
}
|
|
1046
1071
|
}),
|
|
1047
1072
|
map((data) => {
|
|
1073
|
+
debug$2(`hmr payload`, data);
|
|
1048
1074
|
return {
|
|
1049
1075
|
type: "custom",
|
|
1050
1076
|
event: "crx:content-script-payload",
|
|
@@ -1084,6 +1110,7 @@ const pluginHMR = () => {
|
|
|
1084
1110
|
name: "crx:hmr",
|
|
1085
1111
|
apply: "serve",
|
|
1086
1112
|
enforce: "pre",
|
|
1113
|
+
// server hmr host should be localhost
|
|
1087
1114
|
async config({ server = {}, ...config2 }) {
|
|
1088
1115
|
if (server.hmr === false)
|
|
1089
1116
|
return;
|
|
@@ -1093,6 +1120,7 @@ const pluginHMR = () => {
|
|
|
1093
1120
|
server.hmr.host = "localhost";
|
|
1094
1121
|
return { server, ...config2 };
|
|
1095
1122
|
},
|
|
1123
|
+
// server should ignore outdir
|
|
1096
1124
|
configResolved(_config) {
|
|
1097
1125
|
config = _config;
|
|
1098
1126
|
const { watch = {} } = config.server;
|
|
@@ -1130,6 +1158,7 @@ const pluginHMR = () => {
|
|
|
1130
1158
|
closeBundle() {
|
|
1131
1159
|
subs.unsubscribe();
|
|
1132
1160
|
},
|
|
1161
|
+
// background changes require a full extension reload
|
|
1133
1162
|
handleHotUpdate({ modules, server }) {
|
|
1134
1163
|
const { root } = server.config;
|
|
1135
1164
|
const relFiles = /* @__PURE__ */ new Set();
|
|
@@ -1157,6 +1186,7 @@ const pluginHMR = () => {
|
|
|
1157
1186
|
name: "crx:hmr",
|
|
1158
1187
|
apply: "serve",
|
|
1159
1188
|
enforce: "post",
|
|
1189
|
+
// get final output manifest for handleHotUpdate 👆
|
|
1160
1190
|
async transformCrxManifest(manifest) {
|
|
1161
1191
|
inputManifestFiles = await manifestFiles(manifest, { cwd: config.root });
|
|
1162
1192
|
return null;
|
|
@@ -1247,6 +1277,7 @@ const pluginHtmlInlineScripts = () => {
|
|
|
1247
1277
|
};
|
|
1248
1278
|
const postPlugin = {
|
|
1249
1279
|
name: "crx:html-auditor-post",
|
|
1280
|
+
// this hook isn't audited b/c we add it after we set up the auditors
|
|
1250
1281
|
transformIndexHtml(html, ctx) {
|
|
1251
1282
|
const key = toKey(ctx);
|
|
1252
1283
|
const p = pages.get(key);
|
|
@@ -1591,6 +1622,7 @@ Public dir: "${config.publicDir}"`
|
|
|
1591
1622
|
this.emitFile({
|
|
1592
1623
|
type: "asset",
|
|
1593
1624
|
fileName: f,
|
|
1625
|
+
// TODO: cache source buffer
|
|
1594
1626
|
source: await readFile(filename)
|
|
1595
1627
|
});
|
|
1596
1628
|
}
|
|
@@ -1703,8 +1735,11 @@ const pluginWebAccessibleResources = () => {
|
|
|
1703
1735
|
...rest
|
|
1704
1736
|
})).filter(({ resources }) => resources.length);
|
|
1705
1737
|
manifest.web_accessible_resources.push({
|
|
1738
|
+
// change the extension origin on every reload
|
|
1706
1739
|
use_dynamic_url: true,
|
|
1740
|
+
// all web origins can access
|
|
1707
1741
|
matches: ["<all_urls>"],
|
|
1742
|
+
// all resources are web accessible
|
|
1708
1743
|
resources: ["**/*", "*"]
|
|
1709
1744
|
});
|
|
1710
1745
|
return manifest;
|
|
@@ -1834,6 +1869,7 @@ const pluginWebAccessibleResources = () => {
|
|
|
1834
1869
|
};
|
|
1835
1870
|
|
|
1836
1871
|
const crx = (options) => {
|
|
1872
|
+
contentScripts.clear();
|
|
1837
1873
|
return [
|
|
1838
1874
|
pluginOptionsProvider(options),
|
|
1839
1875
|
pluginBackground(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crxjs/vite-plugin",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.13",
|
|
4
4
|
"description": "Build Chrome Extensions with this Vite plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rollup-plugin",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"@vitejs/plugin-react": "^2.1.0",
|
|
102
102
|
"@vitejs/plugin-vue": "3.2.0",
|
|
103
103
|
"chokidar": "^3.5.3",
|
|
104
|
-
"esbuild": "0.
|
|
104
|
+
"esbuild": "0.17.4",
|
|
105
105
|
"esbuild-runner": "2.2.2",
|
|
106
106
|
"eslint": "8.26.0",
|
|
107
107
|
"eslint-plugin-react": "^7.29.4",
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
"svelte": "^3.48.0",
|
|
117
117
|
"typescript": "^4.6.4",
|
|
118
118
|
"vite": "^3.1.7",
|
|
119
|
-
"vite-plugin-inspect": "0.7.
|
|
120
|
-
"vitest": "0.
|
|
119
|
+
"vite-plugin-inspect": "0.7.14",
|
|
120
|
+
"vitest": "0.28.5",
|
|
121
121
|
"vue": "3.2.41"
|
|
122
122
|
}
|
|
123
123
|
}
|