背景
基于vue-cli 开发的自定义组件 A 被另外一个ssr 项目引用
A 通过默认命令打包 生成 dist/A.umd.js 和dist/A.common.js
package.json 设置 main 为 dist/A.umd.js
表现
搜索服务 出现告警 查询系统监控发现服务 因为内存暴涨在不断重启
内存泄漏严重
调查
1.比对最近提交的代码 在发现A的使用会导致内存泄露以后 想查出
2.该组件 通过webpack 打包进入服务端渲染的vue-server-bundle.json中
3.删除该组件 内存泄露修复
测试重现
1.组件在webpack 配置了nodeExternals whitelist 打包进项目中 内存泄露
2.组件main 设置为 umd 或者commonjs 在上述条件下都会引起内存泄露
3.组件 直接通过 nodeExternals 过滤 不打包进vue-server-bundle.json 在ssr node 项目中 npm install 组件A 运行 不会内存泄露
4.nuxt 调用该组件 没有内存泄露
分析原因
<template>
<i />
</template>
<script>
export default {
props: {
test: {
type: Number
}
}
}
</script>
将组件最小化 然后进行打包 之后分析打包结果 发现内存引入了针对Number的polyfill
总结原因
- vue-cli 默认的 useBuiltIns 是 usage
- 组件中用了 Number 做 props 的 validation,Number 的 polyfill 被打包到 package 中
- 这个 polyfill 对global进行了定义
- 并且这个组件被加到了 webpack 的 externals whitelist里面,代码会 build 到 vue-server-bundle.json 中
- SSR 的运行环境是 runInNewContext: true,每次请求进来之后都会重新创建上下文
修复
1.组件服务端安装 不要打包到vue-server-bundle.json中
2.打包组件的时候 babel 配置中使用 useBuiltIns:false不要将polyfill 打包到代码当中去 调用方自己使用polyfill
3.打包组件的时候 如果是为了提供给服务端渲染使用 babel 配置 @vue/app 并且 node:current polyfill 也不会打包进去
引申
babelrc babel.config.js 加载逻辑: segmentfault.com/a/119000001…