React Native 中如何通过 npm 向 Gradle 传递 --offline?
可以用 process.argv.slice(2) 读取 gradle-offline,再按需添加 Gradle 参数。先确认项目使用的 React Native CLI 是否支持 --extra-params。支持该选项时,使用:
react-native run-android --extra-params=--offline
react-native run-android -- --offline 是否会把参数传给 Gradle,取决于 CLI 的实现。-- 只负责结束当前命令的选项解析,不保证后续参数会继续传递。
--offline 只能让 Gradle 使用已有的依赖缓存;缺少所需缓存时,构建仍会失败。
先确认 CLI 支持的参数
在项目目录执行:
npx react-native run-android --help
检查输出中是否包含:
--extra-params <string>
React Native Community CLI 的参数定义包含这个选项,对应的运行逻辑会将 extraParams 加入 Gradle 参数数组。
下面的脚本要求本地 CLI 支持该选项。由于没有指定 CLI 版本,请以项目内的 --help 输出为准。
npm 参数应该怎样读取
假设 package.json 中配置的是:
{
"scripts": {
"dev": "node dev.js"
}
}
执行:
npm run dev gradle-offline
npm 会把 gradle-offline 作为位置参数传给 dev.js。也可以显式使用分隔符:
npm run dev -- gradle-offline
两种写法都可以用这段代码识别:
const args = process.argv.slice(2);
const isGradleOffline = args.includes('gradle-offline');
process.argv.includes('gradle-offline') 也能完成检测,使用 slice(2) 则可以排除 Node 可执行文件路径和脚本路径。
根据 npm 文档,位置参数会传给指定脚本;传递以 - 开头的选项时,应使用 npm 的 -- 分隔符。这里的分隔符用于从 npm 向 dev.js 传参,与 React Native CLI 向 Gradle 传参是两个环节。
跨平台脚本示例
可以通过当前 Node 可执行文件运行项目内的 React Native CLI JavaScript 入口,将命令参数放进数组。这样就不需要分别拼接 Unix 的环境变量赋值语句和 Windows 的 SET 命令。
以下示例假设 dev.js 位于项目根目录,环境文件位于项目内的 envs/.env.dev:
const { spawn } = require('child_process');
const path = require('path');
const projectRoot = __dirname;
const isGradleOffline = process.argv
.slice(2)
.includes('gradle-offline');
const cliPath = require.resolve('react-native/cli.js');
const cliArgs = [
cliPath,
'run-android',
'--active-arch-only',
'--appIdSuffix',
'debug',
];
if (isGradleOffline) {
cliArgs.push('--extra-params=--offline');
}
const child = spawn(process.execPath, cliArgs, {
cwd: projectRoot,
env: {
...process.env,
ENVFILE: path.resolve(projectRoot, 'envs', '.env.dev'),
},
shell: false,
stdio: 'inherit',
});
child.on('error', (error) => {
console.error('无法启动 React Native CLI:', error.message);
process.exitCode = 1;
});
child.on('close', (code, signal) => {
if (signal) {
console.error(`React Native CLI 被信号 ${signal} 终止`);
}
process.exitCode = code ?? 1;
});
使用方式:
# 正常构建
npm run dev
# 启用 Gradle 离线模式
npm run dev gradle-offline
# 同样启用 Gradle 离线模式
npm run dev -- gradle-offline
脚本中的几处处理需要注意:
process.execPath指向当前 Node 可执行文件。CLI 路径和各项参数各占一个数组元素,即使路径包含空格,也不需要手动加引号。env保留了process.env,以继承PATH、JAVA_HOME、Android SDK 等配置,再设置ENVFILE。--extra-params=--offline将选项和值放在同一个参数中,避免 CLI 将--offline识别为独立的 React Native CLI 选项。- 子进程启动失败或构建失败时,脚本会返回非零退出码。
这里使用的本地 CLI 入口是 react-native/cli.js,需要确认项目版本的安装结构与此一致。Windows 下直接执行 react-native.cmd 需要处理命令脚本的启动规则,通过 Node 执行 JavaScript 入口可以省去这部分处理。相关规则见 Node.js 子进程文档。
如果环境文件实际位于 /envs/.env.dev,请将 ENVFILE 改为对应路径。脚本只设置环境变量,文件如何加载取决于项目使用的环境配置工具。如果项目的 package.json 设置了 "type": "module",可将该 CommonJS 脚本命名为 dev.cjs,同时更新 npm script。
脚本中保留的 --appIdSuffix debug 用于确定启动应用的 ID 后缀,不会配置 Gradle 的构建变体。
如果 CLI 不支持 --extra-params
如果 CLI 没有实现参数转发,仅调整 spawn 的参数数组也无法转发参数。
可以直接调用项目内的 Gradle Wrapper,例如在 android 目录执行:
# macOS / Linux
./gradlew :app:installDebug --offline
Windows:
gradlew.bat :app:installDebug --offline
这里假设应用模块名为 app,目标任务为 installDebug。项目存在 product flavor 或自定义变体时,应替换为实际任务。
直接执行 Gradle 时,还需要单独处理 Metro 和应用启动,并传入相同的环境配置,因此无法完整替代 run-android 的行为。
离线构建成功需要哪些缓存
根据 Gradle 文档,--offline 会阻止依赖解析访问网络,改用已有缓存;缺少所需依赖时,构建会直接失败。
可以按以下步骤准备和验证缓存:
- 联网执行一次
npm run dev,完成实际目标变体和设备架构的构建。 - 保留相同的
GRADLE_USER_HOME及其缓存,验证前不要清空缓存目录。 - 执行
npm run dev gradle-offline,确认这次构建所需的依赖已经齐全。
一次构建只会准备实际用到的依赖。更换构建变体、目标架构、依赖版本或仓库配置后,可能需要重新联网构建。
还需要提前准备 Gradle Wrapper 对应的 Gradle 分发包。Wrapper 文档说明,本地没有对应分发包时,Wrapper 会下载 Gradle;--offline 不能替代这一步。Android SDK、NDK 和项目依赖的其他工具也应提前安装。
--offline 控制的是 Gradle 的依赖解析,不能保证自定义构建任务或其他工具完全不联网,也不会自动启用构建输出缓存。离线构建能否成功,取决于本地是否已备齐当前构建所需的依赖和工具。
备注:内容仅供参考。
