AngularJS 的 vendor 依赖管理:closure-compiler 与 ng-closure-runner 的离线托管与压缩构建管线

发布时间:2026/9/18 16:57:37

AngularJS 的 vendor 依赖管理:closure-compiler 与 ng-closure-runner 的离线托管与压缩构建管线 AngularJS 的 vendor 依赖管理closure-compiler 与 ng-closure-runner 的离线托管与压缩构建管线【免费下载链接】angular.jsAngularJS - HTML enhanced for web apps!项目地址: https://gitcode.com/gh_mirrors/an/angular.js导读AngularJS 仓库把无法通过 npm/yarn 官方源获取、或版本无法对齐的第三方构建工具直接以二进制文件形式提交进 git集中存放在vendor目录下并配套一份说明文档用于记录这些库的版本与更新方式。本文以 vendor/README.md 为主线结合 Gruntfile.js、lib/grunt/utils.js 与 src/minErr.js 等源码完整梳理 vendor 依赖的构成、它们在 AngularJS 压缩minify构建管线中的真实用途、更新方法以及未来迁移方向帮助你理解为什么一个开源仓库里会出现两个 jar 文件以及它们如何在每次发布时把源码压缩成angular.min.js。一、vendor 目录是什么为什么需要把依赖提交进 git按照 vendor/README.md 的说明vendor文件夹专门用来存放无法通过 yarn / npm registry 获取的库。这些库虽然以源码或二进制形式随仓库一起分发但它们的来源五花八门npm 上有同名包但版本对不上例如 Google Closure Compiler 虽然发布在 npm 上但 AngularJS 实际锁定的版本20140814并不存在于 npm 中因此只能以自带的compiler.jar形式托管在仓库里。项目从未发布到 npm例如ng-closure-runner版本0.2.4它是 AngularJS 团队围绕 Closure Compiler 定制的封装工具整个项目从未发布到 npm registry因此没有任何包管理器能直接安装它。于是 AngularJS 采取的策略是把这两个库的成品 jar 直接 check-in 到vendor目录构建时通过本地 classpath 加载从而保证任何环境下都能复现出完全一致的压缩结果。当前vendor目录的实际结构如下vendor根目录下还有一份 README.md 作为总说明vendor/ ├── README.md # 依赖管理总说明 ├── closure-compiler/ # Google Closure Compiler20140814 │ ├── COPYING │ ├── README.md # 上游自带的 README │ └── compiler.jar # 编译器本体 └── ng-closure-runner/ # AngularJS 定制封装0.2.4 ├── LICENSE ├── README.md └── ngcompiler.jar # 定制 runner 本体二、vendored 的两大组件与其定位1. closure-compiler20140814vendor/closure-compiler/README.md 是 Google Closure Compiler 上游自带的说明文档。它明确了 Closure Compiler 的定位从 JavaScript 编译出更好的 JavaScript——不是编译到机器码而是解析、分析、删除死代码并重写和压缩剩余代码同时还会检查语法、变量引用和类型对常见的 JavaScript 陷阱给出警告。从该上游 README 可以了解到编译器本身的使用方式这也是理解 AngularJS 构建脚本的基础运行依赖Java 7 或更高版本AngularJS 构建脚本中实际是通过java命令直接执行 jar支持交互模式java -jar compiler.jar后输入var x 17 25;再按Ctrl-DMac/Linux或Ctrl-ZWindows加回车会输出var x42;支持多文件与 glob 模式一次编译# 依次传入多个文件按命令行顺序拼接输出 java -jar compiler.jar --js_output_fileout.js in1.js in2.js in3.js # 递归包含子目录下所有 js java -jar compiler.jar --js_output_fileout.js src/**.js # 递归包含排除 _test.js 结尾的文件用单引号防止 bash 展开 ! java -jar compiler.jar --js_output_fileout.js src/**.js !**_test.js注意上游 README 中的路径如build/compiler.jar是从 Closure Compiler 自己的源码树出发的相对路径在本仓库中对应文件被以成品形式固定在 vendor/closure-compiler/compiler.jar构建脚本以-cp方式直接引用。2. ng-closure-runner0.2.4vendor/ng-closure-runner/README.md 说明它是一个围绕 Google Closure Compiler 的轻量封装runner专门为 AngularJS 定制编译 pass例如--minerr_pass。这份 README 同时记录了两类关键信息如何扩展它以src/org/angularjs/closurerunner/MinerrPass.java作为编写自定义编译 pass 的示例注意该源码路径位于 ng-closure-runner 自己的源码树中并未随本仓库一起提交本仓库内只有打包产物 vendor/ng-closure-runner/ngcompiler.jar发布流程使用 Gradle 构建要求 JDK 1.6开发时用gradle check编译并跑测试正式发版时执行gradle distZip、提交assets/ng-closure-runner.zip、打 tag然后在 AngularJS 的bower.json中把引用更新到新 tag。三、它们在构建管线中的真实位置min压缩任务vendor 里的两个 jar 并不是被随意摆放的装饰品——它们组成了 AngularJS 发布构建中压缩 JS 产物的核心执行链路。真正的调用点位于 lib/grunt/utils.js 的min函数。该函数把源码文件交给 Java 进程classpath 由两个 jar 共同组成java [32位标志] -Xmx2g \ -cp vendor/closure-compiler/compiler.jar:vendor/ng-closure-runner/ngcompiler.jar \ org.angularjs.closurerunner.NgClosureRunner \ --compilation_level SIMPLE_OPTIMIZATIONS \ --language_in ECMASCRIPT5_STRICT \ --minerr_pass \ --minerr_errors build/angular-errors.json \ --minerr_url http://errors.angularjs.org/版本号/ \ --source_map_formatV3 \ --create_source_map build/angular.min.js.map \ --js build/angular.js \ --js_output_file build/angular.min.jsWindows 上 classpath 分隔符为;非 Windows 为:见 lib/grunt/utils.js非 Windows 环境默认追加-Xmx2g内存上限见同一文件的memoryRequirement。这段命令中的关键参数与源码对应关系如下参数取值作用-cp vendor/closure-compiler/compiler.jar:vendor/ng-closure-runner/ngcompiler.jar两个 vendored jar同时加载 Closure Compiler 与 AngularJS 定制 runner主类org.angularjs.closurerunner.NgClosureRunner固定由 vendor/ng-closure-runner/ngcompiler.jar 提供--compilation_levelSIMPLE_OPTIMIZATIONS默认压缩级别唯一例外是build/angular-message-format.js使用ADVANCED_OPTIMIZATIONS见 lib/grunt/utils.js--language_in ECMASCRIPT5_STRICT固定声明输入语言为 ES5 严格模式--minerr_pass固定启用 AngularJS 自定义的 minErr 剥离 pass见下文第四节--minerr_errorsbuild/angular-errors.json把剥离出的错误码信息写到独立 JSON 文件--minerr_urlhttp://errors.angularjs.org/版本/运行时错误消息中附加的错误文档 URL 前缀--source_map_formatV3固定生成 Source Map v3 格式--create_source_mapbuild/angular.min.js.map指定 source map 输出路径--js/--js_output_filebuild/angular.js→build/angular.min.js输入输出文件对压缩完成后min函数还会做三步收尾lib/grunt/utils.js修正 source map 相对路径Closure 生成的 map 中file与sources带有build/前缀直接替换掉统一 strict 模式通过singleStrictlib/grunt/utils.js移除每个文件各自的use strict;改在 IIFE 顶部注入唯一一个追加 source map 指令在压缩文件末尾写入//# sourceMappingURL...sourceMap函数lib/grunt/utils.js。四、--minerr_pass的底层逻辑minErr 与版本占位符--minerr_pass是 ng-closure-runner 为 AngularJS 提供的最重要的自定义 pass它服务于 AngularJS 的错误系统。理解它需要先看 src/minErr.jsfunction minErr(module, ErrorConstructor) { ErrorConstructor ErrorConstructor || Error; var url https://errors.angularjs.org/NG_VERSION_FULL/; // ... return function() { var code arguments[0], template arguments[1], message [ (module ? module : : ) code ] , // ... message template.replace(/\{\d\}/g, function(match) { /* ... */ }); message \n url (module ? module / : ) code; // 可配置地在尾部追加 ?p0...p1... 参数受 minErrConfig.urlErrorParamsEnabled 控制 return new ErrorConstructor(message); }; }可见 AngularJS 的错误对象由模块名 错误码 模板字符串 errors.angularjs.org 文档 URL构成。在未压缩的源码里模板字符串如This {0} is {1}是完整保留、可供开发者直接阅读的而minErr_pass在压缩阶段把这些长模板字符串从产物中剥离换成简短的错误码引用并同步导出到--minerr_errors指定的 JSON 文件中——这正是 AngularJS 的angular.min.js体积远小于普通压缩结果的原因之一同时也解释了为什么错误码、命名空间和模板字符串在源码中必须是静态字符串src/minErr.js 中的注释明确说明这些内容会在构建期被静态解析。minErr里的另一个细节是版本占位符NG_VERSION_FULL。它和 src/AngularPublic.js 中angular.version对象的full/major/minor/dot/codeName一样都是占位符由build任务在打包时替换成真实版本号见 lib/grunt/utils.js 中this.process(src, grunt.config(NG_VERSION), config.strict)的处理逻辑。也就是说从vendor里的 jar 启动的压缩进程最终写进产物的是经过版本替换后的错误 URL。五、构建任务的调度Gruntfile 与并行 minallvendor 依赖不仅被utils.min单独使用还深度嵌入了 Grunt 的任务编排。1. 待压缩文件清单Gruntfile.js 中的min多任务配置列出了所有需要走 Closure Compiler 压缩的模块min: { angular: build/angular.js, animate: build/angular-animate.js, cookies: build/angular-cookies.js, loader: build/angular-loader.js, messageformat: build/angular-message-format.js, messages: build/angular-messages.js, touch: build/angular-touch.js, resource: build/angular-resource.js, route: build/angular-route.js, sanitize: build/angular-sanitize.js, aria: build/angular-aria.js, parseext: build/angular-parse-ext.js }共 12 个产物文件每个都会被 lib/grunt/plugins.js 注册的min多任务调用util.min走一遍第四节描述的流程。2. 任务编排与错误合并lib/grunt/plugins.js 注册了minall读取grunt.config(min)的所有目标通过async.forEach并行压缩以充分利用 CPU。与此对称的还有buildall并行构建未压缩版本。顶层任务则定义在 Gruntfile.jsgrunt minifyclean→build→minallgrunt package也是默认任务validate-angular-files→clean→buildall→minall→collect-errors→write→docs→copy:i18n→compress:build。其中collect-errors对应 lib/grunt/utils.js 的collectErrors把所有build/*-errors.json即--minerr_errors的输出合并成一个build/errors.json结构为{ id: ng, generated: 时间, errors: {...} }如果同一错误码在不同模块间内容不一致会触发grunt.warn警告Duplicate minErr codes dont match!这保证了错误码在整个框架内的全局唯一性。六、如何更新 vendor 依赖维护者视角vendor/README.md 明确规定了更新流程当上游出现新版本时必须手动下载并替换仓库内的文件随后重新构建、验证压缩产物正常再提交变更。以两个组件为例closure-compiler从上游获取新版compiler.jar后覆盖 vendor/closure-compiler/compiler.jar并在 vendor/README.md 中同步更新版本号当前锁定20140814ng-closure-runner按 vendor/ng-closure-runner/README.md 的发布说明——核心团队执行gradle distZip生成 zip、提交到其assets/ng-closure-runner.zip、打 tag然后把 AngularJS 的bower.json引用指到新 tag对应产物最终落到 vendor/ng-closure-runner/ngcompiler.jar。由于这两个 jar 直接参与发布产物的生成任何版本升级都可能改变压缩输出尤其是--minerr_pass与ADVANCED_OPTIMIZATIONS的行为因此更新后必须回归 test 目录下的单元测试与 e2e 测试确认错误码、source map 与最终产物均正常。七、为什么不去掉 vendor关于未来迁移的展望vendor/README.md 在文末给出了一个明确的演进方向如果未来 yarn 支持直接引用 zip 归档依赖对应 yarn 官方仓库的 issue #1483就可以把这两个库从 git 中移除改为在package.json中声明由包管理器统一管理版本与缓存。在此之前手动 check-in 的 vendored 模式是保证构建可复现的最直接手段。从工程角度看这种vendor 化策略有清晰的取舍收益不依赖 npm 上缺失/滞后的包任何环境下grunt package都能用完全相同的编译器版本产出完全相同的二进制结果杜绝构建机器不同导致压缩结果漂移代价仓库体积增加两个 jar 被完整提交、升级需要人工介入、license 需要随包保留vendor 目录内配套存放了 COPYING 与 LICENSE 即为此目的。结语vendor/README.md虽然篇幅简短却是理解 AngularJS 发布构建的关键入口它解释了为什么仓库里会有compiler.jar和ngcompiler.jar而顺着这份说明再去看 lib/grunt/utils.js 中的min函数、lib/grunt/plugins.js 的minall调度和 src/minErr.js 的错误系统就能把依赖管理 → 压缩执行 → minErr 剥离 → 产物发布这条链路完整串起来。对于任何需要在离线/受限网络环境下维护大型前端仓库的团队这套特定版本二进制 vendor 化 构建脚本 classpath 引用 版本说明文档的组合拳都值得借鉴。【免费下载链接】angular.jsAngularJS - HTML enhanced for web apps!项目地址: https://gitcode.com/gh_mirrors/an/angular.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/18 16:57:37

