diff --git a/.changeset/bright-peaches-wink.md b/.changeset/bright-peaches-wink.md new file mode 100644 index 000000000..f9b01d46f --- /dev/null +++ b/.changeset/bright-peaches-wink.md @@ -0,0 +1,5 @@ +--- +"@crxjs/vite-plugin": patch +--- + +fix: hmr error diff --git a/.changeset/eight-stingrays-provide.md b/.changeset/eight-stingrays-provide.md new file mode 100644 index 000000000..0027f490d --- /dev/null +++ b/.changeset/eight-stingrays-provide.md @@ -0,0 +1,5 @@ +--- +"@crxjs/vite-plugin": patch +--- + +Fix/web accessible resources script modules diff --git a/.changeset/fair-flies-admire.md b/.changeset/fair-flies-admire.md new file mode 100644 index 000000000..884071c40 --- /dev/null +++ b/.changeset/fair-flies-admire.md @@ -0,0 +1,5 @@ +--- +"@crxjs/vite-plugin": patch +--- + +Delete invalid changeset diff --git a/.changeset/fluffy-geckos-flash.md b/.changeset/fluffy-geckos-flash.md new file mode 100644 index 000000000..6a333d916 --- /dev/null +++ b/.changeset/fluffy-geckos-flash.md @@ -0,0 +1,5 @@ +--- +"@crxjs/vite-plugin": patch +--- + +fix: background scripts for firefox build diff --git a/.changeset/happy-carpets-boil.md b/.changeset/happy-carpets-boil.md new file mode 100644 index 000000000..1a5db9ded --- /dev/null +++ b/.changeset/happy-carpets-boil.md @@ -0,0 +1,5 @@ +--- +"@crxjs/vite-plugin": patch +--- + +feat: add compatibility mode for Firefox diff --git a/.changeset/pre.json b/.changeset/pre.json index 09c37dd62..e972de0ca 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -9,14 +9,18 @@ "changesets": [ "beige-snails-kiss", "breezy-plums-study", + "eight-stingrays-provide", "eleven-buttons-dream", "eleven-planes-tease", "fair-eggs-change", + "fair-flies-admire", + "fluffy-geckos-flash", "fluffy-numbers-brake", "fresh-suns-do", "gold-spies-occur", "grumpy-brooms-exist", "grumpy-comics-explain", + "happy-carpets-boil", "kind-donkeys-cry", "late-paws-change", "long-kangaroos-work", @@ -32,8 +36,10 @@ "swift-years-kick", "tidy-shrimps-cross", "tiny-planes-float", + "unlucky-goats-exist", "wet-hornets-run", "wicked-moose-listen", + "yellow-paws-search", "young-terms-tickle" ] } diff --git a/.changeset/unlucky-goats-exist.md b/.changeset/unlucky-goats-exist.md new file mode 100644 index 000000000..4b38c0a95 --- /dev/null +++ b/.changeset/unlucky-goats-exist.md @@ -0,0 +1,5 @@ +--- +"rollup-plugin-chrome-extension": patch +--- + +Add match_origin_as_fallback to manifest-v3.schema.json diff --git a/.changeset/yellow-paws-search.md b/.changeset/yellow-paws-search.md new file mode 100644 index 000000000..9c4d58b35 --- /dev/null +++ b/.changeset/yellow-paws-search.md @@ -0,0 +1,6 @@ +--- +'@crxjs/vite-plugin': patch +--- + +Vite 5 moved vite manifest from 'manifest.json' to '.vite/manifest.json'. +This change updates the plugin to use the new location if Vite major version is >4, old location otherwise. \ No newline at end of file diff --git a/.github/workflows/vite-plugin.yml b/.github/workflows/vite-plugin.yml index 8e928e58d..f6ea44592 100644 --- a/.github/workflows/vite-plugin.yml +++ b/.github/workflows/vite-plugin.yml @@ -113,7 +113,7 @@ jobs: run: pnpm install --filter "vite-plugin" - name: Run e2e tests - uses: xvfb-run -a npm test + uses: coactions/setup-xvfb@v1 with: run: pnpm test:run:e2e working-directory: "packages/vite-plugin" diff --git a/packages/rollup-plugin/CHANGELOG.md b/packages/rollup-plugin/CHANGELOG.md index 0c31fc18f..c45069d80 100644 --- a/packages/rollup-plugin/CHANGELOG.md +++ b/packages/rollup-plugin/CHANGELOG.md @@ -1,5 +1,11 @@ # rollup-plugin-chrome-extension +## 3.6.13-beta.1 + +### Patch Changes + +- a0d4592: Add match_origin_as_fallback to manifest-v3.schema.json + ## 3.6.13-beta.0 ### Patch Changes diff --git a/packages/rollup-plugin/package.json b/packages/rollup-plugin/package.json index 2e4e63d41..12b80ca97 100644 --- a/packages/rollup-plugin/package.json +++ b/packages/rollup-plugin/package.json @@ -1,6 +1,6 @@ { "name": "rollup-plugin-chrome-extension", - "version": "3.6.13-beta.0", + "version": "3.6.13-beta.1", "description": "Build Chrome Extensions with this Rollup plugin.", "keywords": [ "rollup-plugin", diff --git a/packages/rollup-plugin/schema/manifest-v3.schema.json b/packages/rollup-plugin/schema/manifest-v3.schema.json index c9e5d3602..5353148eb 100644 --- a/packages/rollup-plugin/schema/manifest-v3.schema.json +++ b/packages/rollup-plugin/schema/manifest-v3.schema.json @@ -150,6 +150,7 @@ "scripting", "search", "sessions", + "sidePanel", "signedInDevices", "storage", "system.cpu", @@ -279,6 +280,11 @@ "description": "Controls whether the content script runs in all frames of the matching page, or only the top frame.", "type": "boolean" }, + "match_origin_as_fallback": { + "type": "boolean", + "description": "Controls whether the content script runs in frames that are related to a matching frame.", + "default": false + }, "css": { "description": "The list of CSS files to be injected into matching pages. These are injected in the order they appear in this array, before any DOM is constructed or displayed for the page.", "items": { @@ -678,6 +684,17 @@ "maxLength": 12, "type": "string" }, + "side_panel": { + "description": "The Side Panel API allows extensions to display their own UI in the side panel, enabling persistent experiences that complement the user's browsing journey.", + "properties": { + "default_path": { + "description": "The path to your site panel page, relative to your extension's root.", + "type": "string" + } + }, + "required": ["default_path"], + "type": "object" + }, "signature": {}, "spellcheck": {}, "storage": {}, diff --git a/packages/vite-plugin-docs/docs/getting-started/_create-project-tabs.mdx b/packages/vite-plugin-docs/docs/getting-started/_create-project-tabs.mdx index 0e972dd33..a1590863e 100644 --- a/packages/vite-plugin-docs/docs/getting-started/_create-project-tabs.mdx +++ b/packages/vite-plugin-docs/docs/getting-started/_create-project-tabs.mdx @@ -24,6 +24,12 @@ npm init vite@latest CRXJS support for Vite 3 is in beta. +::: + +:::info react users + +HMR in CRXJS is incompatible with `@vite/plugin-react-swc`. We recommend using @vitejs/plugin-react instead. + ::: diff --git a/packages/vite-plugin-docs/docs/getting-started/react/01-dev-basics.md b/packages/vite-plugin-docs/docs/getting-started/react/01-dev-basics.md index ca994d1fd..9feb96be6 100644 --- a/packages/vite-plugin-docs/docs/getting-started/react/01-dev-basics.md +++ b/packages/vite-plugin-docs/docs/getting-started/react/01-dev-basics.md @@ -18,6 +18,9 @@ import Installing from '../\_install-extension.md'; +## Install the extension + + ## Opening the extension diff --git a/packages/vite-plugin/CHANGELOG.md b/packages/vite-plugin/CHANGELOG.md index ccf463319..f693c98d1 100644 --- a/packages/vite-plugin/CHANGELOG.md +++ b/packages/vite-plugin/CHANGELOG.md @@ -1,5 +1,32 @@ # @crxjs/vite-plugin +## 2.0.0-beta.22 + +### Patch Changes + +- ce9fe1c: Fix/web accessible resources script modules +- 48d8c68: Vite 5 moved vite manifest from 'manifest.json' to + '.vite/manifest.json'. This change updates the plugin to use the new location + if Vite major version is >4, old location otherwise. + +## 2.0.0-beta.21 + +### Patch Changes + +- cbfd0b3: Delete invalid changeset + +## 2.0.0-beta.20 + +### Patch Changes + +- f5c4bd7: fix: background scripts for firefox build + +## 2.0.0-beta.19 + +### Patch Changes + +- 34980de: feat: add compatibility mode for Firefox + ## 2.0.0-beta.18 ### Patch Changes diff --git a/packages/vite-plugin/package.json b/packages/vite-plugin/package.json index 1681757ed..0bd855aac 100644 --- a/packages/vite-plugin/package.json +++ b/packages/vite-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@crxjs/vite-plugin", - "version": "2.0.0-beta.18", + "version": "2.0.0-beta.22", "description": "Build Chrome Extensions with this Vite plugin.", "keywords": [ "rollup-plugin", diff --git a/packages/vite-plugin/src/client/es/loading-page-script.ts b/packages/vite-plugin/src/client/es/loading-page-script.ts new file mode 100644 index 000000000..629570b12 --- /dev/null +++ b/packages/vite-plugin/src/client/es/loading-page-script.ts @@ -0,0 +1,64 @@ +/** + * This script runs in Vite dev mode if an extension page opens before the + * service worker takes control of fetch (e.g., in the onInstalled event). + */ + +const VITE_URL = 'http://localhost:%PORT%' + +document.body.innerHTML = ` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on ${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
` +document.body.querySelector('button')?.addEventListener('click', () => { + chrome.runtime.reload() +}) + +// ping the dev server until it's ready +let tries = 0 +let ready = false +do { + try { + await fetch(VITE_URL) + ready = true + } catch { + // exponential backoff for retries, maxing out at every 5 seconds + const timeout = Math.min(100 * Math.pow(2, ++tries), 5000) + console.log(`[CRXJS] Vite Dev Server is not available on ${VITE_URL}`) + console.log(`[CRXJS] Retrying in ${timeout}ms...`) + await new Promise((resolve) => setTimeout(resolve, timeout)) + } +} while (!ready) + +// reload the page to load the built files from the dev server +location.reload() + +export {} diff --git a/packages/vite-plugin/src/client/es/page-precontroller-script.ts b/packages/vite-plugin/src/client/es/page-precontroller-script.ts deleted file mode 100644 index 6a2cf5302..000000000 --- a/packages/vite-plugin/src/client/es/page-precontroller-script.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * This script only runs in development, and only if an extension page opens - * before the service worker takes control of fetch (e.g., in the onInstalled event). - * - * Note: `oncontrollerchange` does not fire in this context, instead the page - * continuously reloads until the service worker takes over. - */ -const id = setInterval(() => location.reload(), 100) -setTimeout(() => clearInterval(id), 5000) -export {} diff --git a/packages/vite-plugin/src/client/html/loading-page.html b/packages/vite-plugin/src/client/html/loading-page.html new file mode 100644 index 000000000..f7f9a3a6a --- /dev/null +++ b/packages/vite-plugin/src/client/html/loading-page.html @@ -0,0 +1,12 @@ + + + + Vite Dev Mode + + + +

Vite Dev Mode

+ + diff --git a/packages/vite-plugin/src/client/html/precontroller.html b/packages/vite-plugin/src/client/html/precontroller.html deleted file mode 100644 index 7a892d483..000000000 --- a/packages/vite-plugin/src/client/html/precontroller.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - Waiting for the extension service worker... - - - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

- - diff --git a/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts b/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts index d7aaa8ab0..e73b17ba6 100644 --- a/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts +++ b/packages/vite-plugin/src/node/archive/plugin-contentScripts.ts @@ -77,7 +77,10 @@ export const dynamicResourcesName = '' as const * to all urls. This is secure enough for our purposes b/c the CRX origin is * changed randomly each runtime reload. */ -export const pluginContentScripts: CrxPluginFn = ({ contentScripts = {} }) => { +export const pluginContentScripts: CrxPluginFn = ({ + contentScripts = {}, + browser = 'chrome', +}) => { const { hmrTimeout = 5000, injectCss = true } = contentScripts const dynamicScriptsById = new Map() const dynamicScriptsByLoaderRefId = new Map() @@ -410,14 +413,20 @@ export const pluginContentScripts: CrxPluginFn = ({ contentScripts = {} }) => { .filter(({ resources }) => resources.length) // during development don't specific resources - manifest.web_accessible_resources.push({ - // change the extension origin on every reload - use_dynamic_url: true, + const war: WebAccessibleResourceByMatch = { // all web origins can access matches: [''], // all resources are web accessible resources: ['**/*', '*'], - }) + } + + if (browser !== 'firefox') { + // change the extension origin on every reload + // not allowed in FF b/c FF does this by default + war.use_dynamic_url = true + } + + manifest.web_accessible_resources.push(war) } else { const vmAsset = bundle['manifest.json'] as OutputAsset if (!vmAsset) throw new Error('vite manifest is missing') @@ -564,13 +573,13 @@ export const pluginContentScripts: CrxPluginFn = ({ contentScripts = {} }) => { // clean up web_accessible_resources if (manifest.web_accessible_resources?.length) { - const war = manifest.web_accessible_resources + const wars = manifest.web_accessible_resources manifest.web_accessible_resources = [] const map = new Map>() - for (const r of war) - if (isResourceByMatch(r)) { + for (const war of wars) + if (isResourceByMatch(war)) { // combine resources that share match patterns - const { matches, resources, use_dynamic_url = false } = r + const { matches, resources, use_dynamic_url = false } = war const key = [use_dynamic_url, matches.sort()] .map((x) => JSON.stringify(x)) .join('::') @@ -578,19 +587,32 @@ export const pluginContentScripts: CrxPluginFn = ({ contentScripts = {} }) => { resources.forEach((r) => set.add(r)) map.set(key, set) } else { + // FF does not allow the use_dynamic_url key b/c the urls are always + // dynamic in FF + if (browser === 'firefox' && 'use_dynamic_url' in war) + delete war.use_dynamic_url + // don't touch resources by CRX_id - manifest.web_accessible_resources.push(r) + manifest.web_accessible_resources.push(war) } // rebuild combined resources for (const [key, set] of map) { const [use_dynamic_url, matches] = key .split('::') .map((x) => JSON.parse(x)) as [boolean, string[]] - manifest.web_accessible_resources.push({ + + const war: + | WebAccessibleResourceById + | WebAccessibleResourceByMatch = { matches, resources: [...set], - use_dynamic_url, - }) + } + + // FF does not allow the use_dynamic_url key b/c the urls are always + // dynamic in FF + if (browser !== 'firefox') war.use_dynamic_url = use_dynamic_url + + manifest.web_accessible_resources.push(war) } } else { // array is empty or undefined diff --git a/packages/vite-plugin/src/node/files.ts b/packages/vite-plugin/src/node/files.ts index ab82e98c9..c9962d9af 100644 --- a/packages/vite-plugin/src/node/files.ts +++ b/packages/vite-plugin/src/node/files.ts @@ -19,7 +19,11 @@ export async function manifestFiles( const contentScripts = manifest.content_scripts?.flatMap(({ js }) => js) ?? [] const contentStyles = manifest.content_scripts?.flatMap(({ css }) => css) - const serviceWorker = manifest.background?.service_worker + + const serviceWorker = manifest.background && "service_worker" in manifest.background ? manifest.background.service_worker : undefined; + const backgroundScripts = manifest.background && "scripts" in manifest.background ? manifest.background.scripts : undefined; + const background = serviceWorker ? [serviceWorker].filter(isString) : backgroundScripts ? backgroundScripts.filter(isString) : []; + const htmlPages = htmlFiles(manifest) const icons = [ @@ -55,7 +59,7 @@ export async function manifestFiles( icons: [...new Set(icons)].filter(isString), locales: [...new Set(locales)].filter(isString), rulesets: [...new Set(rulesets)].filter(isString), - background: [serviceWorker].filter(isString), + background: background, webAccessibleResources, } } diff --git a/packages/vite-plugin/src/node/manifest.ts b/packages/vite-plugin/src/node/manifest.ts index 67ac74ae2..6c4a5b3ca 100644 --- a/packages/vite-plugin/src/node/manifest.ts +++ b/packages/vite-plugin/src/node/manifest.ts @@ -16,6 +16,16 @@ export interface WebAccessibleResourceById { use_dynamic_url?: boolean } +export interface ChromeManifestBackground { + service_worker: string + type?: 'module' // If the service worker uses ES modules +} + +export interface FirefoxManifestBackground { + scripts: string[] + persistent?: false +} + export interface ManifestV3 { // Required manifest_version: number @@ -32,10 +42,8 @@ export interface ManifestV3 { action?: chrome.runtime.ManifestAction | undefined author?: string | undefined background?: - | { - service_worker: string - type?: 'module' // If the service worker uses ES modules - } + | ChromeManifestBackground + | FirefoxManifestBackground | undefined chrome_settings_overrides?: | { diff --git a/packages/vite-plugin/src/node/plugin-background.ts b/packages/vite-plugin/src/node/plugin-background.ts index 9b6d33e60..b6ea8c5a8 100644 --- a/packages/vite-plugin/src/node/plugin-background.ts +++ b/packages/vite-plugin/src/node/plugin-background.ts @@ -2,7 +2,9 @@ import workerHmrClient from 'client/es/hmr-client-worker.ts' import { ResolvedConfig } from 'vite' import { defineClientValues } from './defineClientValues' import { getFileName } from './fileWriter-utilities' -import type { CrxPluginFn } from './types' +import { ChromeManifestBackground, FirefoxManifestBackground } from './manifest' +import { getOptions } from './plugin-optionsProvider' +import type { Browser, CrxPluginFn } from './types' import { workerClientId } from './virtualFileIds' /** @@ -21,6 +23,7 @@ import { workerClientId } from './virtualFileIds' */ export const pluginBackground: CrxPluginFn = () => { let config: ResolvedConfig + let browser: Browser return [ { @@ -43,11 +46,18 @@ export const pluginBackground: CrxPluginFn = () => { name: 'crx:background-loader-file', // this should happen after other plugins; the loader file is an implementation detail enforce: 'post', + async config(config) { + const opts = await getOptions(config) + browser = opts.browser || 'chrome' + }, configResolved(_config) { config = _config }, renderCrxManifest(manifest) { - const worker = manifest.background?.service_worker + const worker = + browser === 'firefox' + ? (manifest.background as FirefoxManifestBackground)?.scripts[0] + : (manifest.background as ChromeManifestBackground)?.service_worker let loader: string if (config.command === 'serve') { @@ -55,12 +65,26 @@ export const pluginBackground: CrxPluginFn = () => { if (typeof port === 'undefined') throw new Error('server port is undefined in watch mode') - // development, required to define env vars - loader = `import 'http://localhost:${port}/@vite/env';\n` - // development, required hmr client - loader += `import 'http://localhost:${port}${workerClientId}';\n` - // development, optional service worker - if (worker) loader += `import 'http://localhost:${port}/${worker}';\n` + if (browser === 'firefox') { + // in FF, our "service worker" is actually a background page so we + // can't use import statements + + // development, required to define env vars + loader = `import('http://localhost:${port}/@vite/env');\n` + // development, required hmr client + loader += `import('http://localhost:${port}${workerClientId}');\n` + // development, optional service worker + if (worker) + loader += `import('http://localhost:${port}/${worker}');\n` + } else { + // development, required to define env vars + loader = `import 'http://localhost:${port}/@vite/env';\n` + // development, required hmr client + loader += `import 'http://localhost:${port}${workerClientId}';\n` + // development, optional service worker + if (worker) + loader += `import 'http://localhost:${port}/${worker}';\n` + } } else if (worker) { // production w/ service worker loader at root, see comment at top of file. loader = `import './${worker}';\n` @@ -76,9 +100,16 @@ export const pluginBackground: CrxPluginFn = () => { source: loader, }) - manifest.background = { - service_worker: this.getFileName(refId), - type: 'module', + if (browser !== 'firefox') { + manifest.background = { + service_worker: this.getFileName(refId), + type: 'module', + } + } else { + manifest.background = { + scripts: [this.getFileName(refId)], + type: 'module', + } } return manifest diff --git a/packages/vite-plugin/src/node/plugin-hmr.ts b/packages/vite-plugin/src/node/plugin-hmr.ts index e7603dc58..8f134624f 100644 --- a/packages/vite-plugin/src/node/plugin-hmr.ts +++ b/packages/vite-plugin/src/node/plugin-hmr.ts @@ -101,7 +101,6 @@ export const pluginHMR: CrxPluginFn = () => { ) { debug('sending runtime reload') server.ws.send(crxRuntimeReload) - return [] } } diff --git a/packages/vite-plugin/src/node/plugin-manifest.ts b/packages/vite-plugin/src/node/plugin-manifest.ts index 24d90898e..d6c838bf0 100644 --- a/packages/vite-plugin/src/node/plugin-manifest.ts +++ b/packages/vite-plugin/src/node/plugin-manifest.ts @@ -1,12 +1,12 @@ -import precontrollerJs from 'client/es/page-precontroller-script.ts' -import precontrollerHtml from 'client/html/precontroller.html' +import loadingPageScript from 'client/es/loading-page-script.ts' +import loadingPageHtml from 'client/html/loading-page.html' import { existsSync, promises as fs } from 'fs' import colors from 'picocolors' import { OutputAsset, OutputChunk } from 'rollup' import { ResolvedConfig } from 'vite' import { contentScripts, hashScriptId } from './contentScripts' -import { htmlFiles, manifestFiles } from './files' import { formatFileData, getFileName, prefix } from './fileWriter-utilities' +import { htmlFiles, manifestFiles } from './files' import { decodeManifest, encodeManifest, @@ -228,7 +228,7 @@ export const pluginManifest: CrxPluginFn = () => { ) } - if (manifest.background?.service_worker) { + if (manifest.background && 'service_worker' in manifest.background) { const file = manifest.background.service_worker const id = join(config.root, file) const refId = this.emitFile({ @@ -239,6 +239,17 @@ export const pluginManifest: CrxPluginFn = () => { manifest.background.service_worker = refId } + if (manifest.background && 'scripts' in manifest.background) { + const file = manifest.background.scripts[0] + const id = join(config.root, file) + const refId = this.emitFile({ + type: 'chunk', + id, + name: basename(file), + }) + manifest.background.scripts = [refId] + } + for (const file of htmlFiles(manifest)) { const id = join(config.root, file) this.emitFile({ @@ -272,12 +283,18 @@ export const pluginManifest: CrxPluginFn = () => { // transform hook emits files and replaces in manifest with ref ids // update background service worker filename from ref // service worker not emitted during development, so don't update file name - if (manifest.background?.service_worker) { + if (manifest.background && 'service_worker' in manifest.background) { const ref = manifest.background.service_worker const name = this.getFileName(ref) manifest.background.service_worker = name } + if (manifest.background && 'scripts' in manifest.background) { + const ref = manifest.background.scripts[0] + const name = this.getFileName(ref) + manifest.background.scripts = [name] + } + // update content script file names from refs // TODO: emit and parse css manifest.content_scripts = manifest.content_scripts?.map( @@ -365,17 +382,20 @@ Public dir: "${config.publicDir}"`, if (config.command === 'serve' && files.html.length) { const refId = this.emitFile({ type: 'asset', - name: 'precontroller.js', - source: precontrollerJs, + name: 'loading-page.js', + source: loadingPageScript.replace( + '%PORT%', + `${config.server.port ?? 0}`, + ), }) - const precontrollerJsName = this.getFileName(refId) + const loadingPageScriptName = this.getFileName(refId) files.html.map((f) => this.emitFile({ type: 'asset', fileName: f, - source: precontrollerHtml.replace( + source: loadingPageHtml.replace( '%SCRIPT%', - `/${precontrollerJsName}`, + `/${loadingPageScriptName}`, ), }), ) diff --git a/packages/vite-plugin/src/node/plugin-optionsProvider.ts b/packages/vite-plugin/src/node/plugin-optionsProvider.ts index d882844bd..d011498eb 100644 --- a/packages/vite-plugin/src/node/plugin-optionsProvider.ts +++ b/packages/vite-plugin/src/node/plugin-optionsProvider.ts @@ -2,7 +2,9 @@ import { PluginOption, UserConfig } from 'vite' import { ManifestV3Export } from './defineManifest' import { CrxOptions, CrxPlugin } from './types' -export type CrxInputOptions = { manifest: ManifestV3Export } & CrxOptions +export interface CrxInputOptions extends CrxOptions { + manifest: ManifestV3Export +} const pluginName = 'crx:optionsProvider' export const pluginOptionsProvider = (options: CrxInputOptions | null) => { diff --git a/packages/vite-plugin/src/node/plugin-webAccessibleResources.ts b/packages/vite-plugin/src/node/plugin-webAccessibleResources.ts index 4dff92f82..3306d8ce2 100644 --- a/packages/vite-plugin/src/node/plugin-webAccessibleResources.ts +++ b/packages/vite-plugin/src/node/plugin-webAccessibleResources.ts @@ -1,5 +1,9 @@ import { OutputChunk } from 'rollup' -import { Manifest as ViteManifest, ResolvedConfig } from 'vite' +import { + Manifest as ViteManifest, + ResolvedConfig, + version as ViteVersion, +} from 'vite' import { compileFileResources } from './compileFileResources' import { contentScripts } from './contentScripts' import { DYNAMIC_RESOURCE } from './defineManifest' @@ -14,19 +18,24 @@ import { WebAccessibleResourceByMatch, } from './manifest' import { getOptions } from './plugin-optionsProvider' -import { CrxPluginFn } from './types' +import type { CrxPluginFn, Browser } from './types' const debug = _debug('web-acc-res') export const pluginWebAccessibleResources: CrxPluginFn = () => { let config: ResolvedConfig let injectCss: boolean + let browser: Browser return [ { name: 'crx:web-accessible-resources', apply: 'serve', enforce: 'post', + async config(config) { + const opts = await getOptions(config) + browser = opts.browser || 'chrome' + }, renderCrxManifest(manifest) { // set default value for web_accessible_resources manifest.web_accessible_resources = @@ -40,15 +49,22 @@ export const pluginWebAccessibleResources: CrxPluginFn = () => { })) .filter(({ resources }) => resources.length) - // during development don't do specific resources - manifest.web_accessible_resources.push({ - // change the extension origin on every reload - use_dynamic_url: true, + // during development don't specific resources + const war: WebAccessibleResourceByMatch = { // all web origins can access matches: [''], // all resources are web accessible resources: ['**/*', '*'], - }) + // change the extension origin on every reload + use_dynamic_url: true, + } + + if (browser === 'firefox') { + // not allowed in FF b/c FF does this by default + delete war.use_dynamic_url + } + + manifest.web_accessible_resources.push(war) return manifest }, @@ -58,7 +74,9 @@ export const pluginWebAccessibleResources: CrxPluginFn = () => { apply: 'build', enforce: 'post', async config({ build, ...config }, { command }) { - const { contentScripts = {} } = await getOptions(config) + const opts = await getOptions(config) + const contentScripts = opts.contentScripts || {} + browser = opts.browser || 'chrome' injectCss = contentScripts.injectCss ?? true return { ...config, build: { ...build, manifest: command === 'build' } } @@ -88,10 +106,16 @@ export const pluginWebAccessibleResources: CrxPluginFn = () => { // derive content script resources from vite file manifest if (contentScripts.size > 0) { + // Vite 5 changed the manifest.json location to .vite/manifest.json. + // In order to support both Vite <=4 and Vite 5, we need to check the Vite version and determine the path accordingly. + const viteMajorVersion = parseInt(ViteVersion.split('.')[0]) + const manifestPath = viteMajorVersion > 4 ? '.vite/manifest.json' : 'manifest.json' + const viteManifest = parseJsonAsset( bundle, - 'manifest.json', + manifestPath, ) + const viteFiles = new Map() for (const [, file] of Object.entries(viteManifest)) viteFiles.set(file.file, file) @@ -127,7 +151,8 @@ export const pluginWebAccessibleResources: CrxPluginFn = () => { contentScripts.get(key)!.css = [...css] // loader files import the entry, so entry file must be web accessible - if (type === 'loader') imports.add(fileName) + if (type === 'loader' || isDynamicScript) + imports.add(fileName) const resource: | WebAccessibleResourceById @@ -191,6 +216,13 @@ export const pluginWebAccessibleResources: CrxPluginFn = () => { }) } + /* ------------- BROWSER COMPATIBILITY ------------- */ + if (browser === 'firefox') { + for (const war of combinedResources) { + delete war.use_dynamic_url + } + } + /* --------------- CLEAN UP MANIFEST --------------- */ if (combinedResources.length === 0) diff --git a/packages/vite-plugin/src/node/types.ts b/packages/vite-plugin/src/node/types.ts index b962c813b..d5bc7382c 100644 --- a/packages/vite-plugin/src/node/types.ts +++ b/packages/vite-plugin/src/node/types.ts @@ -51,12 +51,18 @@ export type CrxDevScriptId = { } export interface CrxPlugin extends VitePlugin { - /** Runs during the transform hook for the manifest. Filenames use input filenames. */ + /** + * Runs during the transform hook for the manifest. Filenames use input + * filenames. + */ transformCrxManifest?: ( this: PluginContext, manifest: ManifestV3, ) => Promise | ManifestV3 | null | undefined - /** Runs during generateBundle, before manifest output. Filenames use output filenames. */ + /** + * Runs during generateBundle, before manifest output. Filenames use output + * filenames. + */ renderCrxManifest?: ( this: PluginContext, manifest: ManifestV3, @@ -73,7 +79,6 @@ export interface CrxPlugin extends VitePlugin { } // change this to an interface when you want to add options -// eslint-disable-next-line @typescript-eslint/no-explicit-any export interface CrxOptions { contentScripts?: { preambleCode?: string | false @@ -81,10 +86,17 @@ export interface CrxOptions { injectCss?: boolean } fastGlobOptions?: FastGlobOptions + /** + * The browser that this extension is targeting, can be "firefox" or "chrome". + * Default is "chrome". + */ + browser?: Browser } +export type Browser = 'firefox' | 'chrome' + export interface CrxPluginFn { - (): CrxPlugin | CrxPlugin[] + (options?: CrxOptions): CrxPlugin | CrxPlugin[] } export type ManifestFiles = { diff --git a/packages/vite-plugin/tests/out/basic-js/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/basic-js/__snapshots__/serve.test.ts.snap index 3bd85dc5c..344229787 100644 --- a/packages/vite-plugin/tests/out/basic-js/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/basic-js/__snapshots__/serve.test.ts.snap @@ -44,7 +44,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "manifest.json", "service-worker-loader.js", "src/content.js-loader.js", @@ -65,9 +65,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -113,17 +162,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/basic-ts/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/basic-ts/__snapshots__/serve.test.ts.snap index ea2999ad5..6f736fa8c 100644 --- a/packages/vite-plugin/tests/out/basic-ts/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/basic-ts/__snapshots__/serve.test.ts.snap @@ -41,7 +41,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "manifest.json", "service-worker-loader.js", "src/content.ts-loader.js", @@ -62,9 +62,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -111,17 +160,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/vite-react-fast-refresh/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/vite-react-fast-refresh/__snapshots__/serve.test.ts.snap index 36a722be0..c6b8ff7ef 100644 --- a/packages/vite-plugin/tests/out/vite-react-fast-refresh/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/vite-react-fast-refresh/__snapshots__/serve.test.ts.snap @@ -39,7 +39,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "manifest.json", "service-worker-loader.js", "src/App.tsx.js", @@ -66,9 +66,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -181,17 +230,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/vite-self-directive-in-csp/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/vite-self-directive-in-csp/__snapshots__/serve.test.ts.snap index 5ff9277d5..751bd0d94 100644 --- a/packages/vite-plugin/tests/out/vite-self-directive-in-csp/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/vite-self-directive-in-csp/__snapshots__/serve.test.ts.snap @@ -44,7 +44,7 @@ Object { exports[`works with 'self' directive > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "manifest.json", "service-worker-loader.js", "src/content.ts-loader.js", @@ -65,9 +65,58 @@ Set { } `; -exports[`works with 'self' directive > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`works with 'self' directive > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -114,17 +163,13 @@ exports[`works with 'self' directive > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/vite-svelte/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/vite-svelte/__snapshots__/serve.test.ts.snap index 39fea1a2c..202627526 100644 --- a/packages/vite-plugin/tests/out/vite-svelte/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/vite-svelte/__snapshots__/serve.test.ts.snap @@ -39,7 +39,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash.js", + "assets/loading-page.hash.js", "favicon.ico", "manifest.json", "service-worker-loader.js", @@ -75,9 +75,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -88,7 +137,7 @@ import 'http://localhost:3000/@crx/client-worker'; `; exports[`serve fs output > src/App.svelte.js 1`] = ` -"import { createHotContext as __vite__createHotContext } from \\"/vendor/vite-client.js\\";import.meta.hot = __vite__createHotContext(\\"/src/App.svelte.js\\");/* tests/out/vite-svelte/src/App.svelte generated by Svelte v3.48.0 */ +"import { createHotContext as __vite__createHotContext } from \\"/vendor/vite-client.js\\";import.meta.hot = __vite__createHotContext(\\"/src/App.svelte.js\\");/* src/App.svelte generated by Svelte v3.48.0 */ import { SvelteComponentDev as SvelteComponentDev$, add_location as add_location$, @@ -116,7 +165,7 @@ import { const { Error: Error$, Object: Object$, console: console$ } = globals$; import logo from '/src/assets/svelte.png__import.js'; import Counter from '/src/lib/Counter.svelte.js'; -const file$ = \\"tests/out/vite-svelte/src/App.svelte\\"; +const file$ = \\"src/App.svelte\\"; function create_fragment(ctx) { let main$; @@ -316,7 +365,7 @@ exports[`serve fs output > src/content.js-loader.js 1`] = ` `; exports[`serve fs output > src/lib/Counter.svelte.js 1`] = ` -"import { createHotContext as __vite__createHotContext } from \\"/vendor/vite-client.js\\";import.meta.hot = __vite__createHotContext(\\"/src/lib/Counter.svelte.js\\");/* tests/out/vite-svelte/src/lib/Counter.svelte generated by Svelte v3.48.0 */ +"import { createHotContext as __vite__createHotContext } from \\"/vendor/vite-client.js\\";import.meta.hot = __vite__createHotContext(\\"/src/lib/Counter.svelte.js\\");/* src/lib/Counter.svelte generated by Svelte v3.48.0 */ import { SvelteComponentDev as SvelteComponentDev$, add_location as add_location$, @@ -337,7 +386,7 @@ import { } from \\"/vendor/svelte_internal.js__v--hash.js\\"; const { Error: Error$, Object: Object$, console: console$ } = globals$; -const file$ = \\"tests/out/vite-svelte/src/lib/Counter.svelte\\"; +const file$ = \\"src/lib/Counter.svelte\\"; function create_fragment(ctx) { let button$; @@ -454,17 +503,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/with-circular-deps/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/with-circular-deps/__snapshots__/serve.test.ts.snap index b7c6c05cc..ec0b0e064 100644 --- a/packages/vite-plugin/tests/out/with-circular-deps/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/with-circular-deps/__snapshots__/serve.test.ts.snap @@ -41,7 +41,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "index.html", "manifest.json", "service-worker-loader.js", @@ -64,9 +64,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -74,17 +123,13 @@ exports[`serve fs output > index.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/with-public-dir/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/with-public-dir/__snapshots__/serve.test.ts.snap index 393b543e0..d08bb77a3 100644 --- a/packages/vite-plugin/tests/out/with-public-dir/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/with-public-dir/__snapshots__/serve.test.ts.snap @@ -42,7 +42,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "favicon.svg", "icons/action-icon-128.png", "icons/action-icon-16.png", @@ -64,9 +64,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -80,17 +129,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

" diff --git a/packages/vite-plugin/tests/out/with-sourcemaps/__snapshots__/serve.test.ts.snap b/packages/vite-plugin/tests/out/with-sourcemaps/__snapshots__/serve.test.ts.snap index 282e48469..08016784e 100644 --- a/packages/vite-plugin/tests/out/with-sourcemaps/__snapshots__/serve.test.ts.snap +++ b/packages/vite-plugin/tests/out/with-sourcemaps/__snapshots__/serve.test.ts.snap @@ -41,7 +41,7 @@ Object { exports[`serve fs output > _01 output files 1`] = ` Array [ - "assets/precontroller.hash0.js", + "assets/loading-page.hash0.js", "manifest.json", "service-worker-loader.js", "src/content.ts-loader.js", @@ -62,9 +62,58 @@ Set { } `; -exports[`serve fs output > assets/precontroller.hash0.js 1`] = ` -"const id = setInterval(() => location.reload(), 100); -setTimeout(() => clearInterval(id), 5e3); +exports[`serve fs output > assets/loading-page.hash0.js 1`] = ` +"const VITE_URL = \\"http://localhost:3000\\"; +document.body.innerHTML = \` +
+

Vite Dev Mode

+

+ Cannot connect to the Vite Dev Server on \${VITE_URL} +

+

+ Double-check that Vite is working and reload the extension. +

+

+ This page will close when the extension reloads. +

+ +
\`; +document.body.querySelector(\\"button\\")?.addEventListener(\\"click\\", () => { + chrome.runtime.reload(); +}); +let tries = 0; +let ready = false; +do { + try { + await fetch(VITE_URL); + ready = true; + } catch { + const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3); + console.log(\`[CRXJS] Vite Dev Server is not available on \${VITE_URL}\`); + console.log(\`[CRXJS] Retrying in \${timeout}ms...\`); + await new Promise((resolve) => setTimeout(resolve, timeout)); + } +} while (!ready); +location.reload(); " `; @@ -114,17 +163,13 @@ exports[`serve fs output > src/popup.html 1`] = ` " - Waiting for the extension service worker... - + Vite Dev Mode + - -

Waiting for service worker

- -

- If you see this message, it means the service worker has not loaded fully. -

- -

This page is never added in production.

+ +

Vite Dev Mode

"