Files
rrweb/src/types.ts
Eoghan Murray 6728d12b3c Add a slimDOM option to strip out unnecessary parts of the DOM (#36)
* Add a `slimDOM` option to strip out unnecessary parts of the DOM in terms of replay

 - <script> tags in the <head> take up unnecessary storage space and are often injected semi randomly to become a source of unnecessary variation between recordings of the same thing
 - comment tags can be stripped out without affecting display
 - future: this option could also turn on more aggressive stripping, e.g. elements that are hidden by CSS (assuming we can handle them becoming visible after mutation events)

* Mark nodes ignored due to slimDOM option, so that they can also be ignored by the mutation observer in rrweb

* Introducing the `ignored` attribute violates the `serializedNodeWithId` type

* slimDOM: Strip out whitespace nodes from <head> element as they have no effect but take up space

 - these would otherwise have to be merged after <script> elements are removed; for statcounter usecase, removing
   <script> elements is no good if there is still a trace of their presence due to the white space (and hence a variant <head> node is still produced)
 - I explored a more radical stripping of all white space nodes, but there is a problem if parent node is <pre> or otherwise rendered with `white-space: pre` and similar.
   detecting applied styles with getComputedStyle would be very expensive (I haven't measured it though)

* Export IGNORED_NODE as a constant instead of relying on the hard-to-grok `-2`

* Remove <link rel=preload as=script> which are similarly as useless as <script> tags

* Make slimDOM configurable with the expecations that `slimDOMOptions: true` will only enable non-destructive options (so not all options may be turned on)

* Expand slimDOM to add options to remove more elements from the <head> that should not be necessary in the replayer context
2020-09-20 13:00:44 +08:00

103 lines
1.8 KiB
TypeScript

export enum NodeType {
Document,
DocumentType,
Element,
Text,
CDATA,
Comment,
}
export type documentNode = {
type: NodeType.Document;
childNodes: serializedNodeWithId[];
};
export type documentTypeNode = {
type: NodeType.DocumentType;
name: string;
publicId: string;
systemId: string;
};
export type attributes = {
[key: string]: string | number | boolean;
};
export type elementNode = {
type: NodeType.Element;
tagName: string;
attributes: attributes;
childNodes: serializedNodeWithId[];
isSVG?: true;
needBlock?: boolean;
};
export type textNode = {
type: NodeType.Text;
textContent: string;
isStyle?: true;
};
export type cdataNode = {
type: NodeType.CDATA;
textContent: '';
};
export type commentNode = {
type: NodeType.Comment;
textContent: string;
};
export type serializedNode =
| documentNode
| documentTypeNode
| elementNode
| textNode
| cdataNode
| commentNode;
export type serializedNodeWithId = serializedNode & { id: number };
export type tagMap = {
[key: string]: string;
};
export interface INode extends Node {
__sn: serializedNodeWithId;
}
export type idNodeMap = {
[key: number]: INode;
};
export type MaskInputOptions = Partial<{
color: boolean;
date: boolean;
'datetime-local': boolean;
email: boolean;
month: boolean;
number: boolean;
range: boolean;
search: boolean;
tel: boolean;
text: boolean;
time: boolean;
url: boolean;
week: boolean;
// unify textarea and select element with text input
textarea: boolean;
select: boolean;
}>;
export type SlimDOMOptions = Partial<{
script: boolean;
comment: boolean;
headFavicon: boolean;
headWhitespace: boolean;
headMetaDescKeywords: boolean;
headMetaSocial: boolean;
headMetaRobots: boolean;
headMetaHttpEquiv: boolean;
headMetaAuthorship: boolean;
headMetaVerification: boolean;
}>;