Tag logo

Don't break rules: ESLint (1) - Basics

Aug 11, 2024/
#eslint
/-8 min

Bir zamanlar front-end'çilerin bir takım problemleri vardı. Kodlardaki syntax hatalarını görmek zordu, projelerindeki yazılım dilinin standardı yoktu ve bir yazılımcının

if
dediğine diğer
ternary
diyordu. Dolayısıyla codebase'i kontrol eden bir araca ihtiyaç vardı.

Bunu gören Nicholas C. Zakas duruma el attı ve ESLint’i yarattı.

What is ESLint?

ESLint, kodları belirli kurallara göre analiz eden ve tespit ettiği problemleri belirlediğimiz kurallar çerçevesinde çözen Javascript aracıdır.

Statik bir analiz yaptığı için kodları çalıştırmadan bir takım problemleri keşfeder. Örneğin, bir

for
döngüsünde değişken tanımlamayı unutursanız veya sonsuz döngüye girerseniz sizi uyarır:

1// ESLint: The update clause in this loop moves the variable
2// in the wrong direction. (for-direction)
3for (i = 100; i >= 0; i++) {
4  // ESLint: 'i' is not defined. (no-undef)
5  console.log(`Sayı: ${i}`);
6}

Hatalara karşı tavrı nettir. Bir gün taskınızı bitirmişsinizdir, arkanıza yaslanıp commit atarsınız ve ESLint kapınızı çalar:

Setup Playground Project

Yazı boyunca örnekleri takip etmenizi istiyorum ve gerekli ortamı hazırlamak için alttaki talimatları takip edin.

1# istediğimiz bir dizinde klasör oluşturalım
2$ mkdir example-eslint-project && cd example-eslint-project
3# klasörümüzü npm projesine çevirelim.
4$ npm init -y
5# eslint paketini sadece localde çalışacağı deployment'a
6# dahil edilmeyeceği için devDependency olarak ekleyelim
7$ npm i eslint -D
8# eslint konfigürasyonu yapacağımız dosyayı oluşturmak
9# üzere hazırlanan programı kullanalım
10$ npm init @eslint/config
? How would you like to use ESLint?
  ✔ To check syntax and find problems
? What type of modules does your project use?
  ✔ JavaScript modules (import/export)
? Which framework does your project use?
  ✔ None of these
? Does your project use TypeScript?
  ✔ No
? Where does your code run? >
  ✔ Node
? What format do you want your config file to be in?
  ✔ JavaScript

İşlemlerin sonucunda

.eslintrc.js
dosyası oluşturulur. Bu dosya, ESLint'i konfigüre edeceğimiz yerdir.

.eslintrc.js
1module.exports = {
2  env: {
3    // eslint'in global değişkenleri anlayabilmesi için gerekli
4    // seçenekleri veririz. projede es2021 kullanıldığı ve
5    // node kodları barındırdığını söyleyeceğiz.
6    es2021: true,
7    node: true,
8  },
9  // eslint'in kodları neye göre parse edeceğini belirtiriz.
10  parserOptions: {
11    ecmaVersion: "latest",
12    sourceType: "module",
13  },
14  // önceden tanımlanmış kuralları import etmemizi sağlar.
15  // örnekte eslint ekibinin önerdiği kuralları import ediyoruz.
16  extends: ["eslint:recommended"],
17  // kurallar ile eslintin ilgili sözdizimler karşısında nasıl
18  // davranacağını belirleriz.
19  rules: {},
20};

Şimdilik başka hatalarla uğraşmadan ana konuya odaklanabilmek için

eslint:recommended
'ı kaldıracağız.

.eslintrc.js
1module.exports = {
2  env: {
3    es2021: true,
4    node: true,
5  },
6  parserOptions: {
7    ecmaVersion: "latest",
8    sourceType: "module",
9  },
10  extends: [],
11  rules: {},
12};

Konfigürasyonu ayrı dosyaya çıkarmak yerine

package.json
'un
eslintConfig
alanını da kullanabiliriz. Daha derli toplu durması ve sorumlulukların ayrılması ilkesi gereği
.eslintrc.js
ile ilerlemek sağlıklıdır.

package.json
1{
2  "name": "example-eslint-project",
3  "version": "1.0.0",
4  ...
5  "eslintConfig": {
6    "env": {
7        "es2021": true,
8        "node": true
9    },
10    "parserOptions": {
11        "ecmaVersion": "latest",
12        "sourceType": "module"
13    },
14    "extends": [],
15    "rules": {}
16  }
17}

Rules

ESLint'in bazı sözdizimleri karşısında nasıl davranacağını kurallar tanımlar.

