mixpanel-browser 2.74.0 → 2.76.0
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/.claude/settings.local.json +3 -1
- package/.github/workflows/integration-tests.yml +2 -2
- package/.github/workflows/unit-tests.yml +3 -3
- package/CHANGELOG.md +15 -0
- package/README.md +2 -2
- package/build.sh +10 -8
- package/dist/async-modules/mixpanel-recorder-bIS4LMGd.js +23595 -0
- package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js +2 -0
- package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js.map +1 -0
- package/dist/async-modules/mixpanel-targeting-BcAPS-Mz.js +2520 -0
- package/dist/async-modules/mixpanel-targeting-VOeN7RWY.min.js +2 -0
- package/dist/async-modules/mixpanel-targeting-VOeN7RWY.min.js.map +1 -0
- package/dist/mixpanel-core.cjs.d.ts +68 -0
- package/dist/mixpanel-core.cjs.js +802 -337
- package/dist/mixpanel-recorder.js +828 -40
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-targeting.js +2520 -0
- package/dist/mixpanel-targeting.min.js +2 -0
- package/dist/mixpanel-targeting.min.js.map +1 -0
- package/dist/mixpanel-with-async-modules.cjs.d.ts +590 -0
- package/dist/mixpanel-with-async-modules.cjs.js +9867 -0
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +68 -0
- package/dist/mixpanel-with-async-recorder.cjs.js +802 -337
- package/dist/mixpanel-with-recorder.d.ts +68 -0
- package/dist/mixpanel-with-recorder.js +1591 -343
- package/dist/mixpanel-with-recorder.min.d.ts +68 -0
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +68 -0
- package/dist/mixpanel.amd.js +2124 -345
- package/dist/mixpanel.cjs.d.ts +68 -0
- package/dist/mixpanel.cjs.js +2124 -345
- package/dist/mixpanel.globals.js +802 -337
- package/dist/mixpanel.min.js +185 -175
- package/dist/mixpanel.module.d.ts +68 -0
- package/dist/mixpanel.module.js +2124 -345
- package/dist/mixpanel.umd.d.ts +68 -0
- package/dist/mixpanel.umd.js +2124 -345
- package/dist/rrweb-bundled.js +119 -5
- package/dist/rrweb-compiled.js +116 -5
- package/logo.svg +5 -0
- package/package.json +5 -3
- package/rollup.config.mjs +189 -40
- package/src/autocapture/index.js +10 -27
- package/src/config.js +9 -3
- package/src/flags/index.js +269 -9
- package/src/index.d.ts +68 -0
- package/src/loaders/loader-module.js +1 -0
- package/src/mixpanel-core.js +83 -109
- package/src/recorder/index.js +2 -1
- package/src/recorder/recorder.js +5 -1
- package/src/recorder/rrweb-network-plugin.js +649 -0
- package/src/recorder/session-recording.js +31 -11
- package/src/recorder-manager.js +216 -0
- package/src/request-batcher.js +1 -1
- package/src/targeting/event-matcher.js +42 -0
- package/src/targeting/index.js +11 -0
- package/src/targeting/loader.js +36 -0
- package/src/utils.js +14 -9
- package/testServer.js +55 -0
- /package/src/loaders/{loader-module-with-async-recorder.js → loader-module-with-async-modules.js} +0 -0
package/rollup.config.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import alias from '@rollup/plugin-alias';
|
|
2
2
|
import closureCompiler from '@ampproject/rollup-plugin-closure-compiler';
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
3
4
|
import fs from 'fs';
|
|
4
5
|
import path from 'path';
|
|
5
6
|
import esbuild from 'rollup-plugin-esbuild';
|
|
@@ -7,21 +8,52 @@ import nodeResolve from '@rollup/plugin-node-resolve';
|
|
|
7
8
|
import swc from '@rollup/plugin-swc';
|
|
8
9
|
import browserTestBuilds from './tests/browser/client/rollup.config.mjs';
|
|
9
10
|
|
|
11
|
+
// Capture the hash of async-loaded bundles so we can inject the correct filenames into the main build
|
|
12
|
+
const asyncBundleManifest = {};
|
|
13
|
+
|
|
10
14
|
const COMPILED_RRWEB_PATH = `build/rrweb-compiled.js`;
|
|
11
15
|
const BUNDLED_RRWEB_PATH = `build/rrweb-bundled.js`;
|
|
12
16
|
|
|
17
|
+
const ASYNC_MODULE_BUILD_PATH = `build/async-modules`;
|
|
18
|
+
const RECORDER_BUNDLE_NAME = `mixpanel_recorder`;
|
|
19
|
+
const RECORDER_MIN_BUNDLE_NAME = `mixpanel_recorder_min`;
|
|
20
|
+
const TARGETING_BUNDLE_NAME = `mixpanel_targeting`;
|
|
21
|
+
const TARGETING_MIN_BUNDLE_NAME = `mixpanel_targeting_min`;
|
|
22
|
+
|
|
23
|
+
|
|
13
24
|
// Delete output files at build start so build errors don't silently use stale files
|
|
25
|
+
let hasCleanedOnFull = false;
|
|
14
26
|
const cleanOnRebuild = () => {
|
|
15
|
-
let
|
|
27
|
+
let filesToClean = [];
|
|
16
28
|
return {
|
|
17
29
|
name: `clean-on-rebuild`,
|
|
18
30
|
options(opts) {
|
|
19
31
|
const outputs = Array.isArray(opts.output) ? opts.output : [opts.output];
|
|
20
|
-
|
|
32
|
+
filesToClean = outputs.flatMap(o => {
|
|
33
|
+
if (o.file) {
|
|
34
|
+
return [o.file];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (o.dir && o.entryFileNames) {
|
|
38
|
+
if (!fs.existsSync(o.dir)) return [];
|
|
39
|
+
|
|
40
|
+
// match against regexes like mixpanel-recorder-[hash].js to find the actual output file(s) to clean up
|
|
41
|
+
const regex = new RegExp(`^` + o.entryFileNames.replace(/\./g, `\\.`).replace(`[hash]`, `.+`));
|
|
42
|
+
return fs.readdirSync(o.dir).filter(f => regex.test(f)).map(f => path.join(o.dir, f));
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
});
|
|
21
46
|
},
|
|
22
47
|
buildStart() {
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
if (process.env.FULL && !hasCleanedOnFull) {
|
|
49
|
+
if (fs.existsSync(`build`)) {
|
|
50
|
+
fs.rmSync(`build`, {recursive: true});
|
|
51
|
+
}
|
|
52
|
+
hasCleanedOnFull = true;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const file of filesToClean) {
|
|
25
57
|
if (fs.existsSync(file)) {
|
|
26
58
|
fs.unlinkSync(file);
|
|
27
59
|
}
|
|
@@ -30,10 +62,53 @@ const cleanOnRebuild = () => {
|
|
|
30
62
|
};
|
|
31
63
|
};
|
|
32
64
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
65
|
+
// Capture the resolved (hashed) output filenames from recorder/targeting builds.
|
|
66
|
+
// Stores them in `asyncBundleManifest` so `injectAsyncBundleNames` can inject them into the main build.
|
|
67
|
+
const writeToManifest = () => ({
|
|
68
|
+
name: `write-to-manifest`,
|
|
69
|
+
generateBundle(options, bundle) {
|
|
70
|
+
for (const chunk of Object.values(bundle)) {
|
|
71
|
+
if (chunk.type === `chunk`) {
|
|
72
|
+
asyncBundleManifest[options.name] = chunk.fileName;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Replace __MP_*__ placeholders in src/config.js with build-time values.
|
|
79
|
+
// For the main library build (which runs after), they will be the real hashed filenames.
|
|
80
|
+
const injectAsyncBundleNames = () => ({
|
|
81
|
+
name: `inject-async-bundle-names`,
|
|
82
|
+
renderChunk(code, _chunk, outputOptions) {
|
|
83
|
+
const isMinified = outputOptions.file && outputOptions.file.endsWith(`.min.js`);
|
|
84
|
+
|
|
85
|
+
let recorderBundleName = RECORDER_BUNDLE_NAME;
|
|
86
|
+
let targetingBundleName = TARGETING_BUNDLE_NAME;
|
|
87
|
+
if (isMinified) {
|
|
88
|
+
recorderBundleName = RECORDER_MIN_BUNDLE_NAME;
|
|
89
|
+
targetingBundleName = TARGETING_MIN_BUNDLE_NAME;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!asyncBundleManifest[recorderBundleName] || !asyncBundleManifest[targetingBundleName]) {
|
|
93
|
+
throw new Error(`Async bundle names not found in manifest. Manifest contents: ${JSON.stringify(asyncBundleManifest)}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const replaced = code
|
|
97
|
+
.replace(`__MP_RECORDER_FILENAME__`, asyncBundleManifest[recorderBundleName])
|
|
98
|
+
.replace(`__MP_TARGETING_FILENAME__`, asyncBundleManifest[targetingBundleName]);
|
|
99
|
+
return { code: replaced, map: null };
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const withBasePlugins = (builds) => builds.map((build) => {
|
|
104
|
+
return {
|
|
105
|
+
...build,
|
|
106
|
+
plugins: [
|
|
107
|
+
cleanOnRebuild(),
|
|
108
|
+
...(build.plugins || [])
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
});
|
|
37
112
|
|
|
38
113
|
const aliasRrweb = () => alias({
|
|
39
114
|
entries: [
|
|
@@ -68,6 +143,96 @@ const COMMON_CLOSURE_FLAGS = {
|
|
|
68
143
|
|
|
69
144
|
const MINIFY = process.env.MINIFY || process.env.FULL;
|
|
70
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Async bundles for the recorder and targeting modules.
|
|
148
|
+
*
|
|
149
|
+
* These are loaded on-demand by the main library at runtime via script injection.
|
|
150
|
+
* Filenames include a content hash so the main build can reference an exact, immutable
|
|
151
|
+
* bundle — guaranteeing the async module matches what the library expects.
|
|
152
|
+
* The hash is captured in `asyncBundleManifest` and injected into the main build
|
|
153
|
+
* via `injectAsyncBundleNames`.
|
|
154
|
+
*
|
|
155
|
+
* We also produce non-hashed "legacy" versions of each bundle for backward compatibility
|
|
156
|
+
* with customers who proxy specific filenames from the Mixpanel CDN.
|
|
157
|
+
*/
|
|
158
|
+
const ASYNC_BUNDLE_BUILDS = [
|
|
159
|
+
// Recorder bundle (wraps rrweb)
|
|
160
|
+
{
|
|
161
|
+
input: `src/recorder/index.js`,
|
|
162
|
+
output: [
|
|
163
|
+
{
|
|
164
|
+
dir: ASYNC_MODULE_BUILD_PATH,
|
|
165
|
+
entryFileNames: `mixpanel-recorder-[hash].js`,
|
|
166
|
+
name: RECORDER_BUNDLE_NAME,
|
|
167
|
+
format: `iife`,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
file: `build/mixpanel-recorder.js`,
|
|
171
|
+
name: `legacy_recorder_bundle`,
|
|
172
|
+
format: `iife`,
|
|
173
|
+
},
|
|
174
|
+
...(MINIFY
|
|
175
|
+
? [
|
|
176
|
+
{
|
|
177
|
+
dir: ASYNC_MODULE_BUILD_PATH,
|
|
178
|
+
entryFileNames: `mixpanel-recorder-[hash].min.js`,
|
|
179
|
+
name: RECORDER_MIN_BUNDLE_NAME,
|
|
180
|
+
format: `iife`,
|
|
181
|
+
plugins: [esbuild({target: `es5`, minify: true, sourceMap: true})],
|
|
182
|
+
sourcemap: true,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
file: `build/mixpanel-recorder.min.js`,
|
|
186
|
+
name: `legacy_recorder_min_bundle`,
|
|
187
|
+
format: `iife`,
|
|
188
|
+
plugins: [esbuild({target: `es5`, minify: true, sourceMap: true})],
|
|
189
|
+
sourcemap: true,
|
|
190
|
+
},
|
|
191
|
+
]
|
|
192
|
+
: []),
|
|
193
|
+
],
|
|
194
|
+
plugins: [aliasRrweb(), writeToManifest()],
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
// Targeting bundle (feature flags / experiments)
|
|
198
|
+
{
|
|
199
|
+
input: `src/targeting/index.js`,
|
|
200
|
+
output: [
|
|
201
|
+
{
|
|
202
|
+
dir: ASYNC_MODULE_BUILD_PATH,
|
|
203
|
+
entryFileNames: `mixpanel-targeting-[hash].js`,
|
|
204
|
+
name: TARGETING_BUNDLE_NAME,
|
|
205
|
+
format: `iife`,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
file: `build/mixpanel-targeting.js`,
|
|
209
|
+
name: `legacy_targeting_bundle`,
|
|
210
|
+
format: `iife`,
|
|
211
|
+
},
|
|
212
|
+
...(MINIFY
|
|
213
|
+
? [
|
|
214
|
+
{
|
|
215
|
+
dir: ASYNC_MODULE_BUILD_PATH,
|
|
216
|
+
entryFileNames: `mixpanel-targeting-[hash].min.js`,
|
|
217
|
+
name: TARGETING_MIN_BUNDLE_NAME,
|
|
218
|
+
format: `iife`,
|
|
219
|
+
plugins: [esbuild({target: `es5`, minify: true, sourceMap: true})],
|
|
220
|
+
sourcemap: true,
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
file: `build/mixpanel-targeting.min.js`,
|
|
224
|
+
name: `legacy_targeting_min_bundle`,
|
|
225
|
+
format: `iife`,
|
|
226
|
+
plugins: [esbuild({target: `es5`, minify: true, sourceMap: true})],
|
|
227
|
+
sourcemap: true,
|
|
228
|
+
},
|
|
229
|
+
]
|
|
230
|
+
: []),
|
|
231
|
+
],
|
|
232
|
+
plugins: [commonjs(), nodeResolve({browser: true}), writeToManifest()],
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
|
|
71
236
|
// Main builds used to develop / iterate quickly
|
|
72
237
|
const MAIN_BUILDS = [
|
|
73
238
|
{
|
|
@@ -91,30 +256,7 @@ const MAIN_BUILDS = [
|
|
|
91
256
|
plugins: [swc({swc: {jsc: {target: `es5`}}})]
|
|
92
257
|
},
|
|
93
258
|
|
|
94
|
-
|
|
95
|
-
// rrweb uses esbuild to minify, so do that here as well
|
|
96
|
-
{
|
|
97
|
-
input: `src/recorder/index.js`,
|
|
98
|
-
output: [
|
|
99
|
-
{
|
|
100
|
-
file: `build/mixpanel-recorder.js`,
|
|
101
|
-
name: `mixpanel_recorder`,
|
|
102
|
-
format: `iife`,
|
|
103
|
-
},
|
|
104
|
-
...(MINIFY
|
|
105
|
-
? [
|
|
106
|
-
{
|
|
107
|
-
file: `build/mixpanel-recorder.min.js`,
|
|
108
|
-
name: `mixpanel_recorder`,
|
|
109
|
-
format: `iife`,
|
|
110
|
-
plugins: [esbuild({target: `es5`, minify: true, sourceMap: true})],
|
|
111
|
-
sourcemap: true,
|
|
112
|
-
},
|
|
113
|
-
]
|
|
114
|
-
: []),
|
|
115
|
-
],
|
|
116
|
-
plugins: [aliasRrweb()],
|
|
117
|
-
},
|
|
259
|
+
...ASYNC_BUNDLE_BUILDS,
|
|
118
260
|
|
|
119
261
|
// IIFE main mixpanel build
|
|
120
262
|
{
|
|
@@ -136,6 +278,7 @@ const MAIN_BUILDS = [
|
|
|
136
278
|
: []),
|
|
137
279
|
],
|
|
138
280
|
plugins: [
|
|
281
|
+
injectAsyncBundleNames(),
|
|
139
282
|
nodeResolve({
|
|
140
283
|
browser: true,
|
|
141
284
|
main: true,
|
|
@@ -203,8 +346,7 @@ const ALL_BUILDS = [
|
|
|
203
346
|
],
|
|
204
347
|
},
|
|
205
348
|
|
|
206
|
-
|
|
207
|
-
// Modules builds that are bundled with the recorder
|
|
349
|
+
// Modules builds that are bundled with the recorder and targeting
|
|
208
350
|
{
|
|
209
351
|
input: `src/loaders/loader-module.js`,
|
|
210
352
|
output: [
|
|
@@ -230,6 +372,7 @@ const ALL_BUILDS = [
|
|
|
230
372
|
},
|
|
231
373
|
],
|
|
232
374
|
plugins: [
|
|
375
|
+
commonjs(),
|
|
233
376
|
aliasRrweb(),
|
|
234
377
|
nodeResolve({
|
|
235
378
|
browser: true,
|
|
@@ -240,7 +383,6 @@ const ALL_BUILDS = [
|
|
|
240
383
|
],
|
|
241
384
|
},
|
|
242
385
|
|
|
243
|
-
|
|
244
386
|
// Alternative CJS builds without recorder
|
|
245
387
|
{
|
|
246
388
|
input: `src/loaders/loader-module-core.js`,
|
|
@@ -262,8 +404,14 @@ const ALL_BUILDS = [
|
|
|
262
404
|
],
|
|
263
405
|
},
|
|
264
406
|
{
|
|
265
|
-
input: `src/loaders/loader-module-with-async-
|
|
407
|
+
input: `src/loaders/loader-module-with-async-modules.js`,
|
|
266
408
|
output: [
|
|
409
|
+
{
|
|
410
|
+
file: `build/mixpanel-with-async-modules.cjs.js`,
|
|
411
|
+
name: `mixpanel`,
|
|
412
|
+
format: `cjs`,
|
|
413
|
+
},
|
|
414
|
+
// Backward compatibility: keep old output filename for existing users
|
|
267
415
|
{
|
|
268
416
|
file: `build/mixpanel-with-async-recorder.cjs.js`,
|
|
269
417
|
name: `mixpanel`,
|
|
@@ -271,6 +419,7 @@ const ALL_BUILDS = [
|
|
|
271
419
|
},
|
|
272
420
|
],
|
|
273
421
|
plugins: [
|
|
422
|
+
injectAsyncBundleNames(),
|
|
274
423
|
aliasRrweb(),
|
|
275
424
|
nodeResolve({
|
|
276
425
|
browser: true,
|
|
@@ -280,9 +429,9 @@ const ALL_BUILDS = [
|
|
|
280
429
|
copyTypes(),
|
|
281
430
|
],
|
|
282
431
|
},
|
|
283
|
-
|
|
284
|
-
...browserTestBuilds,
|
|
285
432
|
];
|
|
286
433
|
|
|
287
|
-
const
|
|
288
|
-
|
|
434
|
+
const srcBuilds = process.env.FULL ? ALL_BUILDS : MAIN_BUILDS;
|
|
435
|
+
const builds = [...srcBuilds, ...browserTestBuilds];
|
|
436
|
+
|
|
437
|
+
export default withBasePlugins(builds);
|
package/src/autocapture/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _, document, safewrap, safewrapClass } from '../utils';
|
|
1
|
+
import { _, document, safewrap, safewrapClass, urlMatchesRegexList } from '../utils';
|
|
2
2
|
import { window } from '../window';
|
|
3
3
|
import {
|
|
4
4
|
getPolyfillScrollEndFunction, getPropsForDOMEvent, logger, minDOMApisSupported,
|
|
@@ -112,27 +112,15 @@ Autocapture.prototype.getConfig = function(key) {
|
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
Autocapture.prototype.currentUrlBlocked = function() {
|
|
115
|
-
var i;
|
|
116
115
|
var currentUrl = _.info.currentUrl();
|
|
117
116
|
|
|
118
117
|
var allowUrlRegexes = this.getConfig(CONFIG_ALLOW_URL_REGEXES) || [];
|
|
119
118
|
if (allowUrlRegexes.length) {
|
|
120
119
|
// we're using an allowlist, only track if current URL matches
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (currentUrl.match(allowRegex)) {
|
|
126
|
-
allowed = true;
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
} catch (err) {
|
|
130
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (!allowed) {
|
|
135
|
-
// wasn't allowed by any regex
|
|
120
|
+
try {
|
|
121
|
+
return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
logger.critical('Error while checking block URL regexes: ', err);
|
|
136
124
|
return true;
|
|
137
125
|
}
|
|
138
126
|
}
|
|
@@ -142,17 +130,12 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
142
130
|
return false;
|
|
143
131
|
}
|
|
144
132
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} catch (err) {
|
|
151
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
133
|
+
try {
|
|
134
|
+
return urlMatchesRegexList(currentUrl, blockUrlRegexes);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
logger.critical('Error while checking block URL regexes: ', err);
|
|
137
|
+
return true;
|
|
154
138
|
}
|
|
155
|
-
return false;
|
|
156
139
|
};
|
|
157
140
|
|
|
158
141
|
Autocapture.prototype.pageviewTrackingConfig = function() {
|
package/src/config.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
var Config = {
|
|
1
|
+
export var Config = {
|
|
2
2
|
DEBUG: false,
|
|
3
|
-
LIB_VERSION: '2.
|
|
3
|
+
LIB_VERSION: '2.76.0'
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Window global names for async modules
|
|
7
|
+
export var TARGETING_GLOBAL_NAME = '__mp_targeting';
|
|
8
|
+
export var RECORDER_GLOBAL_NAME = '__mp_recorder';
|
|
9
|
+
|
|
10
|
+
// Constants that are injected at build-time for the names of async modules.
|
|
11
|
+
export var RECORDER_FILENAME = '__MP_RECORDER_FILENAME__';
|
|
12
|
+
export var TARGETING_FILENAME = '__MP_TARGETING_FILENAME__';
|