Thực hiện minify javascript, css files sử dụng Gradle

Gần đây mình đang tham gia vào một dự án Java (Spring MVC, Hibernate, Gradle, BootStrap, FreeMarker. Hôm nay sẽ tổng kết quá trình thực hiện minify Javascript và CSS trong Java WAR archive.
Còn minify là gì? Minify là quá trình rút gọn code, xóa tự động các ký tự không cần thiết và làm nhỏ kích thước của file có thể nhỏ bằng nhiều cách khác. (File có thể thu nhỏ còn lại khoảng 50-60% so với kích thước file ban đầu).

Plugins

Sau khi tìm hiểu thì mình quyết định sử dụng 2 plugin sau.
eriwen/gradle-js-plugin
eriwen/gradle-css-plugin
Theo thiết kế ban đầu các file Javascript, CSS ngoài các file common.js, common.css dùng chung cho tất cả các trang thì các trang lại có sử dụng riêng lẻ file .js, .css riêng lẻ. Vì thế nên phần minify cũng thực hiện theo từng file riêng lẻ.

Định nghĩa dependencies trong build.gradle

[code lang=”groovy”]
buildscript {
repositories {
jcenter()
}
dependencies {
classpath ‘net.saliman:gradle-cobertura-plugin:2.2.7’
classpath "com.eriwen:gradle-js-plugin:1.12.1"
classpath ‘com.eriwen:gradle-css-plugin:1.11.1’
}
}
apply plugin: ‘js’
apply plugin: ‘css’
[/code]
Định nghĩa source file trong build.gradle
[code lang=”groovy”]
//Local variables
def webAppDir = "src/main/webapp"
def versionedOutputDir = "${buildDir}/versioned-files"
def minifyOutputDir = "${buildDir}/minified"
javascript.source {
custom {
js {
srcDir webAppDir + ‘/js’
include "*"
exclude "lib/*"
}
}
}
// Declare your sources
css.source {
custom {
css {
srcDir webAppDir + ‘/css’
include "*.css"
exclude "favicon.ico"
}
}
}
[/code]

Định nghĩa task

Có các phần xử lý chính:
– Minify Javascript
– Minify CSS
– Copy vào file WAR

Minify Javascript

Đọc tất cả các file .js trong thư mục và định nghĩa các task dominifyJs0, dominifyJs1,… theo index.
[code lang=”groovy”]
javascript.source.custom.js.files.eachWithIndex { jsFile, idx ->
tasks.create(name: "dominifyJs${idx}", type: com.eriwen.gradle.js.tasks.MinifyJsTask) {
if (jsFile.getParentFile().getName() != "js") {
source = jsFile
dest = minifyOutputDir + "/js/" + jsFile.getParentFile().getName() + "/${jsFile.name}"
closure {
compilationLevel = ‘SIMPLE_OPTIMIZATIONS’
warningLevel = ‘QUIET’
}
} else {
source = jsFile
dest = minifyOutputDir + "/js/${jsFile.name}"
closure {
compilationLevel = ‘SIMPLE_OPTIMIZATIONS’
warningLevel = ‘QUIET’
}
}
}
}
task individualJsMinify(dependsOn: tasks.matching { Task task -> task.name.startsWith("dominifyJs") })
[/code]
Kết quả
[code lang=”bash”]
$ ./gradlew individualJsMinify
:dominifyJs0
:dominifyJs1
:dominifyJs10
:dominifyJs11
:dominifyJs12
:dominifyJs2
:dominifyJs3
:dominifyJs4
:dominifyJs5
:dominifyJs6
:dominifyJs7
:dominifyJs8
:dominifyJs9
:individualJsMinify
[/code]
Các file Javascript được minify sẽ được tạo trong thư mục build/minified/js
Minify CSS
Đọc tất cả các file .css trong thư mục và định nghĩa các task dominifyCss0, dominifyCss1,… theo index.
[code lang=”groovy”]
css.source.custom.css.files.eachWithIndex { cssFile, idx ->
tasks.create(name: "dominifyCss${idx}", type: com.eriwen.gradle.css.tasks.MinifyCssTask) {
if (cssFile.getParentFile().getName() != "css") {
source = cssFile
dest = minifyOutputDir + "/css/" + cssFile.getParentFile().getName() + "/${cssFile.name}"
closure {
compilationLevel = ‘SIMPLE_OPTIMIZATIONS’
}
} else {
source = cssFile
dest = minifyOutputDir + "/css/${cssFile.name}"
closure {
compilationLevel = ‘SIMPLE_OPTIMIZATIONS’
}
}
}
}
task individualCssMinify(dependsOn: tasks.matching { Task task -> task.name.startsWith("dominifyCss") })
[/code]
Kết quả
[code lang=”bash”]
$ ./gradlew individualCssMinify
:dominifyCss0
:dominifyCss1
:individualCssMinify
[/code]
Các file CSS được minify sẽ được tạo trong thư mục build/minified/css
Copy minified files vào WAR
[code lang=”groovy”]
war {
dependsOn individualJsMinify
dependsOn individualCssMinify
exclude "js/*.js"
from(minifyOutputDir + "/js", {
into ‘js/’ + version
})
exclude "css/*.css"
from( minifyOutputDir + "/css", {
into ‘css/’ + version
})
war.archiveName "ROOT.war"
}
[/code]
Kết quả
[code lang=”bash”]
$ ./gradlew war
:dominifyCss0
:dominifyCss1
:individualCssMinify
:dominifyJs0
:dominifyJs1
:dominifyJs10
:dominifyJs11
:dominifyJs12
:dominifyJs2
:dominifyJs3
:dominifyJs4
:dominifyJs5
:dominifyJs6
:dominifyJs7
:dominifyJs8
:dominifyJs9
:individualJsMinify
:war
[/code]
Các file Javascript, CSS đã được minify trong thư mục build/minified sẽ được copy khi tạo file Java WAR.

Conclusion

Như trên mình đã trình bày các bước thực hiện minify các file Javascript, CSS sử dụng Gradle.
Rất mong sự phản hồi, đóng góp từ các bạn.

Tham khảo

  • http://www.bhaweshkumar.com/blog/2014/08/29/minify-javascript-and-css-using-gradle/
  • https://discuss.gradle.org/t/add-generated-files-with-gradle-before-war-creation/7134