1// usage 1
2if (status === LoginStatus.LOGGED_OUT) {
3  redirect("/login");
4}
5
6// usage 2
7if (status === LoginStatus.LOGGED_OUT)
8  redirect("/login");
9
10// usage 3
11if (status === LoginStatus.LOGGED_OUT) redirect("/login");

Örneğin yukarıdaki kullanımları kurala göre analiz eder ve belirlediğiniz davranışa göre aksiyon alır. Örneğin, kuralı "tek satır kod barındırıyorsa süslü parantez ile karşılaşırsan hata ver" şeklinde konfigüre ettiysek örnekteki ilk iki kullanım için hata alırız. Ardından otomatik formatlayabilirliğini kontrol eder.

Define rule

Basit bir toplama fonksiyonu üzerinden ilerleyelim:

src/sum.js
1var sum = (num1, num2) => {
2  return num1 + num2;
3};

Fonksiyonu incelersek göze çarpan ilk şey

var
kullanımıdır. "Bu devirde hala kullanan kaldı mı?" dediğinizi duyar gibiyim, hala aramızdalar! İkincisi ise noktalı virgül kullanılmamasıdır. Bazı insanlar sever bazı insanlar sevmez ancak otomatik formatlama hatalarının önüne geçmek için kullanmamızın yararı var. Dolayısıyla noktalı virgülün daima konulması ve
var
kullanılmamasına yönelik iki kural tanımlayacağız.

Kuralların arkaplanda nasıl çalıştığına serinin diğer yazılarında değineceğiz. Şimdilik implementasyonuna odaklanalım.

ESLint'te built-in kurallar tanımlanılmıştır.

React
,
Typescript
gibi paketlere özgü kurallar için ekstra npm paketleri indirmemiz gerekir. İsteğimizle örtüşen ESLint kurallarına wiki'den bakarsak:

  • semi
    kuralı, ifade sonlarına noktalı virgül konulmasını zorunlu kılar ya da kullanımını engeller.
  • no-var
    kuralı,
    var
    yerine
    let
    ya da
    const
    kullanılmasını zorunlu kılar ya da
    var
    anahtar kelimesine izin verir.

Artık kurallarımızı etkinleştirelim.

.eslintrc.js
1module.exports = {
2  // ...
3  rules: {
4    semi: "error",
5    "no-var": "error",
6  },
7};

ESLint kurallara verilen değerlere göre üç farklı şekilde davranır:

  • "off"
    ya da
    0
    -- kuralı kapatır
  • "warn"
    ya da
    1
    -- kuralı uyarı verecek biçimde etkinleştirir
  • "error"
    ya da
    2
    -- kuralı hata verecek biçimde etkinleştirir

Bazı kurallar ise özelleştirebilmemize imkan sağlar. Farklı kullanım biçimlerini görmek için farklı kural tanımlarına bakalım.

.eslintrc.js
1module.exports = {
2  // ...
3  rules: {
4    "no-restricted-syntax": "off",
5    // kuralların hata değil uyarı vermesini istiyorsak 'warn' verebiliriz.
6    // bu kuralları düzeltme zorunluluğumuz yoktur.
7    "spaced-comment": "warn",
8    // "semi": ["error", "always"] şeklinde de yazabilirdik ancak varsayılan
9    // değer 'always' olduğu için yazılmadan geçilebilir.
10    semi: "error",
11    quotes: ["error", "double"],
12    // bazı kurallar `options` parametresi kabul eder.
13    camelcase: ["error", { ignoreDestructuring: true }],
14  },
15};

Örneğimize geri dönüp tanımladığımız kurallarla birlikte kodumuzu ESLint'e analiz ettirelim.

1$ npx eslint src/sum.js
/Users/enes.baspinar/Projects/posts-codes/example-eslint-project/src/sum.js
    1:1   error  Unexpected var, use let or const instead  no-var
    2:21  error  Missing semicolon                         semi
    3:2   error  Missing semicolon                         semi

✖ 3 problems (3 errors, 0 warnings)
    3 errors and 0 warnings potentially fixable with the '--fix' option.

Üç adet hata üretti. Bunları elle düzeltebiliriz falan filan ama analizi yapan araç bunu da düzeltemez mi? Pekala düzeltebilir. Dökümantasyona bakarsak bazı kuralların yanlarında ingiliz anahtarı olduğunu görebilirsiniz. Bu "fixable" olduğunu yani otomatik düzeltilebildiği anlamına gelir. Kullandığımız iki kural da bu şekildedir.

"Fixable" olarak belirtilen kurallar komuta

--fix
bayrağı eklenerek düzeltilebilir. Öncesinde kodumuza tekrar bakalım.

src/sum.js
1var sum = (num1, num2) => {
2  return num1 + num2;
3};

Şimdi yeni bayrakla birlikte kodumuzu tekrar çalıştıralım.

