记一次 rollup 打包代码缺失问题

前言

记一次 rollup 打包代码缺失问题

正文

起因是公司使用了一个名为 @elastic/apm-rum-core 的库

该库的作用可以理解为上报用户的操作,比如点击了什么按钮,发起了什么请求等等

官方的文档:Introduction | APM Real User Monitoring JavaScript Agent Reference [5.x] | Elastic

在源码中,有这么一个 patchAll 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { patchXMLHttpRequest } from './xhr-patch'
import { patchFetch } from './fetch-patch'
import { patchHistory } from './history-patch'
import { patchEventTarget } from './event-target-patch'
import EventHandler from '../event-handler'
import { HISTORY, FETCH, XMLHTTPREQUEST, EVENT_TARGET } from '../constants'

var patchEventHandler = new EventHandler()
var alreadyPatched = false

function patchAll() {
if (!alreadyPatched) {
alreadyPatched = true
patchXMLHttpRequest(function (event, task) {
patchEventHandler.send(XMLHTTPREQUEST, [event, task])
})
patchFetch(function (event, task) {
patchEventHandler.send(FETCH, [event, task])
})
patchHistory(function (event, task) {
patchEventHandler.send(HISTORY, [event, task])
})
patchEventTarget(function (event, task) {
patchEventHandler.send(EVENT_TARGET, [event, task])
})
}

return patchEventHandler
}

export { patchAll, patchEventHandler }

其中这个方法使用了 patchEventTarget 来包装 addEventListenerremoveEventListener 这两个方法

但是很奇怪的是在开发环境下代码没有问题,但是打包之后事件监听的包装效果就不存在了

后面分析打包后的代码发现是 patchEventTarget 这个函数被删除了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function patchAll() {
if (!alreadyPatched) {
alreadyPatched = true
patchXMLHttpRequest(function (event, task) {
patchEventHandler.send(XMLHTTPREQUEST, [event, task])
})
patchFetch(function (event, task) {
patchEventHandler.send(FETCH, [event, task])
})
patchHistory(function (event, task) {
patchEventHandler.send(HISTORY, [event, task])
})
// patchEventTarget 函数消失
}

return patchEventHandler
}

所以建了一个 demo 最小化复现这个现象

Dedicatus546 / rollup-build-demo

在关闭 treeshake 之后,该现象消失,但是很明显即使开启 treeshake 功能, patchEventTarget 也不应该被优化掉的

另一个很有意思的是如果我们在 patchAll 源码中加入一个 console.log 来引用 patchEventTarget ,那么代码就能正常地打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ...

function patchAll() {
if (!alreadyPatched) {
alreadyPatched = true
patchXMLHttpRequest(function (event, task) {
patchEventHandler.send(XMLHTTPREQUEST, [event, task])
})
patchFetch(function (event, task) {
patchEventHandler.send(FETCH, [event, task])
})
patchHistory(function (event, task) {
patchEventHandler.send(HISTORY, [event, task])
})
patchEventTarget(function (event, task) {
patchEventHandler.send(EVENT_TARGET, [event, task])
})
// 加入一个 console
console.log(patchEventTarget)
}

return patchEventHandler
}

export { patchAll, patchEventHandler }

或者在 patchEventTarget 函数内加入一个随意的 console.log ,也能正常地打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// ...

export function patchEventTarget(callback) {
if (!window.EventTarget) {
return
}

// 加入一个 console
console.log('hello world!')

var proto = window.EventTarget.prototype
var nativeAddEventListener = proto[ADD_EVENT_LISTENER_STR]
var nativeRemoveEventListener = proto[REMOVE_EVENT_LISTENER_STR]

function findTaskIndex(existingTasks, eventType, listenerFn, capture) {
// ...
}

function isCapture(options) {
// ...
}

function createListenerWrapper(target, eventType, listenerFn, options) {
// ...
}

function getWrappingFn(target, eventType, listenerFn, options) {
// ...
}

proto[ADD_EVENT_LISTENER_STR] = function (eventType, listenerFn, optionsOrCapture) {
// ...
}

proto[REMOVE_EVENT_LISTENER_STR] = function (eventType, listenerFn, optionsOrCapture) {
// ...
}
}

后记

已经给 vite 提了一个 issue 了,不过其实应该给 rollupissue

some code disappeared when build project

趁着写这篇帖子,也给 rollup 提了个 issue

som code in @elastic/apm-rum-core disappear when build