关于重叠包技术在jenkins打包时报错的解决方案

本文介绍了一种利用重叠包技术实现Android应用模块化的方案,通过配置Gradle脚本,实现不同业务模块之间的灵活切换及打包。文章详细解释了如何避免因同名文件导致的编译错误,并提供了具体的工程结构示例。

转载请注明出处:
http://blog.youkuaiyun.com/brucehurrican/article/details/51778319

最近公司项目需要进行部分业务模块的抽离,目前我在项目中采用的是重叠包技术,这样我和同事用AS开发时可以通过切换buildtype来进行不同业务模块的切换,编码,打包。

坑点:

  • 打包时,应根据需要的业务模块(即buildtype对应的文件夹)来选择相应的assembleXXX来build,直接build会报错,原因是直接build 会将所有业务模块的包进行build,而这些包对外肯定有一个统一入口(即有一个共同的文件,如 LibActivity.java)。LibActivity.java 在 A 模块中是显示XX地图信息的, 在B 模块中可能就是用来显示XX商城的。同名文件 LibActivity.java在默认build时会全部build 这样会报 同名文件错误。
  • 项目组用的是jenkins打包,配置的是用gradle来打包,通过gradle build来编包就会报上述错误。

为了兼顾服务器打包的方便,同时不能增大后期代码维护的成本,在对原有重叠包分业务模块的代码结构不做大改的前提下,通过增加gradle脚本,人为设定在每次build时指定要build的业务type来解决上述问题。

核心代码如下:
工程结构:
demos/src/blue  // 业务模块
demos/src/red   // 业务模块
demos/src/main  // 公共模块
demos/src/test
demos/src/androidTest

demos/buildtypes/red/build.gradle

...
buildTypes{
    red{
        versionNameSuffix 'red'
    }
}
sourceSets{
    main{
        java.srcDirs=['src/main','src/red']
        res.srcDirs=['src/main/res','src/red/res']
    }
}
...

asstudydemo/bruceutils/buildtypes/blue/build.gradle

...
buildTypes{
    blue{
        versionNameSuffix 'blue'
    }
}
sourceSets{
    main{
        java.srcDirs=['src/main','src/blue']
        res.srcDirs=['src/main/res','src/blue/res']
    }
}
...

此两个文件用于替换demos/app/build.gradle,上面两个文件主要是用来在服务器上打包用的。开发人员开发时模块间的切换不用这么麻烦,在demos/app/build.gradle完成如下配置即可

 ...
 buildTypes{
    red{
        versionNameSuffix 'red'
    }
    blue{
        versionNameSuffix 'blue'
    }
}
sourceSets{
    main{
        //java.srcDirs=['src/main','src/blue']
        //res.srcDirs=['src/main/res','src/blue/res']
    }
}
 ...

此时可以通过AS上的 Build Variants功能在相应的业务模块间切换。

那么对于 …/red/build.gradle 和 …/blue/build.gradle这两个文件,jenkins是怎样在打包时分别使用的呢,这里还需要一个复制文件的task。task代码如下:

task typered(type: Copy){
    from 'demos/buildtypes/red/build.gradle'
    into 'demos'
}
task typeblue(type: Copy){
    from 'demos/buildtypes/blue/build.gradle'
    into 'demos'
}

这个复制文件的 task 可以放在 demos/build.gradle 此处记为方法1, 也可以存在于单独的脚本文件中demos/copyfiles.gradle 此处记为方法2.

对于方法1 服务器打包时执行如下命令:

  • gradle typered
  • gradle build
    生成业务red的apk

  • gradle typeblue

  • gradle build
    生成业务blue的apk

对于方法2 因为demos/build.gradle 为工程根目录下的gradle脚本,服务器打包时会优先执行该脚本,并顺次招行app/build.gradle脚本,方法2的脚本不在build命令中,如按方法1中命令编译的话,会报 Task typered not found in roo project ‘demos’的错误,此时服务器打包命令就按如下进行:

  • gradle typered -b ‘demos/copyfiles.gradle’
  • gradle build
    生成业务red的apk

  • gradle typeblue -b ‘demos/copyfiles.gradle’

  • gradle build
    生成业务blue的apk

坑点1:
各业务模块的build.gradle的名称应和应用build.gradle一致,否则报错。即在本例中,应保证

  • demos/buildtypes/red/build.gradle
  • demos/buildtypes/blue/build.gradle
  • demos/app/build.gardle

三文件名称一致。

坑点2:

如果重叠包应用在app工程下,则blue、red业务模块中可以使用 applicationIdSuffix 属性

blue {
            applicationIdSuffix 'blue'
            versionNameSuffix 'blue'
        }
        red {
            applicationIdSuffix 'red'
            versionNameSuffix 'red'
        }

如果在lib工程下,则 applicationIdSuffix 属性不可用,否则报错。

坑点3:
gradle复制文件脚本时,会有BUG,copyfiles.gradle运行后要替换的文件是 build.gradle,虽然提示运行成功,但是文件并没有替换。对此,我的解决办法是用shell脚本来复制文件不用gradle脚本。

如果你有更好的方法,欢迎不吝赐教^_^

demo下载

参考资料