1$ npx eslint src/sum.js --fix

src/sum.js
dosyasına yeniden baktığımızda değiştiğini görebiliriz.

src/sum.js
1let sum = (num1, num2) => {
2  return num1 + num2;
3};

Muazzam bir şey değil mi?

VSCode ESLint Extension

ESLint paketi bize lint özelliği sağlarken, VSCode eklentisi kod yazarken canlı bir şekilde otomatik lint özelliği sağlar ve hataları arayüzde görselleştirir.

Hemen indirip deneyelim.

İndirdikten sonra

src/sum.js
dosyamızı ilk haline getirip eklentinin sihirine kapılalım.

Bu menüyü fareyle açmak zorunda değilsiniz. Klavyeden

CTRL/CMD + .
kombinasyonunu kullanabilirsiniz.

Peki bizim için son bir şarkı çalıp

CTRL/CMD + S
ile dosyayı kaydettiğimizde tüm düzeltmeleri otomatik yapsa? O halde hemen VSCode ayarlarına girip bir ekleme yapalım.

Dosya her kaydedildiğinde düzeltme yapmasını istemeyeceğimiz durumlar olabilir. Aşağıdaki değişikliği atlayıp VSCode'a sağ tıkladığımızda çıkan menüden "Format Document" seçeneğini kullanabilirsiniz.

settings.json
1{
2  ...
3  "editor.formatOnSave": true,
4  "editor.codeActionsOnSave": {
5    "source.fixAll": true
6  }
7}

Artık dosyayı kaydettiğimizde otomatik düzelttiğini görebiliriz.

Bu yeteneğinin yalnızca küçük bir parçası. Kod yazma hızımızı ne kadar arttıracağını hayal edin. Sık dosya kaydettiğimiz için alışmak güzel bir kazanım olur. Kendimden örnek verecek olursam neredeyse her kelimeden sonra kendimi

CTRL/CMD + S
yaparken buluyorum.

Disable Rules

Pekala artık hatamızı kollayan iki tane kuralımız var ve başımıza bela oldular. Bundan kurtulmak için, "Kodda sulh, cihanda sulh." ilkesiyle projede özgür takılmamıza izin verecek

freedom.js
isimli bir dosya oluşturalım ve bu dosya, özgür dünyanın projemizdeki temsili olsun. Herkes istediği gibi geliştirme yapabilsin. Üç yöntem vardır:

  • Tüm kuralları tüm dosya için devre dışı bırakabiliriz.

    src/freedom.js
    1/* eslint-disable */
    2
    3var sum = (num1, num2) => {
    4  return num1 + num2;
    5};
  • Tüm kuralları dosyanın bir kısmında devre dışı bırakabiliriz.

    src/freedom.js
    1/* eslint-disable */
    2
    3var sum = (num1, num2) => {
    4  return num1 + num2;
    5};
    6
    7/* eslint-enable */
    8
    9// give error
    10var sqr = (num1) => {
    11  return num1 ** 2;
    12};

Yukarıdaki örneklerde tüm kurallar devre dışı kalır. Spesifik olarak belirtmek istersenz yanlarına kural isimlerini verebilirsiniz.

src/freedom.js
1// eslint-disable-next-line no-var
2var sqr = (num1) => {
3  return num1 ** 2; // eslint-disable-line no-var semi
4}; // give 'semi' error

Summary

ESLint, spesifik kurallar dahilinde kodu analiz eder ve kod stilini belirli kalıplarda tutar. Böylece çok fazla kişinin çalıştığı projelerin her satırı ayrı telden çalmaz. Aynı zamanda noktalı virgül, boşluk gibi çok fazla kullandığınız stillendirmeleri otomatik formatlamak için de faydalıdır.

.eslintrc.js
dosyasından ya da
package.json
dosyasının
eslintConfig
alanından, ESLint'in doğru parse yapabilmesi için gerekli ayarlamalar yapılabilir ve kuralları düzenleyebiliriz.

.eslintrc.js
1module.exports = {
2  env: {
3    es2021: true,
4    node: true,
5  },
6  parserOptions: {
7    ecmaVersion: "latest",
8    sourceType: "module",
9  },
10  rules: {
11    semi: "error",
12    "no-var": "error",
13  },
14};

VSCode ESLint eklentini kullanarak çıktıları editörde canlı canlı görebiliriz. Aynı zamanda otomatik formatlamayı dosya kaydedildiğinde veya tuş kombinasyonlarına basıldığında tetikletebiliriz.

İlk yazımız burada biter benden bu kadar. Serinin devamında çok daha fazla şaşıracağınıza taahhüt ediyorum (

git commit -m "Çok daha fazla şaşıracaksınız"
).

Sağlıcakla kalın.