Bonsai-demo上下文长度调优:BONSAI_CTX自动RAM分层机制解析

Bonsai-demo上下文长度调优:BONSAI_CTX自动RAM分层机制解析 【免费下载链接】Bonsai-demo Bonsai Demo 项目地址: https://gitcode.com/GitHub_Trending/bo/Bonsai-demo Bonsai-demo 让你在本地运行 Bonsai / Ternary-Bonsai 系列小模型(最高 27B…

2026/9/18 16:52:37

C#入门实战:从零构建可调试项目与字符串解析

简介:这是一份面向编程初学者的C#面向对象编程(OOP)入门教程PDF,聚焦抽象类、继承、多态等核心概念的原理与实践,特别适合零基础或刚接触C#的学习者建立扎实的OOP思维。资源为单文件PDF文档,共1个59KB的轻量…

2026/9/18 16:52:36

爱享素材下载器教程:3步免费抓取视频号与抖音无水印视频

爱享素材下载器教程:3步免费抓取视频号与抖音无水印视频 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 以前想把视频号里的一…

2026/9/18 19:22:55

运营报表数据异常自动分析与归因解释

运营报表数据异常自动分析与归因解释在很多企业的日常运营中,数据大盘每天都会发生各种波动:日活(DAU)突然下跌 15%、特定渠道的转化率骤降、退款率在某个时间段异常升高。 传统的做法是运营发现异常后,在群里艾特数据…