<think>我们正在处理一个关于在VSCode本地打包正常,但在Jenkins上构建失败的问题。根据用户提供的引用和问题描述,错误信息是内存溢出(JavaScript heap out of memory)。我们将分析可能的原因并提供解决方案。 ### 问题分析 1. **环境差异**:本地环境(VSCode)与Jenkins环境可能存在差异,括操作系统、Node.js版本、内存分配等。 2. **内存限制**:Node.js默认内存限制较低(约1.5GB),在构建大型项目可能不足。 3. **构建脚本**:Jenkins执行的构建脚本可能与本地不同,例如是否传递了增加内存的参数。 ### 解决方案 #### 1. 增加Node.js内存限制 在构建命令中,通过`--max-old-space-size`参数增加Node.js可用的内存。例如,将内存限制增加到4GB: ```bash node --max-old-space-size=4096 your_build_script.js ``` 在Jenkins的构建脚本中,确保使用该参数。如果使用npm脚本,可以修改`package.json`中的脚本: ```json "scripts": { "build": "node --max-old-space-size=4096 build.js" } ``` 或者,在Jenkins的构建步骤中直接使用: ```bash export NODE_OPTIONS=--max-old-space-size=4096 npm run build ``` #### 2. 检查Jenkins环境 - **Node.js版本**:确保Jenkins服务器上的Node.js版本与本地一致。可以通过在Jenkins中安装Node.js插件来管理版本。 - **系统资源**:检查Jenkins服务器的可用内存。如果服务器内存不足,需要增加内存或优化构建过程。 #### 3. 优化构建配置 如果项目使用Webpack,可以尝试以下优化: - **并行构建**:使用`thread-loader`或`HappyPack`(Webpack4及以下)加速构建。 - **缓存**:启用Webpack的缓存机制,减少重复构建。 - **减少构建范围**:通过配置`exclude`排除不必要的文件。 #### 4. 分步构建 如果项目很大,可以考虑将构建过程拆分成多个步骤,减少单次构建的内存占用。 #### 5. 升级依赖 确保所有构建工具(如Webpack、Babel等)都是最新版本,因为新版本可能含内存优化的改进。 ### 示例:Jenkinsfile配置 在Jenkinsfile中,可以设置环境变量并执行构建: ```groovy pipeline { agent any environment { NODE_OPTIONS = '--max-old-space-size=4096' } stages { stage('Build') { steps { sh 'npm install' sh 'npm run build' } } } } ``` ### 总结 本地构建成功而Jenkins失败通常是由于环境差异和内存限制导致。通过增加Node.js内存限制、确保环境一致以及优化构建配置,可以解决此问题。 §§相关问题§§ 1. 如何检查Jenkins服务器上的Node.js版本和内存使用情况? 2. 除了增加内存,还有哪些优化Webpack构建速度的方法? 3. 如何在Jenkins中管理多个Node.js版本?</think>### VSCode 本地打包正常但 Jenkins 构建失败的原因分析和解决方案 #### 根本原因分析 1. **环境差异导致的内存限制问题** - 本地开发环境通常有更多可用内存(如 16GB+),而 Jenkins 服务器可能配置较低(如 2-4GB) - Node.js 默认内存上限为 **1.4-1.7GB**,大型项目构建容易超出限制,报错:`FATAL ERROR: Ineffective mark-compacts... JavaScript heap out of memory`[^1][^2] 2. **构建过程差异** - Jenkins 构建会执行完整流程(括 lint、test、sourcemap 等),而本地可能跳过部分步骤 - 持续集成环境会清理缓存,导致每次构建都是完整重建 3. **资源竞争问题** - Jenkins 服务器可能同运行多个构建任务,导致内存资源不足 - 容器化环境(如 Docker)未正确配置内存限制 --- #### 解决方案 ##### 1. 增加 Node.js 内存限制(推荐) 在 `package.json` 中修改构建命令: ```json "scripts": { "build": "node --max-old-space-size=4096 ./node_modules/vite/bin/vite.js build" } ``` 或在 Jenkinsfile 中设置环境变量: ```groovy pipeline { environment { NODE_OPTIONS = "--max-old-space-size=4096" // 分配 4GB 内存 } stages { stage('Build') { steps { sh 'npm run build' } } } } ``` ##### 2. 优化构建配置 ```javascript // vite.config.js 或 webpack.config.js export default { build: { sourcemap: false, // 禁用 sourcemap chunkSizeWarningLimit: 1500, // 提高块大小警告阈值 rollupOptions: { output: { manualChunks(id) { // 手动分块 if (id.includes('node_modules')) { return 'vendor' } } } } } } ``` ##### 3. Jenkins 环境调整 ```bash # 在 Jenkins 服务器执行 sudo sysctl -w vm.max_map_count=262144 # 增加内存映射限制 sudo swapoff -a && sudo swapon -a # 重置交换空间 ``` ##### 4. 分阶段构建(适用于超大项目) ```groovy // Jenkinsfile 分步构建示例 stage('Build Part1') { steps { sh 'npm run build:core' // 先构建核心模块 } } stage('Build Part2') { steps { sh 'npm run build:modules' // 再构建其他模块 } } ``` ##### 5. 验证内存使用(诊断工具) 安装内存分析模块: ```bash npm install heapdump v8-profiler-next --save-dev ``` 在构建脚本中添加: ```javascript const heapdump = require('heapdump') setInterval(() => { heapdump.writeSnapshot() }, 60000) // 每分钟生成内存快照 ``` --- ### 关键预防措施 1. **统一环境**:使用 Docker 容器确保本地与 CI 环境一致 ```dockerfile FROM node:18 ENV NODE_OPTIONS="--max-old-space-size=4096" ``` 2. **监控机制**:在 Jenkins 中添加构建内存监控 ```groovy post { always { script { def mem = sh(script: 'free -m', returnStdout: true) echo "内存使用报告:\n${mem}" } } } ``` 3. **增量构建**:配置构建缓存(如 Webpack 的 `cache` 或 Vite 的 `build-cache`) > 通过上述方案,90% 以上的内存溢出问题可得到解决。若项目特别庞大(如 1000+ 组件),建议结合代码分割和动态导入优化[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值