Don't break rules: ESLint (1) - Basics
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.
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.
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.
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:
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.
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:
kuralı, ifade sonlarına noktalı virgül konulmasını zorunlu kılar ya da kullanımını engeller.semi
kuralı,no-var
yerinevar
ya dalet
kullanılmasını zorunlu kılar ya daconst
anahtar kelimesine izin verir.var
Artık kurallarımızı etkinleştirelim.
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:
ya da"off"
-- kuralı kapatır0
ya da"warn"
-- kuralı uyarı verecek biçimde etkinleştirir1
ya da"error"
-- kuralı hata verecek biçimde etkinleştirir2
Bazı kurallar ise özelleştirebilmemize imkan sağlar. Farklı kullanım biçimlerini görmek için farklı kural tanımlarına bakalım.
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.
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.
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.
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.
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.js1/* 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.js1/* 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.
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.
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.