ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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),仅供参考
返回列表