Blok 2 · Ders 14
Modüller ve npm
Kodu dosyalara bölüyor (import/export), npm ile paket kuruyor, package.json ve node_modules'ın ne olduğunu öğreniyorsun.
Bu dersin sonunda
- Kodunu dosyalara bölüp
exportveimportile birbirine bağlayabilirsin - Adlı ve varsayılan dışa aktarmayı ayırt edip doğru
importsatırını yazabilirsin - npm ile proje açıp
package.jsondosyasını okuyabilir,"type": "module"ayarını yapabilirsin - Paket kurup kaldırabilir;
node_modulesvepackage-lock.jsondosyalarının işini açıklayabilirsin - npm betiği yazıp
npm startvenpm runile çalıştırabilirsin - Windows'taki
npm.ps1hatasını çözebilir, kuracağın paketin güvenilir olup olmadığını denetleyebilirsin
Bu sayfada
Şimdiye kadar her programın tek bir dosyadaydı. Gerçek projeler ise onlarca, hatta yüzlerce dosyadan oluşur ve başkalarının yazdığı hazır kodu kullanır. Bu derste kodunu dosyalara bölmeyi (modüller), dünyanın en büyük yazılım paketi deposundan paket kurmayı (npm) ve her JavaScript projesinin kimlik kartı olan package.json dosyasını öğreneceksin.
Neden dosyalara bölmek?
Ders 17'de terminalde oynanan bir oyun yazacaksın: menü, savaş, dükkân, kayıt dosyası. Hepsini tek dosyaya yazarsan dosya kolayca 300 satırı geçer. O zaman şunlar olur:
- Aradığın fonksiyonu bulmak için yüzlerce satır kaydırırsın.
- Savaş kodunu düzeltirken, dükkânın kullandığı aynı adlı bir değişkeni yanlışlıkla bozarsın.
- Dükkân fonksiyonlarını başka bir programda kullanmak için kopyalarsın. Bir hatayı düzeltince bütün kopyaları tek tek düzeltmen gerekir; Ders 3'teki "kendini tekrar etme" kuralı çiğnenmiş olur.
Çözüm, kodu konusuna göre dosyalara bölmek. Her dosya tek bir işe bakar, ana.js hepsini bir araya getirip programı başlatır.
ana.js ötekileri import ile kullanır.Bu dosyaların her birine modül denir.
Dersin klasörü
Bu dersin kodu tek dosyaya sığmayacak, o yüzden ona ayrı bir klasör açıyoruz. VS Code'da C:\kod\ogren açıkken terminale şunları yaz:
PS C:\kod\ogren> mkdir ders14 Directory: C:\kod\ogren Mode LastWriteTime Length Name---- ------------- ------ ----d----- 11.10.2026 19:38 ders14 PS C:\kod\ogren> cd ders14mkdir oluşturduğu klasörü küçük bir tabloyla gösterir (tarih ve saat sende farklı olur). cd ders14 sonrasında istem PS C:\kod\ogren\ders14> olur. Görevlere kadar bütün komutları bu klasörde çalıştıracaksın.
VS Code'un solundaki listede ders14 klasörü belirdi. Üzerine sağ tıkla, New File seç ve dosyaya ana.js adını ver. İçine dükkânın küçük bir hâlini yaz:
const fiyatlar = { "Uzun Kılıç": 350, "Çizme": 300, "Can İksiri": 50} function fiyatBul(esya) { return fiyatlar[esya] ?? 0} console.log("Çizme: " + fiyatBul("Çizme") + " altın")console.log("Uzun Kılıç: " + fiyatBul("Uzun Kılıç") + " altın")Çizme: 300 altınUzun Kılıç: 350 altınfiyatlar[esya] objeden köşeli parantezle okur (Ders 4); boşluk içeren anahtarlar tırnak içinde yazılır. Dükkânda olmayan bir eşya sorulursa undefined gelir, ?? onu 0 yapar (Ders 12). Şimdi bu dükkânı kendi dosyasına taşıyacağız.
İlk modülün: export ve import
ders14 içinde dukkan.js adında yeni bir dosya aç. ana.js'teki ilk dokuz satırı kes ve yeni dosyaya yapıştır (kod taşırken kesip yapıştırmak serbest, yeni bir şey yazmıyorsun). Sonra yeni dosyada function sözcüğünün önüne export yaz. ana.js'te geriye iki console.log satırı kaldı; onların en üstüne de şu satırı ekle:
import { fiyatBul } from "./dukkan.js" console.log("Çizme: " + fiyatBul("Çizme") + " altın")console.log("Uzun Kılıç: " + fiyatBul("Uzun Kılıç") + " altın")İki dosyayı da kaydet ve ana.js'i çalıştır. VS Code'da görüntü şöyle olmalı (düzenleyicide dukkan.js açık):
const fiyatlar = { "Uzun Kılıç": 350, "Çizme": 300, "Can İksiri": 50} export function fiyatBul(esya) { return fiyatlar[esya] ?? 0}PS C:\kod\ogren\ders14> node ana.jsÇizme: 300 altınUzun Kılıç: 350 altınÇıktı aynı; değişen yalnızca düzen. Soldaki listede ders14 klasörünün içi görünüyor.
İki yeni sözcük var:
export(dışa aktar): "bu fonksiyonu başka dosyalar da kullanabilsin" demek.import(içe aktar): "şu dosyadan şunu getir" demek. Node,ana.js'i çalıştırmadan öncedukkan.js'i bulur, okur vefiyatBul'uana.js'in kullanımına verir.
import ve export ile kurulan bu düzenin adı ES modülleri. ES, JavaScript'in resmî kural kitabı olan ECMAScript'in kısaltması; yani bu sistem dilin kendi standardı. Node'un bundan daha eski bir modül sistemi de var, onu biraz sonra tanıyacaksın.
import satırının parçaları. Soldan sağa: ne yapılıyor, ne isteniyor, nereden.Yol kısmı ./ ile başlar: "bu dosyanın yanındaki" demek. Bulunduğun dosyanın yerine göre yazılan bu tür yollara göreli yol (relative path) denir. dukkan.js başka bir yerde olsaydı yolu ona göre yazardın: ders14 içindeki magaza klasöründeyse "./magaza/dukkan.js", bir üst klasördeyse "../dukkan.js" (.. bir üst klasör demek, cd .. komutundaki gibi). Yolun parçalarını Windows'taki gibi ters eğik çizgiyle (\) değil, düz eğik çizgiyle (/) ayırırsın: import yolları her işletim sisteminde aynı yazılır.
Error [ERR_MODULE_NOT_FOUND]: Cannot find moduleNe zaman çıkar? Göreli yolda uzantıyı unutunca ya da dosya adını yanlış yazınca.
import { fiyatBul } from "./dukkan"node:internal/modules/run_main:107 triggerUncaughtException( ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\kod\ogren\ders14\dukkan' imported from C:\kod\ogren\ders14\ana.jsDid you mean to import "./dukkan.js"? at finalizeResolution (node:internal/modules/esm/resolve:272:11) ... Node.js v24.20.0Nasıl düzelir? Node doğrusunu söylüyor: Did you mean to import "./dukkan.js"? ("./dukkan.js'i mi demek istedin?"). Uzantıyı ekle. Bu hatada en üstteki üç satır senin dosyanı değil, Node'un kendi içini gösterir; okumaya Error [...] satırından başla. Dosya adını yanlış yazdığında ("./dukan.js") da aynı hata çıkar, yalnız öneri satırı gelmez: o zaman adı harf harf karşılaştır.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'dukkan.js'Ne zaman çıkar? Kendi dosyanı alırken yolun başına ./ koymayı unutunca.
import { fiyatBul } from "dukkan.js"node:internal/modules/package_json_reader:301 throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'dukkan.js' imported from C:\kod\ogren\ders14\ana.js at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9) ... Node.js v24.20.0Nasıl düzelir? Mesaj "dukkan.js adlı paketi bulamadım" diyor. Başında ./ ya da ../ olmayan her ad Node için bir paket adıdır; paketleri birazdan göreceksin. Kendi dosyanı alırken yolu ./ ile başlat.
TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid moduleNe zaman çıkar? Yolu Windows'taki gibi ters eğik çizgiyle (\) yazınca.
import { fiyatBul } from ".\magaza\dukkan.js"node:internal/modules/package_json_reader:257 throw new ERR_INVALID_MODULE_SPECIFIER( ^ TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid module ".magazadukkan.js" is not a valid package name imported from C:\kod\ogren\ders14\ana.js at parsePackageName (node:internal/modules/package_json_reader:257:11) ... Node.js v24.20.0Nasıl düzelir? Mesajdaki ada bak: .magazadukkan.js. Ters eğik çizgiler kaybolmuş. JavaScript metinlerinde \ özel bir işarettir, yanındaki harfle birlikte okunur ve burada sessizce silindi. Geriye ./ ile başlamayan bir ad kaldığı için Node onu geçersiz bir paket adı saydı. Yolu düz eğik çizgiyle yaz: "./magaza/dukkan.js".
Vitrin ve depo: dışarıya ne açılır?
Bir modül istediği kadar şeyi dışa aktarabilir. dukkan.js'in sonuna ikinci bir fonksiyon ekle:
export function fiyatBul(esya) { return fiyatlar[esya] ?? 0} export function yeterMi(altin, esya) { return altin >= fiyatBul(esya)}yeterMi, aynı dosyadaki fiyatBul'u içe aktarmadan kullanıyor: bir dosyada tanımlanan her şey o dosyanın içinde serbestçe kullanılır. Yalnız fonksiyonlar değil, const ile açılan kutular da dışa aktarılabilir: export const vergi = 10 gibi. ana.js'te iki adı süslü parantezin içinde virgülle ayırıp birlikte al:
import { fiyatBul, yeterMi } from "./dukkan.js" const altin = 300console.log("Çizme: " + fiyatBul("Çizme") + " altın")console.log("Çizmeye yeter mi? " + yeterMi(altin, "Çizme"))console.log("Uzun Kılıç'a yeter mi? " + yeterMi(altin, "Uzun Kılıç"))PS C:\kod\ogren\ders14> node ana.jsÇizme: 300 altınÇizmeye yeter mi? trueUzun Kılıç'a yeter mi? false300 altın, tam 300'lük çizmeye yetiyor, çünkü >= kullandık: fonksiyon sınır değerinde de doğru çalışıyor.
Peki ana.js, dukkan.js'teki fiyatlar objesini doğrudan kullanabilir mi? ana.js'in sonuna console.log(fiyatlar) ekleyip dene:
console.log("Uzun Kılıç'a yeter mi? " + yeterMi(altin, "Uzun Kılıç"))console.log(fiyatlar)Çizme: 300 altınÇizmeye yeter mi? trueUzun Kılıç'a yeter mi? falsefile:///C:/kod/ogren/ders14/ana.js:7console.log(fiyatlar) ^ ReferenceError: fiyatlar is not defined at file:///C:/kod/ogren/ders14/ana.js:7:13 ... Node.js v24.20.0İlk üç satır çalıştı, program 7. satırda durdu: fiyatlar'ı kullanamazsın. Her modülün kendi kapsamı vardır (Ders 3'teki fonksiyonlar gibi); içinde tanımlananlar dışarıdan görünmez, dışarıya yalnızca export ettiklerin açılır. Hata mesajındaki yolun file:/// ile başladığına da dikkat et: ES modüllerinde Node dosyanın yerini böyle, bir internet adresi gibi yazar. Denemeden sonra son satırı sil.
dukkan.js'in vitrini ve deposu. ana.js vitrindekileri alabilir, depodakine ulaşamaz.SyntaxError: The requested module './dukkan.js' does not provide an export named 'fiyatlar'Ne zaman çıkar? Vitrinde olmayan bir şeyi istediğinde: o dosyada export yazmayı unuttuğunda ya da adı farklı yazdığında (fiyatbul, FiyatBul).
import { fiyatlar } from "./dukkan.js"file:///C:/kod/ogren/ders14/ana.js:1import { fiyatlar } from "./dukkan.js" ^^^^^^^^SyntaxError: The requested module './dukkan.js' does not provide an export named 'fiyatlar' at #asyncInstantiate (node:internal/modules/esm/module_job:455:21) ... Node.js v24.20.0Nasıl düzelir? Mesaj "./dukkan.js, fiyatlar adında bir şey dışa aktarmıyor" diyor. Adı, dışa aktarılan adla harfi harfine aynı yaz; o şeyin gerçekten dışarıya açılması gerekiyorsa kendi dosyasında önüne export ekle. Türü neden SyntaxError? Çünkü Node bütün import satırlarını program başlamadan denetler; tıpkı Ders 1'deki yazım hataları gibi, tek satır bile çalışmadan durur.
Varsayılan dışa aktarma
Şimdiye kadar yaptığın şeyin adı adlı dışa aktarma (named export): her şey kendi adıyla vitrine konur, alan dosya aynı adı süslü parantez içinde yazar.
İkinci bir yol daha var. Bir modül "benim asıl işim bu" diyebilir: export default (varsayılan olarak dışa aktar). ders14 içinde karsilama.js dosyasını aç:
export default function karsila(oyuncu) { return "Hoş geldin, " + oyuncu}Varsayılanı alırken süslü parantez yazmazsın. ana.js'i şöyle değiştir:
import karsila from "./karsilama.js"import { fiyatBul, yeterMi } from "./dukkan.js" const altin = 300console.log(karsila("Ahri"))console.log("Çizme: " + fiyatBul("Çizme") + " altın")console.log("Çizmeye yeter mi? " + yeterMi(altin, "Çizme"))PS C:\kod\ogren\ders14> node ana.jsHoş geldin, AhriÇizme: 300 altınÇizmeye yeter mi? trueVarsayılan dışa aktarmanın bir özelliği daha var: adını alan dosya seçer. import selamVer from "./karsilama.js" yazsaydın aynı fonksiyonu selamVer("Lux") diye çağırırdın ve Hoş geldin, Lux alırdın. Süslü parantezsiz import, "bana dosyanın varsayılanını ver, adını ben koyacağım" demektir.
| Adlı (named) | Varsayılan (default) | |
|---|---|---|
| Bir dosyada | istediğin kadar | en fazla bir tane |
| Dışa aktarma | export function fiyatBul | export default function karsila |
| İçe aktarma | import { fiyatBul } from … | import karsila from … |
| Ad | dışa aktarılan adın aynısı | alan dosyanın seçtiği ad |
Hangisini kullanacaksın? Bu kursta çoğunlukla adlıyı: ad her dosyada aynı kalır, aradığında bulursun, VS Code yazarken önerir. Varsayılanı, dosyanın tek bir asıl işi olduğunda görürsün; React derslerinde her bileşen dosyası böyledir (Ders 40). Birazdan kuracağın paket de varsayılan dışa aktarma ile gelir.
SyntaxError: The requested module './dukkan.js' does not provide an export named 'default'Ne zaman çıkar? Adlı dışa aktarılmış bir şeyi süslü parantezsiz almaya çalışınca.
import fiyatBul from "./dukkan.js"file:///C:/kod/ogren/ders14/ana.js:1import fiyatBul from "./dukkan.js" ^^^^^^^^SyntaxError: The requested module './dukkan.js' does not provide an export named 'default' at #asyncInstantiate (node:internal/modules/esm/module_job:455:21) ... Node.js v24.20.0Nasıl düzelir? Süslü parantezsiz import dosyanın varsayılanını ister, dukkan.js'in ise varsayılanı yok. Süslü parantez ekle: import { fiyatBul } from "./dukkan.js". Tersi de olur: varsayılanı süslü parantezle istersen (import { karsila } from "./karsilama.js") bu kez does not provide an export named 'karsila' alırsın.
npm ve package.json
Şimdiye kadar yalnız kendi yazdığın modülleri kullandın. Bir de dünyanın dört bir yanındaki yazılımcıların yazıp herkese açtığı modüller var: bunlara paket denir. Terminale renkli yazı, tarih hesabı, web sunucusu (Ders 28'de Express)... Her birini sıfırdan yazmak yerine hazır paketi kurarsın.
Paketlerin toplandığı yer npm'dir. Bu ad iki şeyi anlatır: internetteki dev paket deposunu (npmjs.com) ve Node.js ile birlikte bilgisayarına kurulmuş npm komutunu. Komut, depodan paket indirir ve projeni düzenli tutar.
Projeyi başlat: npm init
Bir klasörü npm projesine çevirmenin ilk adımı npm init komutudur. Normalde sana proje adı, sürüm gibi sorular sorar; -y (İngilizce yes, evet) "hepsine varsayılan cevabı ver" demek. ders14 klasöründeyken npm init -y yaz.
Windows'ta npm komutu büyük ihtimalle Ders 0'da gördüğün kırmızı hatayı verir. Orada npm.cmd yazarak geçmiştin; şimdi kalıcı olarak çözeceğiz:
npm.ps1 cannot be loaded because running scripts is disabled on this systemNe zaman çıkar? Windows'ta PowerShell terminalinde npm yazınca. Bu kart kalıcı çözümü anlatıyor.
PS C:\kod\ogren\ders14> npm init -ynpm : File C:\Program Files\nodejs\npm.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.At line:1 char:1+ npm init -y+ ~~~ + CategoryInfo : SecurityError: (:) [], PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccessWindows'un dili Türkçe olsa bile bu mesaj büyük olasılıkla İngilizce gelir (Ders 0'da da öyleydi). Türkçe gelirse npm.ps1 dosyasının yüklenemediğini ve bu sistemde betik çalıştırmanın devre dışı olduğunu söyler. Mesajdaki about_Execution_Policies, PSSecurityException ve UnauthorizedAccess sözcükleri çevrilmez, iki dilde de aynıdır; hatayı onlardan tanırsın.
Neden çıkar? PowerShell'de npm yazınca aslında npm.ps1 adlı küçük bir PowerShell betiği (script) çalışır. Windows'ta PowerShell ise başlangıçta hiçbir betik dosyasının çalışmasına izin vermez.
Nasıl düzelir? İki yol var:
- Kalıcı çözüm: terminale
Set-ExecutionPolicy -Scope CurrentUser RemoteSignedyaz, onay sorarsa evet de, sonra npm komutunu yeniden çalıştır. Ne yaptığı hemen aşağıda. - Ayara dokunmadan: Ders 0'daki gibi
npmyerinenpm.cmdyaz (npm.cmd init -y).npm.cmdbetik değil, sıradan bir komut dosyasıdır; ayar onu engellemez. Her komutta.cmdyazmayı unutmaman gerekir.
PowerShell'in betiklere izin verip vermediğini belirleyen bu ayara çalıştırma ilkesi (execution policy) denir. Kalıcı çözümün komutu:
PS C:\kod\ogren\ders14> Set-ExecutionPolicy -Scope CurrentUser RemoteSignedSet-ExecutionPolicy: çalıştırma ilkesini değiştir.-Scope CurrentUser: yalnız senin Windows kullanıcın için. Bilgisayarı kullanan başkalarını etkilemez ve yönetici izni istemez.RemoteSigned: bu bilgisayarda oluşan betikler (Node.js kurulumunun koyduğunpm.ps1dahil) çalışır; internetten indirilmiş betikler ise ancak güvenilir bir yayıncının dijital imzası varsa çalışır.
Komut bir onay sorusu sorabilir. Soru İngilizceyse Execution Policy Change başlığıyla gelir ve Do you want to change the execution policy? ("Çalıştırma ilkesini değiştirmek istiyor musun?") diye biter. Altındaki seçeneklerden "evet" olanın harfini ([Y] Yes için Y) yazıp Enter'a bas; soru gelmezse bir şey yapmana gerek yok.
Microsoft'un kendi belgesine göre bu ayar bir güvenlik sistemi değildir; kullanıcıyı gerçekten durdurmaz, yalnızca yanlışlıkla betik çalıştırmanı önleyen bir emniyet kemeridir. RemoteSigned, Windows'un sunucu sürümlerinde zaten varsayılan ayardır. Ayarın tuttuğunu denetle (npm sürüm numarası sende farklı olabilir):
PS C:\kod\ogren\ders14> Get-ExecutionPolicyRemoteSignedPS C:\kod\ogren\ders14> npm --version11.19.0Şimdi npm init -y çalışır:
PS C:\kod\ogren\ders14> npm init -yWrote to C:\kod\ogren\ders14\package.json: { "name": "ders14", "version": "1.0.0", "description": "", "main": "ana.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "type": "commonjs"}npm klasöre package.json adında bir dosya yazdı ve içeriğini ekrana bastı. Bu dosya projenin kimlik kartıdır:
| Alan | Ne anlatır |
|---|---|
name | Projenin adı; npm klasörün adını kullandı. |
version | Projenin sürümü. |
description, keywords, author | Açıklama, anahtar sözcükler, yazar. Şimdilik boş. |
main | Projenin ana dosyası; npm klasörde bulduğu ilk .js dosyasını yazdı. |
scripts | Kısa komutlar (npm betikleri). Biraz sonra. |
license | Lisans: başkalarının kodunu hangi koşulla kullanabileceği. ISC "serbestçe kullan" diyen kısa bir lisanstır. |
type | Node'un bu klasördeki .js dosyalarını hangi modül sistemiyle okuyacağı. |
"type" satırı: module mi, commonjs mi?
npm son satıra "type": "commonjs" yazdı. Şimdi programını yeniden çalıştır:
SyntaxError: Cannot use import statement outside a moduleNe zaman çıkar? package.json'da "type": "commonjs" yazarken .js dosyasında import kullanınca. npm init bu satırı kendiliğinden yazdığı için ilk karşılaşacağın yer burası.
PS C:\kod\ogren\ders14> node ana.js(node:7156) Warning: Failed to load the ES module: C:\kod\ogren\ders14\ana.js. Make sure to set "type": "module" in the nearest package.json file or use the .mjs extension.(Use `node --trace-warnings ...` to show where the warning was created)C:\kod\ogren\ders14\ana.js:1import karsila from "./karsilama.js"^^^^^^ SyntaxError: Cannot use import statement outside a module at wrapSafe (node:internal/modules/cjs/loader:1861:18) ... Node.js v24.20.0Nasıl düzelir? İlk satırdaki uyarı çözümü söylüyor: en yakın package.json dosyasına "type": "module" yaz (Make sure to set "type": "module"…). package.json'da "commonjs" yazan yeri "module" yap, kaydet ve yeniden çalıştır.
{ "name": "ders14", "version": "1.0.0", "description": "", "main": "ana.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "type": "module"}PS C:\kod\ogren\ders14> node ana.jsHoş geldin, AhriÇizme: 300 altınÇizmeye yeter mi? trueDeğişen tek sözcük: "commonjs" yerine "module". Artık Node bu klasördeki .js dosyalarını ES modülü olarak okuyor.
Node 24, bir dosyayı hangi sistemle okuyacağına şöyle karar verir:
| Durum | Node ne yapar? |
|---|---|
Klasörde (ve üst klasörlerde) package.json yok | Dosyada import/export görürse modül sayar ve sessizce çalıştırır. Dersin başında böyle çalıştı. |
package.json var, "type" satırı yok | Yine çalıştırır ama her seferinde bir uyarı yazar (aşağıda). |
"type": "commonjs" | .js dosyaları CommonJS'tir; import satırı hata verir. |
"type": "module" | .js dosyaları ES modülüdür. Bu kursta hep bunu kullanacağız. |
Dosyanın adı .mjs ile bitiyor | "type" satırına bakmadan her zaman ES modülü sayar (uyarıdaki use the .mjs extension önerisi bu). |
CommonJS'i tanımak
npm neden "commonjs" yazdı? Sebep tarih. Node 2009'da çıktığında JavaScript'in kendi modül sistemi yoktu; Node, o yıllarda sunucuda çalışan JavaScript için önerilmiş CommonJS adlı sistemi benimsedi. Bugün kullandığın import/export (ES modülleri) dile 2015'te eklendi ve artık standart bu.
Ama npm'deki paketlerin büyük bir kısmı ve internetteki eski yazıların çoğu hâlâ CommonJS ile yazılı. CommonJS yazmayacaksın, ama gördüğünde tanıyıp okuyabilmelisin. Aynı dukkan.js ve ana.js, "type": "commonjs" olan bir klasörde CommonJS ile böyle yazılır (bunları kendi dosyalarına yazma, yalnızca oku):
const fiyatlar = { "Uzun Kılıç": 350, "Çizme": 300, "Can İksiri": 50} function fiyatBul(esya) { return fiyatlar[esya] ?? 0} function yeterMi(altin, esya) { return altin >= fiyatBul(esya)} module.exports = { fiyatBul, yeterMi }const { fiyatBul, yeterMi } = require("./dukkan.js") console.log(fiyatBul("Çizme"))300module.exports = { … }: "dışarıya bu objeyi ver". Dışa açılacak her şey tek bir objeye konur; bu satır genellikle dosyanın sonundadır.require("./dukkan.js"): "o dosyanın dışa açtığı objeyi getir". Gelen objedenfiyatBulveyeterMi'yi parçalayarak (Ders 12) alıyoruz.
| İş | ES modülü | CommonJS |
|---|---|---|
| Dışa açmak | export function fiyatBul | module.exports = { fiyatBul } |
| İçe almak | import { fiyatBul } from "./dukkan.js" | const { fiyatBul } = require("./dukkan.js") |
| Varsayılan | export default / import karsila from … | module.exports = karsila / const karsila = require(…) |
| Yoldaki uzantı | zorunlu | yazılmasa da olur |
Bir dosyanın adı .mjs ile bitiyorsa her zaman ES modülü, .cjs ile bitiyorsa her zaman CommonJS sayılır; "type" ayarı yalnız .js dosyaları içindir. İki yazımı aynı dosyada karıştıramazsın.
ReferenceError: require is not defined in ES module scopeNe zaman çıkar? Bir CommonJS satırını (bu bölümdeki örneği ya da internetten kopyaladığın bir require satırını) "type": "module" olan bir projeye yazınca.
const { fiyatBul, yeterMi } = require("./dukkan.js")file:///C:/kod/ogren/ders14/ana.js:1const { fiyatBul, yeterMi } = require("./dukkan.js") ^ ReferenceError: require is not defined in ES module scope, you can use import insteadThis file is being treated as an ES module because it has a '.js' file extension and '\\?\C:\kod\ogren\ders14\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension. at file:///C:/kod/ogren/ders14/ana.js:1:31 ... Node.js v24.20.0Nasıl düzelir? Mesaj iki yol söylüyor; senin yolun birincisi: "require bu dosyada yok, import kullanabilirsin". Satırı import ile yeniden yaz: import { fiyatBul, yeterMi } from "./dukkan.js". Dosyanın adını .cjs yapmak da çalışır ama yeni kodda CommonJS yazmıyoruz.
Paket kurmak: npm install
Terminale yazdırdığın her şey aynı renkte. Önemli satırları yeşil ya da kırmızı yapmak için terminale özel, okunmaz kodlar göndermek gerekir. Bu işi yapan küçük bir paket var: picocolors. Kurmak için ders14 klasöründe (internet bağlantısı gerekir):
PS C:\kod\ogren\ders14> npm install picocolors added 1 package, and audited 2 packages in 954ms found 0 vulnerabilitiesadded 1 package: bir paket eklendi.picocolorsbaşka bir pakete ihtiyaç duymadığı için yalnız kendisi geldi; büyük paketler yanlarında onlarcasını getirir.audited 2 packages: npm, senin projen dahil iki paketi bilinen güvenlik açıklarına karşı taradı.found 0 vulnerabilities: bilinen açık yok.
Bu tek komut üç şeyi değiştirdi:
npm install picocolors paketi depodan indirir ve projende üç yere iz bırakır.node_modulesklasörü: paketin kendi dosyaları buraya indi. Bu klasörü elle düzenlemezsin; npm yönetir.package.json: sonuna yeni bir bölüm eklendi. Projenin hangi paketlere ihtiyaç duyduğu, yani bağımlılıkları burada yazar:{ }package.json "type": "module", "dependencies": { "picocolors": "^1.1.1" }package-lock.json: npm'in tuttuğu ayrıntılı kayıt. İçinde kurulan sürümün tam numarası, indirildiği adres ve içeriğin parmak izi (integrity) var. Bu dosyayı da elle düzenlemezsin:{ }package-lock.json "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
Şimdi paketi kullan. ana.js'i şöyle değiştir:
import pc from "picocolors"import karsila from "./karsilama.js"import { fiyatBul, yeterMi } from "./dukkan.js" const altin = 300console.log(pc.bold(karsila("Ahri")))console.log("Çizme: " + fiyatBul("Çizme") + " altın") if (yeterMi(altin, "Çizme")) { console.log(pc.green("Çizmeyi alabilirsin"))} else { console.log(pc.red("Altının yetmiyor"))}PS C:\kod\ogren\ders14> node ana.jsHoş geldin, AhriÇizme: 300 altınÇizmeyi alabilirsinKendi terminalinde ilk satır kalın, son satır yeşil görünür (bu sayfadaki pencere renkleri göstermiyor). Satır satır:
import pc from "picocolors": yolun başında./yok, demek ki bu bir paket. Node onunode_modulesklasöründe arar. Paket varsayılan dışa aktarma ile geliyor; adını biz seçtik:pc(paketin kendi belgesinde de bu ad kullanılıyor).pc.green(metin), metni yeşile boyanmış hâliyle geri verir;pc.redkırmızı,pc.boldkalın yapar. Boyanan metni yineconsole.logyazdırır.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'picocolors'Ne zaman çıkar? Paketi kurmadan import edince, başka bir klasörde kurunca ya da node_modules klasörü yokken (ör. projeyi GitHub'dan yeni indirmişken).
PS C:\kod\ogren\ders14> node ana.jsnode:internal/modules/package_json_reader:301 throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'picocolors' imported from C:\kod\ogren\ders14\ana.js at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9) ... Node.js v24.20.0Nasıl düzelir? package.json'un olduğu klasörde npm install picocolors yaz. Paket zaten package.json'da yazılıysa yalnızca npm install yeter; npm eksik olan her şeyi kurar. Terminalin hangi klasörde olduğuna bak: istem PS C:\kod\ogren\ders14> olmalı.
node_modules, Git ve npm uninstall
node_modules klasörü kolayca şişer. Bu derste içinde tek paket var, ama Express gibi bir paket yanında onlarcasını getirir; gerçek projelerde bu klasör yüzlerce megabayta ulaşır. Üstelik ona ihtiyacın yok: npm, package.json ve package-lock.json'a bakarak onu istediği an birebir aynısıyla yeniden kurar. Bu yüzden node_modules Git'e konmaz.
C:\kod\ogren klasöründeki .gitignore dosyasını aç (Ders 7'de oluşturmuştun; yoksa aynı adla yeni bir dosya oluştur) ve en alta, Ders 7'deki tabloda gördüğün satırı ekle:
node_modules/Bu satır, hangi alt klasörde olursa olsun adı node_modules olan her klasörü Git'in görmezden gelmesini sağlar. Kural yalnız bu derse değil, C:\kod\ogren içindeki bütün projelere işler.
node_modules gönderilmez; arkadaşın onu npm install ile kendi bilgisayarında kurar.Kendin dene: VS Code'un solundaki listede ders14 içindeki node_modules klasörüne sağ tıkla ve Delete ile sil. node ana.js artık Cannot find package 'picocolors' hatası verir (yukarıdaki kart). Şimdi paket adı vermeden npm install yaz:
PS C:\kod\ogren\ders14> npm install added 1 package, and audited 2 packages in 855ms found 0 vulnerabilitiesPS C:\kod\ogren\ders14> node ana.jsHoş geldin, AhriÇizme: 300 altınÇizmeyi alabilirsinPaket adı verilmeyen npm install, package.json'daki bağımlılıkların hepsini package-lock.json'daki tam sürümleriyle kurar. GitHub'dan indirdiğin her projede ilk yazacağın komut budur.
Bir paketi projeden çıkarmak için npm uninstall kullanılır:
PS C:\kod\ogren\ders14> npm uninstall picocolors removed 1 package, and audited 1 package in 618ms found 0 vulnerabilitiesnpm paketi node_modules'tan sildi ve package.json'daki dependencies bölümünü kaldırdı. ana.js hâlâ picocolors'u içe aktardığı için program yine Cannot find package hatası verir. Derse devam etmek için paketi yeniden kur: npm install picocolors.
npm betikleri
Projeni indiren biri onu nasıl çalıştıracağını nereden bilecek? node ana.js mi, node oyun.js mi? Ayrıca bazı komutlar uzun ve her seferinde yazması zahmetli. Çözüm, package.json'daki scripts bölümü: kısa adlara uzun komutlar bağlarsın. Bunlara npm betiği (npm script) denir.
scripts bölümünü şöyle değiştir. Her satırın sonundaki virgüle dikkat: sonuncusu hariç hepsinde var.
"scripts": { "start": "node ana.js", "renksiz": "node ana.js --no-color", "test": "echo \"Error: no test specified\" && exit 1" },start adı özeldir, npm start ile çalışır. npm önce hangi betiği çalıştırdığını iki satırla söyler, sonra programın çıktısı gelir:
PS C:\kod\ogren\ders14> npm start > ders14@1.0.0 start> node ana.js Hoş geldin, AhriÇizme: 300 altınÇizmeyi alabilirsinÖteki adları npm run ile çalıştırırsın. renksiz betiği aynı programı --no-color ekiyle başlatır; picocolors bu eki görünce renk kullanmaz (renk kodlarını anlamayan bir yere çıktı verirken işe yarar). Uzun bir komutu bir kez yazıp kısa bir ada bağlamanın örneği bu:
PS C:\kod\ogren\ders14> npm run renksiz > ders14@1.0.0 renksiz> node ana.js --no-color Hoş geldin, AhriÇizme: 300 altınÇizmeyi alabilirsinKendi terminalinde bu kez kalın ya da yeşil yazı görmezsin: picocolors eki gördü ve boyamadı.
Bir projede hangi betikler var, unuttuysan yalnız npm run yaz:
PS C:\kod\ogren\ders14> npm runLifecycle scripts included in ders14@1.0.0: start node ana.js test echo "Error: no test specified" && exit 1available via `npm run`: renksiz node ana.js --no-colorKural şu: start ve test kısaca npm start, npm test diye çalışır; ötekiler için npm run ad yazarsın. npm renksiz yazarsan npm Unknown command: "renksiz" der ve npm run renksiz'i önerir. npm init'in koyduğu test betiği şimdilik yalnız "Error: no test specified" yazıp hatayla biter; test yazmayı Ders 53'te öğreneceksin.
npm error Missing script: "baslat"Ne zaman çıkar? package.json'da olmayan bir betiği çalıştırmak isteyince (adı yanlış yazınca ya da betiği eklemeyi unutunca).
PS C:\kod\ogren\ders14> npm run baslatnpm error Missing script: "baslat"npm errornpm error To see a list of scripts, run:npm error npm runnpm error A complete log of this run can be found in: C:\Users\Deniz\AppData\Local\npm-cache\_logs\2026-10-11T13_02_09_584Z-debug-0.logNasıl düzelir? Mesaj ne yapacağını söylüyor: npm run yazıp betiklerin listesine bak, adı oradakiyle aynı yaz. Son satırdaki günlük (log) dosyasına şimdilik bakmana gerek yok.
npm error code EJSONPARSENe zaman çıkar? package.json'u elle düzenlerken virgülü ya da tırnağı unutunca. Aşağıdaki dosyada 7. satırın sonunda virgül yok:
"scripts": { "start": "node ana.js" "renksiz": "node ana.js --no-color",PS C:\kod\ogren\ders14> npm startnpm error code EJSONPARSEnpm error JSON.parse Invalid package.json: JSONParseError: Expected ',' or '}' after property value in JSON at position 131 (line 8 column 5) while parsing near "...: \"node ana.js\"\n \"renksiz\": \"node ana..."npm error JSON.parse Failed to parse JSON data.npm error JSON.parse Note: package.json must be actual JSON, not just JavaScript.npm error A complete log of this run can be found in: C:\Users\Deniz\AppData\Local\npm-cache\_logs\2026-10-11T13_05_14_252Z-debug-0.logNasıl düzelir? Mesaj sorunu line 8 column 5 (8. satır, 5. sütun) olarak gösteriyor: npm 8. satırın başında "renksiz"'i görünce şaşırdı, çünkü önce bir virgül bekliyordu. Eksik virgül hep bir önceki satırın sonundadır. VS Code da hatalı yerin altını kırmızıyla çizer. Note: ile başlayan satır da önemli: package.json gerçek JSON olmalı, JavaScript gibi rahat yazılamaz.
npm error enoent Could not read package.jsonNe zaman çıkar? npm komutunu package.json'un olmadığı bir klasörde çalıştırınca. En sık sebep, terminalin hâlâ C:\kod\ogren'de olması.
PS C:\kod\ogren> npm startnpm error code ENOENTnpm error syscall opennpm error path C:\kod\ogren\package.jsonnpm error errno -4058npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open 'C:\kod\ogren\package.json'npm error enoent This is related to npm not being able to find a file.npm error enoentnpm error A complete log of this run can be found in: C:\Users\Deniz\AppData\Local\npm-cache\_logs\2026-10-11T13_02_19_052Z-debug-0.logNasıl düzelir? ENOENT "böyle bir dosya ya da klasör yok" demek. Mesaj aradığı yolu da yazıyor: C:\kod\ogren\package.json. Doğru klasöre geç (cd ders14) ve komutu orada çalıştır.
Sürüm numaraları
package.json'da "picocolors": "^1.1.1" yazıyordu. Bu numara rastgele değil, üç parçalı bir kural izler: büyük.küçük.yama (İngilizcesi major.minor.patch).
| Parça | Ne zaman artar? | Senin için anlamı |
|---|---|---|
Yama (1.1.1 → 1.1.2) | Hata düzeltilince | Güvenle güncellenir. |
Küçük (1.1.1 → 1.2.0) | Yeni özellik eklenince, eski kod bozulmadan | Genellikle güvenle güncellenir. |
Büyük (1.1.1 → 2.0.0) | Eski kodu bozabilecek değişiklikte | Önce paketin değişiklik notlarını oku. |
Bu kural bir sözdür, garanti değil: ona uymak paketi yazan kişiye kalmıştır. Yaygın paketlerin hemen hepsi uyar. Numaranın önündeki işaret, npm'e hangi sürümleri kabul edebileceğini söyler:
| Kurulabilecek sürüm | ^1.1.1 | ~1.1.1 | 1.1.1 |
|---|---|---|---|
1.1.1 | ✓ | ✓ | ✓ |
1.1.7 | ✓ | ✓ | ✗ |
1.4.0 | ✓ | ✗ | ✗ |
2.0.0 | ✗ | ✗ | ✗ |
1.0.9 | ✗ | ✗ | ✗ |
^(şapka, npm'in varsayılanı): aynı büyük sürüm içinde, en az bu kadar yeni her sürüm.~(tilde): aynı küçük sürüm içinde, yalnız yamalar.- İşaretsiz: yalnız tam olarak bu sürüm.
Hangi sürümün gerçekten kurulduğuna ise package-lock.json karar verir: paketin sonradan 1.1.7 sürümü çıksa bile, kilit dosyasında 1.1.1 yazdıkça npm install herkese 1.1.1'i kurar. Böylece senin bilgisayarında çalışan proje, arkadaşının bilgisayarında da aynı sürümlerle çalışır.
Paket seçerken dikkat
npm install ile kurduğun her paket, bilgisayarında senin yetkinle kod çalıştırır. Bu yüzden paket kurmak, birinin yazdığı programı çalıştırmak kadar ciddi bir iştir. Kurmadan önce şunlara bak:
| Neye bak | Nerede | İyi işaret | Uyarı işareti |
|---|---|---|---|
| Adı | Resmî belge, npmjs.com | Belgedekiyle harfi harfine aynı | Bir harf, tire ya da nokta farkı |
| Haftalık indirme | npmjs.com: Weekly Downloads | Binlerce, milyonlarca | Çok az ve adı popüler bir pakete benziyor |
| Son yayın | npmjs.com: Last publish | Bakımı sürüyor | Büyük bir paket yıllardır güncellenmemiş |
| Bağımlılık sayısı | npm view çıktısında deps | Az ya da hiç | Küçük bir iş için onlarca bağımlılık |
| Lisans | npmjs.com: License | MIT, ISC, Apache-2.0 | Lisans yok |
| Kaynak kodu | GitHub bağlantısı | Açıklayıcı README, yanıt alan sorun kayıtları (issues) | Depo yok, README boş |
"Son yayın" tek başına karar vermez: picocolors gibi küçük ve bitmiş bir paketin uzun süre güncellenmemesi normaldir. Bu bilgilerin bir kısmını terminalden de görebilirsin:
PS C:\kod\ogren\ders14> npm view picocolors picocolors@1.1.1 | ISC | deps: none | versions: 9The tiniest and the fastest library for terminal output formatting with ANSI colorshttps://github.com/alexeyraspopov/picocolors#readme# devamı kısaltıldı: anahtar sözcükler, dosya bilgileri, bakımcılar, son yayın tarihiİlk satır: son sürüm 1.1.1, lisans ISC, hiç bağımlılığı yok, bugüne kadar 9 sürüm yayınlanmış. Altında paketin açıklaması ve kaynak kodunun adresi var. İndirme istatistiklerine göre picocolors Ekim 2026'da bir haftada yaklaşık 247 milyon kez indirildi: dünyanın en çok kullanılan paketlerinden biri.
Kurduktan sonra da npm audit ile projedeki paketleri bilinen açıklara karşı taratabilirsin:
PS C:\kod\ogren\ders14> npm auditfound 0 vulnerabilitiesnpm audit yalnız bilinen açıkları bulur; dün yayınlanmış zararlı bir kodu tanımaz. Bu yüzden en önemli koruma, neyi kurduğuna dikkat etmendir. İki gerçek olay:
- Adı benzeyen sahte paket (2017): Ortam ayarlarını yönetmeye yarayan popüler
cross-envpaketinin adına çok benzeyencrossenvadlı bir paket yayınlandı. Adı yanlış yazıp onu kuranların bilgisayarındaki ortam ayarlarını, içlerinde sık sık bulunan şifre ve erişim anahtarlarıyla birlikte saldırgana gönderiyordu. npm bu ve aynı kişinin yayınladığı benzer adlı yaklaşık 40 paketi sildi. - Ele geçirilen popüler paketler (Eylül 2025):
chalkvedebuggibi dünyanın en çok indirilen paketlerinin bakımcısı, sahte bir "npm destek" e-postasıyla kandırıldı. Saldırgan bu paketlerin zararlı sürümlerini yayınladı; sürümler birkaç saat içinde kaldırıldı. Kilit dosyası olan ve o saatlerde güncelleme yapmayan projeler etkilenmedi.
npm error code E404Ne zaman çıkar? Paket adını yanlış yazınca: depoda o adda bir paket yok.
PS C:\kod\ogren\ders14> npm install picocoloursnpm error code E404npm error 404 Not Found - GET https://registry.npmjs.org/picocolours - Not foundnpm error 404npm error 404 The requested resource 'picocolours@*' could not be found or you do not have permission to access it.npm error 404npm error 404 Note that you can also install from anpm error 404 tarball, folder, http url, or git url.npm error A complete log of this run can be found in: C:\Users\Deniz\AppData\Local\npm-cache\_logs\2026-10-11T13_04_58_550Z-debug-0.logNasıl düzelir? 404 Not Found "bulunamadı" demek: picocolours diye bir paket yok, doğrusu picocolors. Bu hatayı aldığın için şanslısın: yanlış yazdığın ad gerçekten var olsaydı npm hiç ses çıkarmadan başka birinin paketini kurardı. Bu yüzden adı her zaman resmî kaynaktan kopyala.
Görevler
Görevlerin çoğu ders14 klasöründe; iki görev kendi klasörlerinde birer npm projesi. Önce kendin dene, takılırsan ipuçlarını sırayla aç.
Can modülü
ders14 klasöründe can.js adında bir modül yaz. İçinde iki adlı dışa aktarma olsun:
hasarAl(hp, hasar): canı hasar kadar azaltıp yeni canı döndürür; sonuç0'ın altına inmez.iyiles(hp, miktar): canı artırıp döndürür; sonuç100'ü geçmez.
Sonra gorev1.js dosyasını aç, iki fonksiyonu içe aktar ve sırayla şunları yazdır: hasarAl(100, 30), hasarAl(20, 50), iyiles(90, 25), iyiles(40, 25). node gorev1.js şunu yazmalı:
70010065İpucu 1
can.js'te iki fonksiyonun da önünde export olmalı. gorev1.js'in ilk satırı import { …, … } from "./can.js" biçiminde.
İpucu 2
"Sıfırın altına inmesin" için Math.max(0, …), "100'ü geçmesin" için Math.min(100, …) kullanabilirsin (Ders 9). if ile yazmak da doğru.
Çözümü göster
export function hasarAl(hp, hasar) { return Math.max(0, hp - hasar)} export function iyiles(hp, miktar) { return Math.min(100, hp + miktar)}import { hasarAl, iyiles } from "./can.js" console.log(hasarAl(100, 30))console.log(hasarAl(20, 50))console.log(iyiles(90, 25))console.log(iyiles(40, 25))70010065Sınır denemesi: hasarAl(30, 30) tam 0, hasarAl(31, 30) 1, iyiles(75, 25) tam 100 vermeli. Math.max ile Math.min'in yerini karıştırırsan program hata vermez ama dört satırın dördü de yanlış çıkar: 0, -30, 115, 100. Çıktıyı bu yüzden beklenenle satır satır karşılaştır.
Adını sen koy
mana.js adında bir modül yaz. İçinde varsayılan dışa aktarma ile tek bir fonksiyon olsun: manayı ve yeteneğin bedelini alır; mana yetiyorsa Yetenek kullanıldı, kalan mana: …, yetmiyorsa Mana yetmiyor metnini döndürür. gorev2.js'te bu fonksiyonu yetenek adıyla içe aktar (fonksiyonun kendi adı ne olursa olsun) ve sırayla yetenek(200, 80), yetenek(80, 80), yetenek(79, 80) sonuçlarını yazdır:
Yetenek kullanıldı, kalan mana: 120Yetenek kullanıldı, kalan mana: 0Mana yetmiyorİpucu 1
export default function manaKontrol(mana, bedel) { … } biçiminde başla. İçe aktarırken süslü parantez yok: import yetenek from "./mana.js".
İpucu 2
Mana bedele eşitken de yetenek kullanılabilmeli: > mı, >= mi? Kalan manayı metne eklerken çıkarmayı paranteze al: (mana - bedel).
Çözümü göster
export default function manaKontrol(mana, bedel) { if (mana >= bedel) { return "Yetenek kullanıldı, kalan mana: " + (mana - bedel) } return "Mana yetmiyor"}import yetenek from "./mana.js" console.log(yetenek(200, 80))console.log(yetenek(80, 80))console.log(yetenek(79, 80))Yetenek kullanıldı, kalan mana: 120Yetenek kullanıldı, kalan mana: 0Mana yetmiyorİkinci satır sınır değeri: > yazsaydın 80 manayla 80'lik yetenek kullanılamazdı. Parantezi unutursan "…: " + mana - bedel önce metni birleştirir, sonra metinden sayı çıkarmaya çalışır ve sonuç Yetenek kullanıldı, kalan mana: 120 yerine NaN olur.
TFT faiz hesaplayıcısı
Kendi npm projeni sıfırdan kur. C:\kod\ogren içinde tft-faiz adında yeni bir klasör aç ve terminalde oraya geç: terminal ders14'teyken sırayla cd .., mkdir tft-faiz ve cd tft-faiz yaz. Sonra:
npm init -yile projeyi başlat ve"type"satırını"module"yap.picocolorspaketini kur.faiz.jsdosyasındafaizHesapla(altin)fonksiyonunu adlı dışa aktarma ile ver. TFT kuralı: her 10 altın için 1 faiz, ama en fazla 5.ana.js,[0, 9, 10, 49, 50, 87]dizisindeki her altın değeri içinAltın 49, faiz 4biçiminde bir satır yazdırsın; faizi 5 olan satırlar yeşil olsun.package.json'a birstartbetiği ekle; programnpm startile çalışsın.
npm start çıktısının son altı satırı (renkler görünmeden) şöyle olmalı:
Altın 0, faiz 0Altın 9, faiz 0Altın 10, faiz 1Altın 49, faiz 4Altın 50, faiz 5Altın 87, faiz 5İpucu 1
"Her 10 altın için 1": Math.floor(altin / 10). "En fazla 5": sonucu Math.min(5, …) içine al.
İpucu 2
İpucu 3
package.json'da "scripts" içine "start": "node ana.js", satırını ekle. Satırın sonundaki virgüle dikkat; npm start EJSONPARSE verirse virgülü kontrol et.
Çözümü göster
export function faizHesapla(altin) { return Math.min(5, Math.floor(altin / 10))}import pc from "picocolors"import { faizHesapla } from "./faiz.js" const altinlar = [0, 9, 10, 49, 50, 87] for (const altin of altinlar) { const faiz = faizHesapla(altin) const satir = `Altın ${altin}, faiz ${faiz}` if (faiz === 5) { console.log(pc.green(satir)) } else { console.log(satir) }}{ "name": "tft-faiz", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node ana.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "type": "module", "dependencies": { "picocolors": "^1.1.1" }} > tft-faiz@1.0.0 start> node ana.js Altın 0, faiz 0Altın 9, faiz 0Altın 10, faiz 1Altın 49, faiz 4Altın 50, faiz 5Altın 87, faiz 5Sınır değerleri: 9 henüz 10'a ulaşmadığı için 0, 10 tam 1, 49 4, 50 tam 5, 87 ise üst sınırda kalıp 5. Math.min'i unutursan son satır faiz 8 çıkar. npm init klasör boşken çalıştığı için main alanında index.js yazıyor; bu alan programın çalışmasını etkilemez.
CommonJS'ten çeviri
Bir arkadaşın TFT birimlerinin yıldızlarını sayan iki dosya göndermiş, ama CommonJS ile yazmış. Dosyaları ders14 klasörüne koyunca node gorev4.js hata veriyor:
const birimler = [ { ad: "Jinx", yildiz: 2 }, { ad: "Annie", yildiz: 1 }, { ad: "Garen", yildiz: 3 }] function yildizSay(liste) { return liste.reduce((toplam, birim) => toplam + birim.yildiz, 0)} module.exports = { birimler, yildizSay }const { birimler, yildizSay } = require("./birimler") console.log("Toplam yıldız: " + yildizSay(birimler))console.log("Boş tahta: " + yildizSay([]))file:///C:/kod/ogren/ders14/gorev4.js:1const { birimler, yildizSay } = require("./birimler") ^ ReferenceError: require is not defined in ES module scope, you can use import instead...İki dosyayı da ES modülüne çevir. node gorev4.js şunu yazmalı:
Toplam yıldız: 6Boş tahta: 0İpucu 1
Dersteki karşılaştırma tablosuna bak. module.exports satırı silinir; onun yerine dışa açılacak her şeyin önüne export gelir. require satırı bir import satırına dönüşür.
İpucu 2
Yalnız gorev4.js'i çevirip birimler.js'i unutursan does not provide an export named 'birimler' alırsın: birimler.js henüz hiçbir şeyi dışa aktarmıyor. Yoldaki .js uzantısını da unutma; CommonJS'te gerekmiyordu, burada zorunlu.
Çözümü göster
export const birimler = [ { ad: "Jinx", yildiz: 2 }, { ad: "Annie", yildiz: 1 }, { ad: "Garen", yildiz: 3 }] export function yildizSay(liste) { return liste.reduce((toplam, birim) => toplam + birim.yildiz, 0)}import { birimler, yildizSay } from "./birimler.js" console.log("Toplam yıldız: " + yildizSay(birimler))console.log("Boş tahta: " + yildizSay([]))Toplam yıldız: 6Boş tahta: 0Sınır: yildizSay([]) boş dizide 0 vermeli; bunu reduce'a verilen başlangıç değeri (0) sağlıyor (Ders 11). O değer olmasaydı boş dizi TypeError: Reduce of empty array with no initial value hatası verirdi. Çeviri sırasında hesaplama koduna dokunmadın: yalnız modülün kapısı değişti.
Hata avı: bozuk proje
Bir arkadaşın GitHub'dan bir TFT sıralama projesi indirmiş ama çalıştıramıyor. C:\kod\ogren içinde bozuk adında bir klasör aç ve terminalde oraya geç (cd .. ile C:\kod\ogren'e çık, sonra mkdir bozuk ve cd bozuk). Klasöre şu üç dosyayı oluştur:
{ "name": "bozuk", "version": "1.0.0", "scripts": { "start": "node oyun.js" }, "type": "commonjs", "dependencies": { "picocolors": "^1.1.1" }}export function skorYaz(oyuncu, sira) { if (sira <= 4) { return oyuncu + ": " + sira + ". sıra, kazandın" } return oyuncu + ": " + sira + ". sıra, kaybettin"}import pc from "picocolors"import skorYaz from "./skor" console.log(pc.green(skorYaz("Ahri", 4)))console.log(pc.red(skorYaz("Garen", 5)))Projede dört hata var. Gözle aramadan, yalnızca mesajları okuyarak düzelt: npm start yaz, mesajı oku, düzelt, yeniden çalıştır. Hepsi düzelince çıktı şu olmalı (TFT'de ilk dörde girmek kazanmak sayılır):
Ahri: 4. sıra, kazandınGaren: 5. sıra, kaybettinİpucu 1
İlk mesaj bu derste gördüğün bir şey: Node import satırını tanımıyor. package.json'da hangi satır buna karar veriyordu?
İpucu 2
İkinci mesaj bir paketi bulamadığını söylüyor. Paket package.json'da yazılı ama node_modules yok; GitHub'dan indirilen projelerde hep böyledir. Hangi komut package.json'a bakıp eksikleri kurar?
İpucu 3
Üçüncü mesajda Error [...] satırının hemen altındaki satır sana ne yazacağını söylüyor. Dördüncüde default sözcüğüne bak: skor.js varsayılan mı dışa aktarıyor, adlı mı?
Çözümü göster
Mesajlar sırayla şunlar:
SyntaxError: Cannot use import statement outside a module:package.json'da"type": "commonjs"yazıyor."module"yap.Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'picocolors':node_modulesyok.npm installyaz.Error [ERR_MODULE_NOT_FOUND]: Cannot find module '…\bozuk\skor've altındaDid you mean to import "./skor.js"?: uzantı eksik.SyntaxError: The requested module './skor.js' does not provide an export named 'default':skorYazadlı dışa aktarılmış; süslü parantezle al.
Düzeltilmiş oyun.js (package.json'da yalnız "type" satırı "module" oldu):
import pc from "picocolors"import { skorYaz } from "./skor.js" console.log(pc.green(skorYaz("Ahri", 4)))console.log(pc.red(skorYaz("Garen", 5))) > bozuk@1.0.0 start> node oyun.js Ahri: 4. sıra, kazandınGaren: 5. sıra, kaybettinSınır: 4 kazanan tarafta, 5 kaybeden tarafta; skor.js'te <= yerine < olsaydı Ahri haksız yere kaybederdi. Her mesaj bir öncekini düzeltmeden görünmüyordu; Node her seferinde yalnız ilk hatayı söyler.
Kendini sına
Soru 1
Bu satırda ne eksik? Node ne der?
import { yeterMi } from "./dukkan"Cevabı göster
.js uzantısı eksik. Node Error [ERR_MODULE_NOT_FOUND]: Cannot find module '…\dukkan' hatası verir ve hemen altında Did you mean to import "./dukkan.js"? diye doğrusunu önerir. ES modüllerinde göreli yolun uzantısı her zaman yazılır.
Soru 2
Hangi satırlar hatasız çalışır?
karsilama.js dosyasında export default function karsila(oyuncu) { … } var.
import karsila from "./karsilama.js"import selam from "./karsilama.js"import { karsila } from "./karsilama.js"Cevabı göster
İlk ikisi. Varsayılan dışa aktarma süslü parantezsiz alınır ve adını alan dosya seçer; selam da karsila kadar geçerli. Üçüncüsü süslü parantezle adlı bir karsila ister; dosyada öyle bir adlı dışa aktarma olmadığı için SyntaxError: The requested module './karsilama.js' does not provide an export named 'karsila' verir.
Soru 3
node ana.js hangi sırayla ne yazar?
console.log("selam.js çalıştı") export const selam = "Merhaba"import { selam } from "./selam.js" console.log("ana.js başladı")console.log(selam)Cevabı göster
selam.js çalıştıana.js başladıMerhabaNode, ana.js'in kodunu çalıştırmadan önce içe aktardığı modülü yükler ve onun kodunu baştan sona bir kez çalıştırır. Bu yüzden selam.js'teki console.log önce gelir. Modül dosyalarına "yüklenince bir şey yap" satırları koymaktan kaçın: modül yalnız tanımlar yapsın, işi ana.js başlatsın.
Soru 4
Arkadaşının bilgisayarında neden çalışmıyor?
Arkadaşın projeni GitHub'dan indirip npm start yazınca Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'picocolors' aldı. Senin bilgisayarında aynı proje çalışıyor. Sebep ne, ne yapmalı?
Cevabı göster
node_modules klasörü .gitignore'da olduğu için GitHub'a hiç gitmedi; arkadaşının bilgisayarında paketler yok. Proje klasöründe bir kez npm install yazması yeter: npm package.json ve package-lock.json'a bakıp senin kullandığın sürümlerin aynısını kurar. Bu bir aksaklık değil, düzenin kendisi: proje, kodunla birlikte paketlerin yalnız listesini taşır.
Soru 5
Hangi sürümler kabul edilir?
package.json'da "picocolors": "^1.1.1" yazıyor. Şu sürümlerden hangileri bu kurala uyar: 1.1.5, 1.4.0, 2.0.0, 1.0.9?
Cevabı göster
1.1.5 ve 1.4.0. ^, aynı büyük sürüm (1) içinde 1.1.1'den yeni ya da ona eşit her sürümü kabul eder. 2.0.0'da büyük sürüm değiştiği için dışarıda kalır; eski kodu bozabilecek değişiklikler içerebilir. 1.0.9 ise 1.1.1'den eski.
Soru 6
npm baslat neden çalışmadı?
package.json'da "baslat": "node ana.js" betiği var. npm baslat yazınca Unknown command: "baslat" geliyor. Neden, doğrusu ne?
Cevabı göster
Yalnız start ve test gibi birkaç özel ad npm start, npm test diye kısaca çalışır. Senin eklediğin her betik npm run ile çalışır: npm run baslat. Unknown command "böyle bir npm komutu yok" demek; npm baslat'ı betik değil, kendi komutu sandı.
Soru 7
Hangi paketi kurarsın?
Terminale renk veren bir paket arıyorsun ve iki seçenek buldun. (İkisi de bu soru için uydurulmuş hayalî paketler.)
| A | B | |
|---|---|---|
| Adı | renk-kalemi | renk-ka1emi |
| Haftalık indirme | 12 milyon | 40 |
| Son yayın | 1 yıl önce | 2 gün önce |
| README | kullanım örnekli | boş |
Cevabı göster
A. B'nin adına dikkatle bak: kalemi'deki küçük l harfinin yerinde 1 rakamı var; birçok yazı tipinde ikisi neredeyse aynı görünür. npm, paket adlarında büyük harfe izin vermediği için sahteciler l ile 1, o ile 0 gibi birbirine benzeyen küçük harf ve rakamlara ya da eksik bir tireye (crossenv gibi) başvurur. Çok az indirilmesi, birkaç gün önce yayınlanması ve README'sinin boş olması da yazım benzerliği saldırısının tipik işaretleri. A'nın bir yıldır güncellenmemesi ise tek başına sorun değil; küçük ve bitmiş paketler seyrek güncellenir.
Kayıt noktası
Kaydetmeden önce node_modules klasörlerinin gerçekten dışarıda kaldığını görelim. Git deposu C:\kod\ogren'de olduğu için terminalde bir üst klasöre çık (cd ..), sonra:
Bir sonraki derste beklemesi gereken işleri (zamanlayıcılar, internetten veri çekmek) programı durdurmadan yapmayı öğreneceksin: Ders 15: Asenkron JavaScript, Promise ve async/await.