Lompat ke konten
dokumentasi.id
Commit 83fc07e
v2
Star3,5 rb

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-21).

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.

TaskTargetBerkas masukan → keluaranRujukan
lessbuildsrc/less/waves.less → dist/waves.cssGruntfile.js:6-11
lesstestsrc/less/waves.less → tests/less/waves.cssGruntfile.js:12-16
cssmintargetdist/waves.css dan tiga CSS test → empat berkas .min.css, dengan sourceMap: falseGruntfile.js:19-31
jshintdaftar berkasgruntfile.js, src/js/*.jsGruntfile.js:33-46
uglifyjssrc/js/waves.js → dist/waves.min.js plus dist/waves.min.js.mapGruntfile.js:48-70
copyjssrc/js/waves.js → dist/waves.jsGruntfile.js:73-79
copydocsdist/waves.min.css, dist/waves.min.js → docs/staticGruntfile.js:80-85
sass-convertberkassrc/scss/*.scss → src/sass, dengan indent: 2Gruntfile.js:88-99
sasstestsrc/**/*.sass dan src/**/*.scss → tests/, dengan ext: '.css'Gruntfile.js:101-111
cleantestmenghapus tests/*Gruntfile.js:113-115
watchscriptsrc/**/*.js, src/**/*.less → menjalankan buildGruntfile.js:117-125
watchgruntGruntfile.js, tanpa daftar tasksGruntfile.js:126-128

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-46). Blok uglify memakai mangle: true dan drop_console: true serta menghasilkan source map dist/waves.min.js.map (Gruntfile.js:48-70).

watch.script memakai spawn: false dengan event added, deleted, dan changed, lalu menjalankan tasks: ['build'] (Gruntfile.js:117-125). watch.grunt hanya memantau Gruntfile.js tanpa daftar tasks, sehingga tidak ada task yang dijalankan ulang saat berkas itu berubah (Gruntfile.js:126-128).

Urutan sebelas langkah build

Task build adalah array berisi sebelas nama task yang dijalankan Grunt secara berurutan (Gruntfile.js:193-205). 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.
Fig. 1: Urutan sebelas langkah task buildAngka 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-205). Karena eksekusinya serial, cssmin selalu melihat dist/waves.css dan tiga CSS test yang sudah selesai ditulis (Gruntfile.js:19-31).

⚠️ copy berada di posisi keempat, sedangkan cssmin di posisi kesembilan (Gruntfile.js:193-205). Target copy:docs menyalin dist/waves.min.css ke docs/static sebelum berkas sumbernya ada (Gruntfile.js:80-85). Pada build bersih hanya dist/waves.min.js yang sudah tersedia saat itu, karena uglify berjalan di posisi ketiga (Gruntfile.js:48-70).

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.
Fig. 2: Perpindahan berkas antar langkah buildSatu 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-151). Task ini tidak memanggil compiler Less, melainkan melakukan empat penggantian regex:

  • /@(?!import|media|keyframes|-)/g diganti $, sehingga variabel Less menjadi variabel SCSS (Gruntfile.js:137).
  • /\.([\w\-]*)\s*\((.*)\)\s*\{/g diganti @mixin $1($2){, sehingga deklarasi mixin dikenali (Gruntfile.js:139).
  • /\.([\w\-]*\(.*\)\s*;)/g diganti @include $1, sehingga pemanggilan mixin berubah bentuk (Gruntfile.js:141).
  • /~(?:\"|\')(.*)(?:\"|\')/g diganti #{"$1"}, misalnya ~'!important' menjadi #{"!important"} (Gruntfile.js:144).

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:146).

sass-convert mengubah src/scss/*.scss menjadi src/sass dengan from: 'scss', to: 'sass', dan indent: 2 (Gruntfile.js:88-99). 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-111). 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-157). 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-173). Bila tidak ada perbedaan, log menulis PASS: conversions generated same CSS (Gruntfile.js:175). Perbandingan isinya dibahas di Verifikasi Kesetaraan CSS.

⚠️ execute:test menyetel failure = true ketika menemukan perbedaan, tetapi tetap memanggil done() tanpa argumen (Gruntfile.js:153-178). Task tidak pernah masuk keadaan gagal, jadi grunt build selesai dengan kode keluar 0 walaupun log memuat ERROR: sass failed test. atau ERROR: scss failed test..

clean:test menjadi langkah penutup dan menghapus tests/* (Gruntfile.js:113-115). 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:207).

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.
Fig. 3: Siklus default, build, dan watchTask 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:207). Setiap perubahan di src/**/*.js atau src/**/*.less menjalankan ulang seluruh rantai build, termasuk clean:test di akhir (Gruntfile.js:117-125).

Paket task yang dimuat

loadNpmTasks memuat sepuluh paket plugin, termasuk grunt-contrib-concat (Gruntfile.js:180-190). Tidak ada blok concat di initConfig maupun pemakaiannya di array build, sehingga paket itu tidak terpakai oleh task mana pun (Gruntfile.js:193-205).