kodingup.camp

Beranda/Kualitas Web: Aksesibilitas, Performa, Keamanan, Testing & Tooling

Linter & Formatter

Modul 7 dari 86 menit bacaLinting and Formatting

Isi modul

    Kenapa ini penting

    Bayangkan sebuah redaksi koran. Ada korektor yang membaca naskah untuk mencari salah ketik, kalimat ambigu, atau fakta yang janggal. Ada juga penata letak yang memastikan semua artikel memakai font, ukuran, dan jarak paragraf yang sama, siapa pun penulisnya. Keduanya bekerja sebelum koran naik cetak, sehingga pembaca tidak pernah melihat kekacauan.

    Di dunia kode, korektor itu bernama linter dan penata letak itu bernama formatter:

    Manfaatnya terasa begitu kamu bekerja dalam tim. Review kode tidak lagi diisi debat "pakai kutip satu atau dua?", karena Prettier yang memutuskan. Bug kecil tertangkap di editor sebelum sempat jalan di browser. Diff di Git hanya berisi perubahan yang bermakna, bukan pergeseran spasi. MDN Curriculum memasukkan topik ini ke modul CSS tooling dan Other tooling types karena hampir semua proyek profesional memakainya sejak hari pertama.

    Konsep inti

    ESLint 10 dan flat config

    ESLint adalah linter JavaScript paling populer. Versi saat ini 10.13, membutuhkan Node.js ^20.19.0, ^22.13.0, atau >=24. Sejak versi 9, ESLint memakai format konfigurasi flat config: satu file eslint.config.js yang mengekspor array objek konfigurasi. Format lama .eslintrc.json yang masih sering muncul di tutorial lama adalah sistem yang sudah ditinggalkan. Kalau menemukannya, ikuti panduan migrasi di eslint.org.

    Cara tercepat memulai adalah npm init @eslint/config@latest, yang menanyakan beberapa pertanyaan lalu membuat file konfigurasi. Struktur flat config:

    Kunci Fungsi
    files Pola file yang dikenai objek ini, misalnya ['**/*.js']
    ignores Pola file yang dilewati. Objek yang hanya berisi ignores berlaku global
    plugins + extends Memakai kumpulan aturan siap pakai, misalnya extends: ['js/recommended']
    languageOptions.globals Variabel global yang dikenal: globals.browser (window, document) atau globals.node (process)
    rules Mengatur aturan satu per satu: 'off', 'warn', atau 'error'

    Objek dibaca berurutan, dan objek belakangan menimpa yang di depan untuk file yang sama. Helper defineConfig dari eslint/config memberi bantuan autocomplete di editor dan mendukung extends.

    Beberapa aturan yang sangat berguna untuk pemula: no-unused-vars (variabel tidak terpakai), no-undef (variabel tidak dikenal, sering karena salah ketik), eqeqeq (wajib ===), dan no-console (opsional, mengingatkan console.log yang terlupa).

    Prettier: formatter yang beropini

    Prettier (versi 3.9) sengaja memberi sangat sedikit pilihan. Filosofinya: daripada tim berdebat soal gaya, serahkan saja ke Prettier. Dokumentasi resminya menyarankan menginstal versi pasti (--save-exact), karena versi minor yang berbeda bisa memformat sedikit berbeda, dan semua anggota tim harus memakai versi yang sama.

    Dua perintah utama:

    Opsi yang umum diubah di .prettierrc.json: singleQuote, semi, printWidth, trailingComma. File .prettierignore menentukan file yang tidak diformat (folder dist misalnya).

    Linter dan formatter tidak boleh berebut

    ESLint dulu punya banyak aturan gaya (indentasi, kutip). Kalau ESLint dan Prettier sama-sama mengatur hal itu, keduanya bisa saling bertentangan. Solusinya: pasang eslint-config-prettier, yang mematikan semua aturan ESLint yang bertabrakan dengan Prettier. Hasilnya pembagian tugas yang jelas: ESLint untuk kualitas, Prettier untuk tampilan.

    Stylelint untuk CSS

    Stylelint (versi 17.16) adalah linter untuk CSS (juga SCSS dengan konfigurasi tambahan stylelint-config-standard-scss). Konfigurasi standar stylelint-config-standard menangkap hal seperti properti yang salah ketik (colr), selector duplikat, satuan pada nol (0px → 0), dan warna hex yang bisa dipendekkan. Quick start resminya npm create stylelint@latest. Konfigurasi manualnya berupa file stylelint.config.mjs.

    Format on save di VS Code

    Supaya kamu tidak perlu mengingat menjalankan perintah, biarkan editor yang bekerja. Pasang ekstensi ESLint (Microsoft), Prettier - Code formatter, dan Stylelint, lalu simpan pengaturan di .vscode/settings.json proyek agar seluruh tim memakai aturan yang sama. Setiap kali menekan Ctrl+S (Cmd+S di Mac), file diformat dan masalah yang bisa diperbaiki otomatis langsung dibereskan.

    Pre-commit hook: penjaga gerbang terakhir

    Tidak semua orang memasang ekstensi editor. Git hook adalah script yang dijalankan Git pada momen tertentu, misalnya sebelum commit. Kombinasi yang direkomendasikan dokumentasi Prettier adalah:

    Kalau ESLint menemukan error, commit dibatalkan sampai kamu memperbaikinya. Saat kami mencobanya, commit yang berisi if (x == 2) langsung ditolak dengan pesan Expected '===' and instead saw '==' dan husky - pre-commit script failed.

    Contoh kode

    Instal semua alat:

    npm install -D eslint @eslint/js globals eslint-config-prettier
    npm install -D --save-exact prettier
    npm install -D stylelint stylelint-config-standard
    

    Konfigurasi ESLint (flat config):

    // eslint.config.js
    import { defineConfig } from 'eslint/config';
    import js from '@eslint/js';
    import globals from 'globals';
    import prettier from 'eslint-config-prettier/flat';
    
    export default defineConfig([
      // Objek berisi ignores saja = berlaku global
      { ignores: ['dist/', 'playwright-report/', 'test-results/'] },
      {
        files: ['**/*.js'],
        plugins: { js },
        extends: ['js/recommended'],                    // aturan rekomendasi bawaan
        languageOptions: { globals: globals.browser },  // kenal window, document
        rules: {
          eqeqeq: 'error',
          'no-unused-vars': 'warn',
        },
      },
      {
        // File konfigurasi & test E2E berjalan di Node, bukan di browser
        files: ['*.config.js', 'e2e/**/*.js'],
        languageOptions: { globals: globals.node },     // kenal process
      },
      prettier, // TERAKHIR: matikan aturan gaya yang bentrok dengan Prettier
    ]);
    
    // .prettierrc.json
    {
      "singleQuote": true,
      "semi": true,
      "printWidth": 90
    }
    
    // stylelint.config.mjs
    /** @type {import('stylelint').Config} */
    export default {
      extends: ['stylelint-config-standard'],
      rules: {
        'selector-class-pattern': null, // izinkan nama class bebas (mis. bahasa Indonesia)
      },
    };
    

    Sekarang lihat alat-alat itu bekerja pada kode yang sengaja dibuat berantakan:

    // src/bad.js
    const harga = 1000
    let diskon = 0.1
    if (harga == "1000") {
      console.log("sama")
    }
    
    npx eslint .
    # → src/bad.js
    # →   2:5   warning  'diskon' is assigned a value but never used  no-unused-vars
    # →   3:11  error    Expected '===' and instead saw '=='          eqeqeq
    # → ✖ 2 problems (1 error, 1 warning)
    
    npx prettier src/bad.js        # tampilkan hasil format tanpa menyimpan
    # → const harga = 1000;
    # → let diskon = 0.1;
    # → if (harga == '1000') {
    # →   console.log('sama');
    # → }
    

    Perhatikan: Prettier merapikan titik koma dan kutip, tapi tidak memperbaiki ==. Itu tugas ESLint. Pembagian tugasnya terlihat jelas.

    /* src/bad.css */
    .kartu {
      color: #FFFFFF;
      colr: red;
      margin: 0px;
    }
    .kartu {
      padding: 1rem
    }
    
    npx stylelint "src/**/*.css"
    # → src/bad.css
    # →   2:10  ✖  Expected "#FFFFFF" to be "#FFF"                    color-hex-length
    # →   3:3   ✖  Unknown property "colr"                            property-no-unknown
    # →   4:12  ✖  Disallowed unit                                    length-zero-no-unit
    # →   6:1   ✖  Duplicate selector ".kartu", first used at line 1  no-duplicate-selectors
    # →   6:1   ✖  Expected empty line before rule                    rule-empty-line-before
    # → ✖ 5 problems (5 errors, 0 warnings)
    # →   3 errors potentially fixable with the "--fix" option.
    
    npx stylelint "src/**/*.css" --fix   # perbaiki yang bisa diperbaiki otomatis
    # → sisa 2 error (colr & selector duplikat) harus diperbaiki manusia
    

    Pengaturan editor untuk seluruh tim:

    // .vscode/settings.json
    {
      "editor.formatOnSave": true,
      "editor.defaultFormatter": "esbenp.prettier-vscode",
      "editor.codeActionsOnSave": {
        "source.fixAll.eslint": "explicit",
        "source.fixAll.stylelint": "explicit"
      },
      "css.validate": false
    }
    

    (css.validate: false mematikan validasi CSS bawaan VS Code supaya tidak dobel dengan Stylelint.)

    Script di package.json dan pre-commit hook:

    npm pkg set scripts.lint="eslint . && stylelint \"src/**/*.css\""
    npm pkg set scripts.format="prettier . --write"
    
    git init                                   # husky butuh repositori Git
    npm install -D husky lint-staged
    npx husky init                             # membuat .husky/pre-commit + script "prepare"
    node --eval "fs.writeFileSync('.husky/pre-commit','npx lint-staged\n')"
    
    // tambahkan di package.json
    {
      "lint-staged": {
        "*.js": ["eslint --fix", "prettier --write"],
        "*.css": ["stylelint --fix", "prettier --write"]
      }
    }
    
    git add .
    git commit -m "fitur form"
    # → ✔ eslint --fix
    # → ✔ stylelint --fix
    # → ✔ prettier --write
    # → (kalau ada error ESLint: "husky - pre-commit script failed" dan commit dibatalkan)
    

    Kesalahan umum

    1. Mengikuti tutorial lama dengan .eslintrc.json. ESLint 10 memakai eslint.config.js (flat config). Cek tanggal tutorial dan selalu rujuk eslint.org.
    2. ESLint dan Prettier saling bertengkar. Simpan file, format berubah, ESLint protes, begitu terus. Pasang eslint-config-prettier dan letakkan paling akhir di array konfigurasi.
    3. 'process' is not defined di file konfigurasi. File seperti playwright.config.js berjalan di Node. Tambahkan objek konfigurasi dengan globals.node untuk file-file itu.
    4. Mematikan aturan setiap kali muncul error. Peringatan linter biasanya benar. Pahami dulu alasannya. Kalau memang perlu pengecualian, nonaktifkan untuk satu baris saja dengan komentar // eslint-disable-next-line nama-aturan beserta alasannya.
    5. Versi Prettier berbeda antar-anggota tim. Hasil format berbeda, diff jadi kotor. Pakai --save-exact dan commit package-lock.json.

    Latihan

    1. Mudah, Jalankan ESLint pada kode berikut dan sebutkan masalah yang dilaporkan: function hitung(a, b) { let hasil = a + b; return a * b; } (dengan konfigurasi di atas).
    2. Sedang, Tambahkan aturan no-console sebagai peringatan, kecuali untuk console.warn dan console.error, hanya untuk file di folder src/.
    3. Menantang, Proyekmu memakai SCSS. Ubah konfigurasi Stylelint agar memeriksa file .scss, lalu tambahkan entri lint-staged untuknya.
    Lihat solusi

    1. ESLint melapor 'hasil' is assigned a value but never used (warning no-unused-vars). Kemungkinan besar ini bug: fungsi bernama "hitung" yang menghitung hasil = a + b tapi mengembalikan a * b. Linter tidak tahu mana yang benar, tapi membuatmu berhenti dan berpikir.

    2.

    // tambahkan objek ini di eslint.config.js (sebelum prettier)
    {
      files: ['src/**/*.js'],
      rules: {
        'no-console': ['warn', { allow: ['warn', 'error'] }],
      },
    },
    

    3.

    npm install -D stylelint-config-standard-scss
    
    // stylelint.config.mjs
    export default {
      extends: ['stylelint-config-standard-scss'], // sudah mencakup config standar + aturan SCSS
    };
    
    {
      "lint-staged": {
        "*.js": ["eslint --fix", "prettier --write"],
        "*.{css,scss}": ["stylelint --fix", "prettier --write"]
      }
    }
    

    Jalankan dengan npx stylelint "src/**/*.{css,scss}".

    Ringkasan

    Video pendamping

    Kalau penjelasan di atas belum masuk, tonton ini. Video dari kanal YouTube pihak lain.

    3. How to Set Up ESLint 9 with Prettier in Node.js (Flat Config + VS Code Auto-Format)Leela Web Dev · Bahasa InggrisBuka di YouTube

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.