9
Pipeline Build Grunt
Gruntfile.js memegang seluruh proses build Waves. grunt.initConfig mendeklarasikan blok konfigurasi less, cssmin, jshint, uglify, copy, sass-convert, sass, clean, dan watch. Di luar itu ada dua task kustom hasil grunt.registerTask — execute:less2scss dan execute:test — serta dua task rangkaian, build dan default. Versi setiap plugin dikunci di devDependencies, misalnya grunt 1.1.0 dan grunt-contrib-cssmin 3.0.0 (package.json:9-211).
Blok konfigurasi di initConfig
Setiap target sudah dipatok ke path tetap, sehingga grunt build berjalan tanpa argumen path. Tabel berikut memetakan target, berkas masukan, dan berkas keluarannya.
| Task | Target | Berkas masukan → keluaran | Rujukan |
|---|---|---|---|
less | build | src/less/waves.less → dist/waves.css | Gruntfile.js:6-112 |
less | test | src/less/waves.less → tests/less/waves.css | Gruntfile.js:12-163 |
cssmin | target | dist/waves.css dan tiga CSS test → empat berkas .min.css, dengan sourceMap: false | Gruntfile.js:19-314 |
jshint | daftar berkas | gruntfile.js, src/js/*.js | Gruntfile.js:33-465 |
uglify | js | src/js/waves.js → dist/waves.min.js plus dist/waves.min.js.map | Gruntfile.js:48-706 |
copy | js | src/js/waves.js → dist/waves.js | Gruntfile.js:73-797 |
copy | docs | dist/waves.min.css, dist/waves.min.js → docs/static | Gruntfile.js:80-858 |
sass-convert | berkas | src/scss/*.scss → src/sass, dengan indent: 2 | Gruntfile.js:88-999 |
sass | test | src/**/*.sass dan src/**/*.scss → tests/, dengan ext: '.css' | Gruntfile.js:101-11110 |
clean | test | menghapus tests/* | Gruntfile.js:113-11511 |
watch | script | src/**/*.js, src/**/*.less → menjalankan build | Gruntfile.js:117-12512 |
watch | grunt | Gruntfile.js, tanpa daftar tasks | Gruntfile.js:126-12813 |
jshint menulis nama berkas pertamanya sebagai gruntfile.js dengan huruf kecil, berbeda kapitalisasi dari Gruntfile.js di akar repository, dan mengisi reporterOutput dengan string kosong agar laporan tidak ditulis ke berkas (Gruntfile.js:33-465). Blok uglify memakai mangle: true dan drop_console: true serta menghasilkan source map dist/waves.min.js.map (Gruntfile.js:48-706).
watch.script memakai spawn: false dengan event added, deleted, dan changed, lalu menjalankan tasks: ['build'] (Gruntfile.js:117-12512). watch.grunt hanya memantau Gruntfile.js tanpa daftar tasks, sehingga tidak ada task yang dijalankan ulang saat berkas itu berubah (Gruntfile.js:126-12813).
Urutan sebelas langkah build
Task build adalah array berisi sebelas nama task yang dijalankan Grunt secara berurutan (Gruntfile.js:193-20514). Konvensi warna di seluruh halaman ini: hijau untuk langkah produksi yang harus lulus, ungu untuk berkas turunan, oranye untuk konfigurasi dan langkah yang perlu kehati-hatian, merah untuk langkah destruktif.
graph TD
LESS_BUILD["1. less:build"] --> JSHINT["2. jshint"]
JSHINT --> UGLIFY["3. uglify"]
UGLIFY --> COPY["4. copy"]
COPY --> LESS2SCSS["5. execute:less2scss"]
LESS2SCSS --> SASSCONVERT["6. sass-convert"]
SASSCONVERT --> SASS_TEST["7. sass:test"]
SASS_TEST --> LESS_TEST["8. less:test"]
LESS_TEST --> CSSMIN["9. cssmin"]
CSSMIN --> EXEC_TEST["10. execute:test"]
EXEC_TEST --> CLEAN_TEST["11. clean:test"]
style LESS_BUILD fill:#2d7d46,color:#fff
style JSHINT fill:#2d7d46,color:#fff
style UGLIFY fill:#2d7d46,color:#fff
style COPY fill:#2d7d46,color:#fff
style LESS2SCSS fill:#f59e0b,color:#000
style SASSCONVERT fill:#8b5cf6,color:#fff
style SASS_TEST fill:#2d7d46,color:#fff
style LESS_TEST fill:#2d7d46,color:#fff
style CSSMIN fill:#2d7d46,color:#fff
style EXEC_TEST fill:#f59e0b,color:#000
style CLEAN_TEST fill:#dc2626,color:#fff
%% fig: Urutan sebelas langkah task build
%% desc: Angka pada node mengikuti posisi elemen array build, dari less:build sampai clean:test.Nomor pada diagram mengikuti posisi elemen di array, bukan ketergantungan antar task: sass:test dan less:test sebenarnya saling lepas dan hanya kebetulan berurutan (Gruntfile.js:193-20514). Karena eksekusinya serial, cssmin selalu melihat dist/waves.css dan tiga CSS test yang sudah selesai ditulis (Gruntfile.js:19-314).
⚠️
copyberada di posisi keempat, sedangkancssmindi posisi kesembilan (Gruntfile.js:193-20514). Targetcopy:docsmenyalindist/waves.min.csskedocs/staticsebelum berkas sumbernya ada (Gruntfile.js:80-858). Pada build bersih hanyadist/waves.min.jsyang sudah tersedia saat itu, karenauglifyberjalan di posisi ketiga (Gruntfile.js:48-706).
Aliran berkas antar langkah
Satu berkas Less menjadi sumber tiga jalur sekaligus: CSS distribusi, CSS test untuk Less, dan SCSS yang kemudian diturunkan menjadi SASS.
graph LR
LESS["src/less/waves.less"] -->|"less:build"| DCSS["dist/waves.css"]
LESS -->|"less:test"| TCSS["tests/less/waves.css"]
LESS -->|"execute:less2scss"| SCSS["src/scss/waves.scss"]
SCSS -->|"sass-convert"| SASSD["src/sass/waves.sass"]
SCSS -->|"sass:test"| TSCSS["tests/scss/waves.css"]
SASSD -->|"sass:test"| TSASS["tests/sass/waves.css"]
DCSS -->|"cssmin"| MIN["dist/waves.min.css"]
TCSS -->|"cssmin"| TMIN_LE["tests/less/waves.min.css"]
TSCSS -->|"cssmin"| TMIN_SC["tests/scss/waves.min.css"]
TSASS -->|"cssmin"| TMIN_SA["tests/sass/waves.min.css"]
TMIN_LE -->|"dibaca"| EXEC["execute:test"]
TMIN_SC -->|"dibaca"| EXEC
TMIN_SA -->|"dibaca"| EXEC
EXEC -->|"lalu"| CLEAN["clean:test"]
style LESS fill:#f59e0b,color:#000
style SCSS fill:#f59e0b,color:#000
style DCSS fill:#8b5cf6,color:#fff
style TCSS fill:#8b5cf6,color:#fff
style SASSD fill:#8b5cf6,color:#fff
style TSCSS fill:#8b5cf6,color:#fff
style TSASS fill:#8b5cf6,color:#fff
style MIN fill:#8b5cf6,color:#fff
style TMIN_LE fill:#8b5cf6,color:#fff
style TMIN_SC fill:#8b5cf6,color:#fff
style TMIN_SA fill:#8b5cf6,color:#fff
style EXEC fill:#2d7d46,color:#fff
style CLEAN fill:#dc2626,color:#fff
%% fig: Perpindahan berkas antar langkah build
%% desc: Satu berkas Less menghasilkan CSS distribusi, SCSS, dan SASS; empat berkas min dari cssmin dibaca execute:test sebelum clean:test menghapus semuanya.Berkas dist/ yang dihasilkan rantai ini dirinci di Artefak Distribusi.
Konversi Less ke SCSS dan SASS
execute:less2scss membaca src/less/waves.less sebagai teks lalu menulis src/scss/waves.scss (Gruntfile.js:132-15115). Task ini tidak memanggil compiler Less, melainkan melakukan empat penggantian regex:
/@(?!import|media|keyframes|-)/gdiganti$, sehingga variabel Less menjadi variabel SCSS (Gruntfile.js:13716)./\.([\w\-]*)\s*\((.*)\)\s*\{/gdiganti@mixin $1($2){, sehingga deklarasi mixin dikenali (Gruntfile.js:13917)./\.([\w\-]*\(.*\)\s*;)/gdiganti@include $1, sehingga pemanggilan mixin berubah bentuk (Gruntfile.js:14118)./~(?:\"|\')(.*)(?:\"|\')/gdiganti#{"$1"}, misalnya~'!important'menjadi#{"!important"}(Gruntfile.js:14419).
Komentar di dalam task mengakui batas pendekatan ini: NOTE: for true less->scss transpiling we'd need to replace spin to adjust-hue (not needed but anyway) (Gruntfile.js:14620).
sass-convert mengubah src/scss/*.scss menjadi src/sass dengan from: 'scss', to: 'sass', dan indent: 2 (Gruntfile.js:88-999). sass:test lalu mengompilasi src/**/*.sass dan src/**/*.scss ke tests/ dengan ext: '.css', sehingga muncul tests/sass/waves.css dan tests/scss/waves.css (Gruntfile.js:101-11110). Isi ketiga sumber gaya itu dibahas di Sistem Gaya Less, SCSS, dan SASS.
Verifikasi kesetaraan CSS dan pembersihan
execute:test membaca tiga berkas min hasil cssmin: tests/less/waves.min.css, tests/sass/waves.min.css, dan tests/scss/waves.min.css (Gruntfile.js:155-15721). Ketiganya dibandingkan berpasangan; setiap perbedaan memicu grunt.log.writeln dengan pesan ERROR: sass failed test., ERROR: scss failed test., atau WARNING: sass files aren't equal? (Gruntfile.js:159-17322). Bila tidak ada perbedaan, log menulis PASS: conversions generated same CSS (Gruntfile.js:17523). Perbandingan isinya dibahas di Verifikasi Kesetaraan CSS.
⚠️
execute:testmenyetelfailure = trueketika menemukan perbedaan, tetapi tetap memanggildone()tanpa argumen (Gruntfile.js:153-17824). Task tidak pernah masuk keadaan gagal, jadigrunt buildselesai dengan kode keluar 0 walaupun log memuatERROR: sass failed test.atauERROR: scss failed test..
clean:test menjadi langkah penutup dan menghapus tests/* (Gruntfile.js:113-11511). Setelah build selesai tidak ada lagi berkas di tests/, jadi grunt execute:test tidak bisa diulang tanpa menjalankan build lagi. Direktori hasil ini memang diabaikan Git: .gitignore:34-38 mencantumkan docs/static/waves* dan tests/.
Task default dan watch
Task default hanya berisi dua elemen: build lalu watch (Gruntfile.js:20725).
graph LR
DEFAULT["grunt default"] --> BUILD["build"]
BUILD --> WATCH["watch"]
WATCH -->|"src/**/*.js atau src/**/*.less berubah"| BUILD
WATCH -->|"Gruntfile.js berubah"| GRUNT_W["watch.grunt tanpa tasks"]
style DEFAULT fill:#f59e0b,color:#000
style BUILD fill:#2d7d46,color:#fff
style WATCH fill:#f59e0b,color:#000
style GRUNT_W fill:#f59e0b,color:#000
%% fig: Siklus default, build, dan watch
%% desc: Task default menjalankan build sekali, lalu watch memicu build ulang setiap kali berkas JS atau Less berubah.Karena default memanggil build lebih dulu, satu kali grunt tanpa nama task sudah menghasilkan artefak lengkap sebelum watch masuk mode memantau (Gruntfile.js:20725). Setiap perubahan di src/**/*.js atau src/**/*.less menjalankan ulang seluruh rantai build, termasuk clean:test di akhir (Gruntfile.js:117-12512).
Paket task yang dimuat
loadNpmTasks memuat sepuluh paket plugin, termasuk grunt-contrib-concat (Gruntfile.js:180-19026). Tidak ada blok concat di initConfig maupun pemakaiannya di array build, sehingga paket itu tidak terpakai oleh task mana pun (Gruntfile.js:193-20514).