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

发布时间:2026/11/12 4:30:54

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/11/9 21:56:57

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/11/9 22:05:04

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

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

2026/11/11 0:47:28

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

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

2026/11/12 4:29:20

工地电工作业证复审流程全解析 电工上岗必须这个证你知道吗

工地电工作业证复审流程全解析 电工上岗必须这个证你知道吗 你还在为找不到工作发愁?工地电工作业证复审没过,直接影响你能不能上岗。现在全国范围内,施工单位对电工证的要求越来越严格,尤其是高压电工、低压电工这类特种作业岗位,必须持证上岗。别等被…

2026/11/12 4:29:20

低压电工作业安全技术培训PPT保姆级教程:别被中介坑了,这招超实用

低压电工作业安全技术培训PPT保姆级教程:别被中介坑了,这招超实用 你是不是也遇到过这种情况?想考低压电工证,到处打听报名点,结果被中介坑了钱还考不过?别急,这篇保姆级教程就是为你准备的。不管你是开封公路工程从业者,还是准备跨省转介办理,这…

2026/11/12 4:29:19

龙江哪里有学电工证 官方回应证书过期怎么处理最靠谱

龙江哪里有学电工证 官方回应证书过期怎么处理最靠谱 证书过期了不知道怎么复审延期?在龙江地区,越来越多的电工从业者发现,手里那本特种作业操作证并不是终身有效的,一旦超过规定时间不进行复审,就会面临证件失效、无法上岗甚至面临处罚等现实问题。尤…

2026/11/12 4:24:19

考电工证用处,学历不高怕报不上名?良心建议来了

考电工证用处,学历不高怕报不上名?良心建议来了 学历不高怕报不上名?别急,考电工证用处其实比你想象的更大。特别是像你这种没有太多学历背景的朋友,电工证不仅是一张通行证,更是你改变现状的关键钥匙。别被“门槛高”吓到, 良心建议…

2026/11/11 12:42:59

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/12 0:04:01

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘 工地太忙根本没时间复习考试?你不是一个人。作为一名在南阳卧龙区干了七八年市政公用工程的电工,我深知这个问题的现实性。电工证不仅是工作的“入场券”,更是职业发展的“通行证”,但备考过程…

2026/11/12 0:04:01

双流电工证考别怕挂科!郑州报考避坑指南全攻略

双流电工证考别怕挂科!郑州报考避坑指南全攻略 实操考试心里没底怕挂科?双流电工证考在郑州报名,很多人因为不了解流程、准备不充分,白白浪费时间和金钱。作为三门峡应届工程类毕业生,我也曾经历过这样的焦虑。今天就从零开始,手把手教你如何避开郑州报…

2026/11/12 0:04:01

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少 之前考的证在外省能不能转过来?这个问题确实让不少准备换城市工作的朋友犯了难,尤其像电工证这种实操性很强的证书,很多人担心跨省后证书能不能继续用。其实,只要符合相关流程,是可以顺利转…

2026/11/11 20:27:01

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

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

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

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

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