Files
rrweb/packages/web-extension/vite.config.ts
Justin Halsall 5217a09c60 Support top-layer <dialog> recording & replay (#1503)
* chore: its important to run `yarn build:all` before running `yarn dev`

* feat: trigger showModal from rrdom and rrweb

* feat: Add support for replaying modal and non modal dialog elements

* chore: Update dev script to remove CLEAR_DIST_DIR flag

* Get modal recording and replay working

* DRY up dialog test and dedupe snapshot images

* feat: Refactor dialog test to use updated attribute name

* feat: Update dialog test to include rr_open attribute

* chore: Add npm dependency happy-dom@14.12.0

* Add more test cases for dialog

* Clean up naming

* Refactor dialog open code

* Revert changed code that doesn't do anything

* Add documentation for unimplemented type

* chore: Remove unnecessary comments in dialog.test.ts

* rename rr_open to rr_openMode

* Replace todo with a skipped test

* Add better logging for CI

* Rename rr_openMode to rr_open_mode

rrdom downcases all attribute names which made `rr_openMode` tricky to deal with

* Remove unused images

* Move after iframe append based on @YunFeng0817's comment
https://github.com/rrweb-io/rrweb/pull/1503#discussion_r1666363931

* Remove redundant dialog handling from rrdom.

rrdom already handles dialog element creation it's self

* Rename variables for dialog handling in rrweb replay module

* Update packages/rrdom/src/document.ts

---------

Co-authored-by: Eoghan Murray <eoghan@getthere.ie>
2026-04-01 12:00:00 +08:00

115 lines
3.7 KiB
TypeScript

import { defineConfig, LibraryFormats, PluginOption } from 'vite';
import webExtension, { readJsonFile } from 'vite-plugin-web-extension';
import zip from 'vite-plugin-zip-pack';
import * as path from 'path';
import type { PackageJson } from 'type-fest';
import react from '@vitejs/plugin-react';
const emptyOutDir = !process.argv.includes('--watch');
function useSpecialFormat(
entriesToUse: string[],
format: LibraryFormats,
): PluginOption {
return {
name: 'use-special-format',
config(config) {
// entry can be string | string[] | {[entryAlias: string]: string}
const entry = config.build?.lib && config.build.lib.entry;
let shouldUse = false;
if (typeof entry === 'string') {
shouldUse = entriesToUse.includes(entry);
} else if (Array.isArray(entry)) {
shouldUse = entriesToUse.some((e) => entry.includes(e));
} else if (entry && typeof entry === 'object') {
const entryKeys = Object.keys(entry);
shouldUse = entriesToUse.some((e) => entryKeys.includes(e));
}
if (shouldUse) {
config.build = config.build ?? {};
// @ts-expect-error: lib needs to be an object, forcing it.
config.build.lib =
typeof config.build.lib == 'object' ? config.build.lib : {};
// @ts-expect-error: lib is an object
config.build.lib.formats = [format];
}
},
};
}
export default defineConfig({
root: 'src',
// Configure our outputs - nothing special, this is normal vite config
build: {
outDir: path.resolve(
__dirname,
'dist',
process.env.TARGET_BROWSER as string,
),
emptyOutDir,
},
// Add the webExtension plugin
plugins: [
react(),
webExtension({
// A function to generate manifest file dynamically.
manifest: () => {
const packageJson = readJsonFile('package.json') as PackageJson;
const isProduction = process.env.NODE_ENV === 'production';
type ManifestBase = {
common: Record<string, unknown>;
chrome: Record<string, unknown>;
firefox: Record<string, unknown>;
};
const originalManifest = readJsonFile('./src/manifest.json') as {
common: Record<string, unknown>;
v2: ManifestBase;
v3: ManifestBase;
};
const ManifestVersion =
process.env.TARGET_BROWSER === 'chrome' && isProduction ? 'v3' : 'v2';
const BrowserName =
process.env.TARGET_BROWSER === 'chrome' ? 'chrome' : 'firefox';
const commonManifest = originalManifest.common;
const manifest = {
version: '2.0.0',
author: packageJson.author,
version_name: packageJson.dependencies?.rrweb?.replace('^', ''),
...commonManifest,
};
Object.assign(
manifest,
originalManifest[ManifestVersion].common,
originalManifest[ManifestVersion][BrowserName],
);
return manifest;
},
browser: process.env.TARGET_BROWSER,
webExtConfig: {
startUrl: ['github.com/rrweb-io/rrweb'],
watchIgnored: ['*.md', '*.log'],
},
additionalInputs: ['pages/index.html', 'content/inject.ts'],
}),
// https://github.com/aklinker1/vite-plugin-web-extension/issues/50#issuecomment-1317922947
// transfer inject.ts to iife format to avoid error
useSpecialFormat(
[path.resolve(__dirname, 'src/content/inject.ts')],
'iife',
),
process.env.ZIP === 'true' &&
zip({
inDir: `dist/${process.env.TARGET_BROWSER || 'chrome'}`,
outDir: 'dist',
outFileName: `${process.env.TARGET_BROWSER || 'chrome'}.zip`,
}),
],
resolve: {
alias: {
'~': path.resolve(__dirname, './src'),
},
},
});