firebase-js-sdk 包体积分析工具指南:Modular Export Binary Size Calculator 使用与实现原理 开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载本篇技术指南围绕 firebase-js-sdk 仓库中的体积分析工具 repo-scripts/size-analysis 展开系统讲解该工具的两大核心能力逐个分析某个 Firebase 包中每个导出符号export的二进制体积以及分析预定义 Bundle 的打包体积Bundle 定义是一组来自不同 Firebase 包的导入组合用于模拟真实业务场景例如“一次 Google 登录 一次 Firestore 读取”。读完本文你将掌握该工具的完整 CLI 命令、三个可编程 API、报告 JSON 结构并能从源码层面理解它如何借助 Rollup/Webpack 的 Tree Shaking、Terser 压缩与 TypeScript 类型分析实现精确的体积拆解。工具概览它能解决什么问题Firebase 的模块化 SDK 主张“按需导入”但开发者往往不清楚每个 API 到底会引入多少代码、携带多少依赖。firebase-size-analysis工具见 package.json把这个问题量化提供两类分析单个导出分析Modular Export Analysis针对某个 package如firebase/auth枚举其.d.ts中定义的全部公开导出逐一测量引入该导出后被打包进最终产物的代码字节数并区分“仅该导出自身代码”与“连同外部依赖一并计入”两种口径。Bundle 分析Bundle Analysis把多个包中的若干导入组合成一个模拟真实用例的 bundle 定义文件然后分别用 Rollup 和 Webpack 实际打包、压缩输出原始大小与 gzip 大小用于评估“实现某个功能最低需要多少字节”。工具以 TypeScript 编写CLI 入口为 cli.ts底层分析逻辑集中在 analysis-helper.ts 与 bundle-analysis.ts可通过命令行使用也可作为库在 Node.js 中编程调用。分析单个导出的体积CLI 用法命令行参数模块导出分析使用cli.ts的默认子命令不带子命令名支持的 flags 如下完整定义见 cli.tsFlag别名类型说明--version—boolean显示版本号--inputModule--imarray要分析的模块名列表例如--inputModule firebase/functions firebase/auth多个模块以空格分隔--inputDtsFile--ifstringAdhoc 分析的入口传入一个.d.ts定义文件的路径--inputBundleFile--ibstringAdhoc 分析的入口传入一个 bundle 文件路径必须与--inputDtsFile同时指定--output-ostring报告输出位置分析模块时是目录路径Adhoc 分析时是文件路径CLI 中为必填项--help—boolean显示帮助场景一分析一个或多个 Firebase 包在仓库根目录执行注意ts-node-script是仓库 scripts 中约定的运行方式cd repo-scripts/size-analysis ts-node-script cli.ts --im firebase/app firebase/auth -o path to output DIRECTORY该命令会为firebase/app和firebase/auth分别生成报告文件写入输出目录。从 package-analysis.ts 的源码看--inputModule提供的包名会与packages/*下每个子目录package.json的name字段做精确匹配argv.inputModule.includes(json.name)报告文件名格式为模块名-dependencies.json。场景二分析全部 Firebase 包不指定--inputModule时工具会遍历仓库packages/*下所有符合条件的模块ts-node-script cli.ts -o path to output DIRECTORY源码 package-analysis.ts 展示了默认的模块筛选规则仅保留name以firebase开头、且不包含-compat与-types的包。也就是说compat 兼容层和纯类型包默认被排除在体积分析之外。场景三Adhoc 临时分析当目标产物不在packages/下、或你想分析任意一份.d.ts与其对应 bundle 时使用 adhoc 模式ts-node-script cli.ts --if path to dts file --ib path to bundle file -o path to output FILE注意两点约束源码见 package-analysis.ts--if与--ib必须成对出现只给其一而缺少另一个会抛出INVALID_FLAG_COMBINATION“Invalid command flag combinations!”错误adhoc 报告只能写入文件不能写目录。参数校验与常见错误工具内置了丰富的错误码定义于 analysis-helper.ts便于定位问题错误码含义INVALID_FLAG_COMBINATION--if/--ib未成对出现等非法参数组合BUNDLE_FILE_DOES_NOT_EXIST模块缺少 bundle 文件module/main字段均未定义DTS_FILE_DOES_NOT_EXIST模块缺少.d.ts文件OUTPUT_DIRECTORY_REQUIRED期望输出目录但给出的路径是文件OUTPUT_FILE_REQUIRED期望输出文件但给出的路径是目录INPUT_FILE_DOES_NOT_EXIST输入文件不存在INPUT_DTS_FILE_DOES_NOT_EXIST输入的.d.ts文件不存在INPUT_BUNDLE_FILE_DOES_NOT_EXIST输入的 bundle 文件不存在FILE_PARSING_ERRORJS 文件解析失败PKG_JSON_DOES_NOT_EXIST模块目录下没有package.jsonTYPINGS_FIELD_NOT_DEFINED模块的package.json未定义typings字段其中OUTPUT_DIRECTORY_REQUIRED与OUTPUT_FILE_REQUIRED的判定逻辑在 writeReportToDirectory 与 writeReportToFile 中前者检查路径必须已是目录后者检查路径必须不是目录必要时会递归创建父目录。generateReportForModuleanalysis-helper.ts则要求模块必须声明typings字段否则拒绝分析——这是为了排除纯类型包。程序化 API在代码中调用分析能力工具的所有分析逻辑都被封装为可复用的异步函数可直接import使用均从 analysis-helper.ts 导出。async generateReportForModule(moduleLocation: string): PromiseReport为单个模块生成体积分析报告。moduleLocation传入 Firebase 模块的绝对路径源码中会读取该目录下的package.json通过typings字段定位.d.ts再通过module/main字段定位 bundle 文件try { const moduleLocation: string absolute/path/to/firebase/module; const report: Report await generateReportForModule(moduleLocation); console.log(report); } catch (error) { console.log(error); }值得注意的细节模块定位 bundle 时优先取package.json的module字段ESM 入口其次才回退到main字段CJS 入口逻辑见 retrieveBundleFileLocation。async generateReportForModules(moduleLocations: string[]): PromiseReport[]为一组模块递归生成报告数组中的每个元素是一个模块路径。递归时还会向下探测子模块例如firebase/firestore/memory但有两个限制条件见 traverseDirs子目录必须包含package.json且其中的generate-size-analysis-report字段必须为true才会被纳入分析递归深度默认限制为 1 层levelLimit传 1源码注释说明目前没有比这更深的子模块。try { const moduleLocations: string[] [...module1, ...module2]; const reports: Report[] await generateReportForModules(moduleLocations); console.log(reports); } catch (error) { console.log(error); }async generateReport(name: string, dtsFile: string, bundleFile: string): PromiseReportAdhoc 分析的编程版。name是显示在报告上的名称dtsFile是感兴趣的.d.ts定义文件的绝对路径bundleFile是对应定义文件的 bundle 绝对路径。函数会先对两个路径做path.resolve并检查文件是否存在然后调用 extractExports 提取公开 API再逐个导出计算体积try { const name: string adhoc; const dtsFile: string .../index.d.ts; const bundleFile: string .../index.esm2017.js; const report: Report await generateReport(name, dtsFile, bundleFile); console.log(report); } catch (error) { console.log(error); }报告数据结构读懂 JSON 输出单导出分析的报告类型为Report其结构见 analysis-helper.tsinterface MemberList { classes: string[]; functions: string[]; variables: string[]; enums: string[]; unknown: string[]; } interface ExportData { name: string; classes: string[]; functions: string[]; variables: string[]; enums: string[]; unknown: string[]; externals: { [key: string]: string[] }; // 该导出引入的外部依赖及符号 size: number; // 仅导出自身代码不含 firebase 外部依赖与 tslib的字节数 sizeWithExtDeps: number; // 连同外部依赖一并解析后打包的字节数 } interface Report { name: string; symbols: ExportData[]; }对每个导出符号报告会列出它引入的 classes / functions / variables / enums 顶层符号集合即经过 Tree Shaking 后真正进入产物的代码并用externals记录从哪些外部模块导入了哪些符号。size与sizeWithExtDeps两个数字分别对应“只看自己”与“连依赖一起算”两种口径是判断 API 体量最直观的指标。底层原理单个导出体积是如何算出来的这一节从 analysis-helper.ts 的源码还原完整链路理解它有助于你判断分析结果的可信边界。第一步提取公开 API 列表。extractExports 用 TypeScript 编译器创建 Program借助getExportsOfModule获取模块的全部导出再根据符号声明类型把每个导出归类为 function / class / variable / enum / unknown。它支持导出重命名export { tar as tarr }、先声明后导出export { foo as foo2 }、*重导出、重命名导入后重命名导出等复杂场景——对应的行为均被 size-analysis.test.ts 的测试用例覆盖。注意const enum会被主动排除因为常量枚举不会增加 bundle 体积且导入它会触发 Rollup 阶段报错。第二步逐个导出做 Tree Shaking。核心函数 extractDependenciesAndSize 对每个导出符号生成一行入口代码export { exportName } from bundle 文件绝对路径;随后用 Rollup 对该入口执行两次打包第一次解析全部外部依赖resolve插件配置mainFields: [module, main]配合commonjs()产出的代码用于计算sizeWithExtDeps第二次把所有firebase/*包和tslib声明为external不解析产出的代码用于计算size与提取顶层符号。第三步压缩并计量。两份产物都用 Terser 压缩mangle: { toplevel: true }、compress: false、去掉注释再以Buffer.byteLength(code, utf-8)计算字节数未解析外部依赖的产物还会用 TypeScript 的 AST 遍历extractAllTopLevelSymbols提取全部顶层符号分类并通过 extractExternalDependencies 解析 import 语句记录每个外部模块被引入了哪些符号含重命名导入、import * as命名空间导入、默认导入等形态。第四步汇总。buildJsonReport 遍历全部公开导出为每个导出执行上述流程最终拼装成Report由 writeReportToDirectory 以JSON.stringify(report, null, 4)写入-dependencies.json文件。Bundle 体积分析模拟真实业务场景Bundle 定义bundle definition是什么一个 bundle 定义就是一组来自不同 Firebase 包的导入组合用来模拟某个具体使用场景——例如 README 中提到的“支持 Google 登录并读取一次 Firestore”。定义文件是 JSON 数组存放在仓库的 bundle-definitions 目录下覆盖analytics、app-check、auth、database、firestore、firestore-lite、functions、messaging、performance、remote-config、storage等产品线。从 bundle-analysis.ts 的类型定义看bundle 定义由三部分组成namebundle 名称例如Read data oncedescription可选场景说明dependencies依赖数组每个元素含packageName包名如firebase或firebase/authversionOrTagnpm 版本或 tag省略时默认latest见 parseBundleDefinitionimports可以是字符串数组命名导入也可以是{ path, imports }形式的子模块导入对象数组。以 auth.json 中的GooglePopup场景为例{ name: GooglePopup, dependencies: [ { packageName: firebase, versionOrTag: latest, imports: [ { path: app, imports: [initializeApp] } ] }, { packageName: firebase, versionOrTag: latest, imports: [ { path: auth, imports: [ initializeAuth, indexedDBLocalPersistence, GoogleAuthProvider, signInWithPopup, browserPopupRedirectResolver, onAuthStateChanged ] } ] } ] }它等价于“初始化 App 配置 Auth 弹窗登录”Rollup 会按此生成入口文件并真实打包得到该场景的最小产物体积。firestore.json 中还能看到firestore/pipelines这类更深层子模块的导入写法。CLI 用法与参数Bundle 分析通过bundle子命令执行ts-node-script cli.ts bundle [FLAGs]参数定义见 cli.tsFlag别名取值默认值说明--input-i路径必填bundle 定义 JSON 文件的路径--mode-mnpm/localnpmnpm分析发布到 npm 的包local忽略定义中的版本分析仓库本地对应包--bundler-brollup/webpack/bothrollup使用哪种打包器创建 bundle--output-o路径./size-analysis-bundles.jsonbundle 分析结果输出位置--debug-dbooleanfalse调试模式在结果中输出额外数据npm 模式与 local 模式的差异两种模式的执行路径在 analyzeBundle 中分叉npm 模式先调用 setupTempProject 在临时目录生成一个package.json把 bundle 定义中的packageName/versionOrTag写为dependencies再执行npm install真实安装依赖随后以临时项目的node_modules作为解析根目录打包local 模式不安装任何依赖直接解析仓库本地node_modules中的对应包此时 bundle 定义中的版本号被忽略适合在 CI 中验证当前提交的代码体积。打包器的解析配置也因模式而异Rollup 通过moduleDirectories指定node_modules位置见 bundle/rollup.tsWebpack 通过resolve.modules指定见 bundle/webpack.ts两者都使用mainFields: [module, main]优先走 ESM 入口以便最大化 Tree Shaking 效果。入口文件如何生成createEntryFileContent 把 bundle 定义翻译成一段真实的入口源码普通命名导入生成export {symbol} from module子模块导入展开为export {symbol} from package/path。它还维护一个symbolsCache集合处理同名符号冲突——当多个模块导出同名符号时用symbol_随机数重命名createSymbolName避免打包报错。另外支持三种特殊导入标记SpecialImportdefault import生成import name from module并紧跟console.log(name)防止被 Tree Shaking 掉namespace import生成import * as name from module并同样用console.log保活side effect import生成裸import module表示只关心模块的副作用。结果与调试模式每个 bundle 的分析结果结构见 bundle-analysis.tsinterface BundleAnalysis { name: string; // bundle 定义中的名称 description: string; dependencies: BundleDependency[]; results: BundleAnalysisResult[]; // 每个 bundler 一条结果 } interface BundleAnalysisResult { bundler: rollup | webpack; size: number; // 压缩后字节数 gzipSize: number; // gzip 压缩后字节数由 gzip-size 计算见 util.ts debugInfo?: { pathToBundle?: string; // 未压缩产物路径 pathToMinifiedBundle?: string; // 压缩产物路径 dependencies?: MemberList; // 产物中的顶层符号列表 }; }体积计算链路为Rollup/Webpack 打包 → minifyTersermangle toplevel、compress: false→ calculateContentSizeBuffer.byteLength求字节数、gzip-size求 gzip 字节数。开启--debug后工具会在临时目录落盘原始与压缩后的 bundle 文件并额外提取产物顶层符号方便你人工核对“这些字节到底装了什么”。--bundler both时同一 bundle 会分别用 Rollup 与 Webpack 各打一次包报告中出现两条results可直接对比两个打包器在同等场景下的体积差异。在 CI 与发布流程中的应用该工具不仅是开发者手动的分析手段也深度嵌入仓库的自动化流程。全量 bundle 分析脚本analyze-all-bundles.ts 中的generateReportForBundles(version?)会遍历bundle-definitions/*.json逐个执行分析。传version如9.0.0时以 npm 模式测量该历史版本用于回填历史体积数据不传时以 local 模式测量当前提交供 CI 使用。输出被归一化为{ sdk: bundle, type: 产品名 (场景名), value: size }的上报格式。模块导出体积上报report_modular_export_binary_size.ts 在 CI 中调用generateReportForModules遍历packages/*同样过滤-compat/-types把每个模块的Report汇总后通过 size_report_helper.ts 上传至体积追踪后端从而对每次提交的“单导出体积”与“场景 bundle 体积”进行趋势监控。自动化测试size-analysis.test.ts 使用 Vitest 覆盖了导出提取含重命名、重导出、去重、顶层符号提取、dedup/replaceAll等辅助函数测试输入位于 test/test-inputs运行前由pretest:node先编译测试输入并用 Rollup 预生成 bundle 文件。使用前提与注意事项该工具定位为仓库内部脚本package.json中private: true依赖 Node.js24.12.0需要在仓库安装依赖根目录yarn.lock与lerna.json/nx.json管理的工作区后运行CLI 在模块分析模式下--output为必填cli.tsBundle 分析模式下则有默认值使用时注意区分报告的size是在compress: false只 mangle、不深度压缩的前提下计算与真实生产构建的产物体积口径不同横向对比同工具的多次运行结果更有意义需要子模块如firebase/firestore/memory被纳入分析时务必在其package.json中设置generate-size-analysis-report: true否则会被递归遍历阶段跳过。掌握以上 CLI 参数、编程 API 与源码链路后你既可以快速生成任意 Firebase 包的导出体积报告也能编写自定义的 Bundle 定义来度量自己关心场景的最小包体为体积优化决策提供量化依据。赞分享开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载相关推荐Firebase JS SDK 核心工具包 firebase/util 完全指南公开 API、源码实现与实战用法Firebase JS SDK 核心工具包 firebase/util 完全指南公开 API、源码实现与实战用法 导读 firebase/util 是 F开发工具后端为什么选择Minegrub World Selection Theme让你的Linux启动界面秒变Minecraft风格为什么选择Minegrub World Selection Theme让你的Linux启动界面秒变Minecraft风格 Minegrub World SelSunnyUI 头像控件 UIAvatar 完全指南三种显示方式、圆形/方形形状与主题样式联动SunnyUI 头像控件 UIAvatar 完全指南三种显示方式、圆形/方形形状与主题样式联动 UIAvatar 是 SunnyUI 开源 WinForm 控开发工具后端上一篇MaxViT XLarge TF 512在工业应用中的实践检测、识别与分割案例终极指南下一篇LLaMA-Factory NPU 融合算子指南RMSNorm、SwiGLU、RoPE 与 MoE 的硬件加速实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考