2026/9/18 19:22:55

基于YOLOv8与PyQt5的路面坑洞检测系统实战

1. 路面坑洞检测系统整体设计思路拆解1.1 为什么选择YOLOv8而不是传统图像处理方法做路面坑洞检测这件事,我最早试过用传统的边缘检测加阈值分割。OpenCV的Canny算子配合形态学操作,在光照均匀、坑洞边缘清晰的理想图片上确实能跑出结果,但一…

2026/9/18 19:22:55

维护者的情绪管理:面对恶意差评与无理索取

维护者的情绪管理:面对恶意差评与无理索取开源是一件充满理想主义色彩的事情,但只要你的项目获得了一定的曝光,你的 GitHub Issue 区就不可避免地会变成各种情绪的聚集地。 有的用户会因为一个微小的 Bug 在评论区破口大骂:“这么…

2026/9/18 19:22:55

轻量鉴权:基于 HMAC 签名的 API 认证

轻量鉴权:基于 HMAC 签名的 API 认证在构建微服务间通信、外部 Webhook 回调或轻量单体系统对外开放的 API 时,很多团队一上来就照搬复杂的 OAuth2、IdentityServer 或者是带有一堆配置的 JWT 刷新体系。 对于简单的服务端对服务端(S2S&#…

2026/9/18 19:22:55

C-NCAP 2024附录L详解:AEB/FCW测试时间基准与ADAS工程实践

简介:C-NCAP 2024版附录L是面向整车企业ADAS开发与测试工程师、安全评价人员及高校研究者的主动安全试验规程。文档完整规定了AEB、FCW等系统的试验术语、车辆坐标系、天气要求、VUT准备与预处理流程,并系统展开L.6.1的AEB C2C测试场景,如CCR…

2026/9/18 19:17:55

硬件工程师的硬核读法:如何用四层过滤法精读芯片资料

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 14:13:01

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/18 14:13:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/18 14:13:02

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/18 14:13:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码