Grails 3.3.8打包WAR时未包含React生成的bundle.js静态资源
我最近碰到一个头疼的问题:把React项目打包生成的bundle.js想整合到Grails的WAR包中,在IntelliJ IDEA里直接运行Grails项目时,页面能正常加载React应用,但用grails war命令打包后,部署到服务器就发现React应用没了——查了下WAR包,居然没包含bundle.js的内容!
我的环境与配置信息
- Grails版本:3.3.8
- JDK版本:1.8.0_432
gradle.properties内容:
grailsVersion=3.3.8 gormVersion=6.1.10.RELEASE gradleWrapperVersion=3.5
build.gradle关键配置片段:
buildscript { repositories { mavenLocal() maven { url "https://repo.grails.org/grails/core" } } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" classpath "org.grails.plugins:hibernate5:${gormVersion-"RELEASE"}" classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.14.8" } } version "0.1" group "myapp" apply plugin:"eclipse" apply plugin:"idea" apply plugin:"war" apply plugin:"org.grails.grails-web" apply plugin:"asset-pipeline" apply plugin:"org.grails.grails-gsp" apply plugin:"java" apply plugin:"io.spring.dependency-management" war.archiveName='myapp.war' // 依赖配置省略... assets { minifyJs = true minifyCss = true } jar { manifest { attributes 'Main-Class': 'myapp.Application' } } war { manifest { attributes 'Main-Class': 'myapp.Application' } }
GSP页面中引用bundle.js的代码:
<div id="react-root"></div> <asset:javascript src="bundle.js"/> </div>
我已经尝试过的方法(但都没生效)
- 参考了相关问题里提到的资产插件配置调整,没有解决
- 在
Application.groovy和application.yml中配置排除bundle.js的压缩,无效:- Application.groovy配置:
grails.assets = [ minifyJs: false, minifyCss: true, minifyOptions: [ excludes: [ '**/jquery-2.2.0.min.js', '**/bundle.js' ] ] ] - application.yml配置:
grails: assets: minifyJs: true minifyCss: true minifyOptions: excludes: - '**/jquery-2.2.0.min.js' - '**/bundle.js'
- Application.groovy配置:
- 在
application.js中添加//= bundle.js,也没效果
针对这个问题的解决建议
1. 确保bundle.js在Asset Pipeline的扫描范围内
Grails的Asset Pipeline默认只扫描grails-app/assets/javascripts/目录,你要么把React生成的bundle.js复制到这个目录,要么在build.gradle里配置额外的资产源目录:
assets { sourceDirs = ['grails-app/assets', 'src/main/webapp/react-dist'] // 替换成你的React打包输出目录 minifyJs = true minifyCss = true }
2. 用正确的Asset Pipeline语法导入bundle.js
在grails-app/assets/javascripts/application.js中,用require语法导入bundle.js,确保它被纳入资产编译流程:
//= require bundle.js
这里要注意,//= bundle是用来定义打包组的,单个文件导入要用require。
3. 让React打包任务先于Grails资产编译执行
要确保React先打包生成最新的bundle.js,再让Grails处理资产。在build.gradle中添加任务依赖:
// 定义React打包任务 task npmBuild(type: Exec) { workingDir 'path/to/your/react-project' // 替换为你的React项目根目录 if (System.getProperty('os.name').toLowerCase().contains('windows')) { commandLine 'cmd', '/c', 'npm', 'run', 'build' // Windows环境 } else { commandLine 'npm', 'run', 'build' // 类Unix环境 } } // 让Grails的资源处理任务依赖于React打包任务 processResources.dependsOn npmBuild assets.dependsOn npmBuild
4. 验证资产编译结果
执行./gradlew asset-compile(或gradlew.bat asset-compile)命令,然后查看build/assets/javascripts目录下是否有bundle.js。如果这里能找到,说明资产编译正常,WAR打包时就会包含它。
5. 移除WAR包中不必要的Main-Class配置
Grails WAR包不需要Main-Class属性(这是给可执行JAR用的),可以删除war块里的manifest配置,避免潜在冲突:
// 移除这段配置 war { manifest { attributes 'Main-Class': 'myapp.Application' } }
备注:内容来源于stack exchange,提问作者Amit Thakur

