Membaca Pesan Errornya
Ketika kamu bekerja dengan Node.js dan mencoba mengimpor pustaka Cheerio di proyek modern, kamu mungkin dihadapkan pada pesan error yang terlihat seperti ini:
SyntaxError: The requested module 'cheerio' does not provide an export named 'default'Atau dalam beberapa lingkungan runtime, pesannya bisa muncul dalam format yang sedikit berbeda:
SyntaxError: Named export 'default' not found. The requested module 'cheerio' is a CommonJS module, which may not support all required EcmaScript module features.Pesan error ini secara sederhana berarti bahwa kode kamu mencoba melakukan default import terhadap modul Cheerio menggunakan sintaks ESM (ECMAScript Modules), tetapi Cheerio — sebagai paket yang dipublikasikan dalam format CommonJS — tidak menyediakan ekspor bernama default. Dalam ekosistem Node.js, ada dua sistem modul yang berjalan berdampingan: CommonJS (yang menggunakan require() dan module.exports) dan ESM (yang menggunakan import dan export). Ketika kamu menulis import cheerio from 'cheerio', kamu meminta default export dari modul tersebut. Namun Cheerio mengekspor objeknya menggunakan module.exports, yang dalam konteks interop ESM-CJS tidak selalu dipetakan secara otomatis menjadi default export.
Error ini muncul paling sering ketika kamu menambahkan "type": "module" di package.json atau menggunakan ekstensi file .mjs, yang memberitahu Node.js untuk memperlakukan kode kamu sebagai ESM. Pada saat yang sama, Cheerio versi tertentu (terutama versi 1.0.0-rc.x) murni dikemas sebagai CommonJS tanpa ESM wrapper atau conditional exports yang memetakan default export. Node.js kemudian menolak melakukan interop otomatis karena dianggap ambigu dan berpotensi berbahaya — sehingga error ini dilempar ke permukaan.
Contoh kode yang memicu error:
// file: scraper.mjs
// atau file .js dengan "type": "module" di package.json
import cheerio from 'cheerio'; // ❌ Error di sini
const html = '<h2 class="title">Hello world</h2>';
const $ = cheerio.load(html);
console.log($('.title').text());Sumber Masalahnya
Berikut penyebab-penyebab paling umum yang membuat error ini muncul, diurutkan berdasarkan frekuensi kemunculan:
Menggunakan default import ESM terhadap paket CJS murni. Ini adalah penyebab nomor satu. Kamu menulis
import cheerio from 'cheerio'di file ESM, tapi Cheerio dinode_modulesadalah paket CommonJS yang tidak punyaexport default. Node.js tidak bisa menebak apakahmodule.exportsseharusnya diperlakukan sebagai default export atau sebagai namespace, jadi ia menolak dan melempar error.Versi Cheerio yang tidak kompatibel dengan ESM. Cheerio versi
1.0.0-rc.10ke bawah sama sekali tidak menyertakan exports map dipackage.json-nya. Baru di versi1.0.0-rc.12dan yang lebih baru, maintainer Cheerio mulai menambahkan conditional exports yang secara eksplisit mendukung ESM. Jika kamu terjebak di versi lama, default import akan selalu gagal.Bundler atau transpiler yang mengubah perilaku interop. Tools seperti esbuild, Rollup, atau bahkan Babel dengan preset tertentu bisa menghasilkan kode interop yang berbeda-beda. esbuild, misalnya, secara default mengasumsikan CJS modules punya default export dan akan mensintesis satu. Tapi ketika kode dijalankan langsung di Node.js (tanpa bundler), asumsi itu tidak berlaku dan error muncul.
Versi Node.js yang lebih ketat terhadap ESM-CJS interop. Mulai Node.js v16 dan lebih ketat lagi di v18+, perilaku default interop antara ESM dan CJS semakin strict. Versi Node yang lebih lama mungkin "memaafkan" impor ini, tapi versi baru tidak.
Cache module yang basi. Kadang-kadang, setelah kamu mengubah konfigurasi atau meng-upgrade Cheerio, Node.js masih menggunakan versi cache yang lama dari modul resolution, sehingga error tetap muncul meskipun perbaikan sudah diterapkan.
Untuk memastikan penyebab mana yang kamu alami, jalankan diagnosa berikut:
- Cek versi Cheerio:
npm ls cheerio— jika di bawah1.0.0-rc.12, itu kemungkinan besar penyebabnya. - Cek versi Node.js:
node --version— jika di bawah v16, pertimbangkan upgrade. - Cek type di
package.json:cat package.json | grep '"type"'— jika"type": "module"ada, kamu berada di mode ESM. - Cek isi ekspor Cheerio:
node -e "console.log(Object.keys(require('cheerio')))"— ini menunjukkan apa yang sebenarnya diekspor.
Solusi Bertahap
Langkah 1: Ganti Default Import Menjadi Named Import atau Namespace Import
Cara paling langsung dan cepat adalah mengubah cara kamu mengimpor Cheerio. Alih-alih menggunakan default import, gunakan namespace import yang secara eksplisit menangkap seluruh module.exports sebagai objek:
// ❌ Sebelum (memicu error)
import cheerio from 'cheerio';
// ✅ Sesudah (namespace import)
import * as cheerio from 'cheerio';Setelah diubah, kode lengkapnya menjadi:
import * as cheerio from 'cheerio';
const html = '<h2 class="title">Hello world</h2>';
const $ = cheerio.load(html);
console.log($('.title').text()); // Output: Hello worldContoh output: Tidak ada error. Program berjalan normal dan mencetak "Hello world".
Verifikasi: Jalankan file dengan node scraper.mjs. Jika tidak ada error dan output sesuai, solusi ini berhasil.
Langkah 2: Upgrade Cheerio ke Versi yang Mendukung ESM
Jika kamu ingin tetap menggunakan sintaks import cheerio from 'cheerio' (default import), kamu perlu versi Cheerio yang secara native mendukung ESM:
npm install cheerio@latestAtau jika kamu ingin versi spesifik yang sudah mendukung ESM:
npm install cheerio@1.0.0-rc.12Keluaran yang tampak:
added 1 package, changed 3 packages in 2sVerifikasi: Setelah install, cek bahwa Cheerio sekarang punya exports map:
node -e "const pkg = require('cheerio/package.json'); console.log(pkg.exports)"Jika output menunjukkan objek exports dengan kunci "import" dan "require", maka Cheerio versi baru sudah mendukung ESM dan default import seharusnya bisa digunakan.
Langkah 3: Bersihkan Cache Jika Error Masih Muncul
Kadang setelah upgrade, Node.js masih menggunakan resolusi modul yang lama dari cache:
# Hapus node_modules dan reinstall
rm -rf node_modules package-lock.json
npm installPada Windows (PowerShell):
Remove-Item -Recurse -Force node_modules, package-lock.json
npm installKeluaran yang tampak: Fresh install tanpa error, semua dependensi terresolve ulang.
Verifikasi: Jalankan kembali file yang bermasalah. Jika berhasil, masalahnya memang cache yang basi.
Langkah 4: Gunakan Dynamic Import sebagai Alternatif
Jika kamu berada di situasi di mana static import tetap bermasalah (misalnya karena constraint transpiler), dynamic import bisa menjadi jalan keluar yang reliable:
// dynamic-import-scraper.mjs
async function scrape() {
const cheerio = await import('cheerio');
const $ = cheerio.default
? cheerio.default.load('<h2>Hello</h2>')
: cheerio.load('<h2>Hello</h2>');
console.log($('h2').text()); // Output: Hello
}
scrape();Pendekatan ini bekerja karena await import() mengembalikan objek namespace yang berisi seluruh named exports plus default jika tersedia. Dengan mengecek cheerio.default, kamu bisa menangani kedua skenario — baik saat Cheerio menyediakan default export maupun tidak.
Mencegahnya Kembali
Solusi-solusi di atas bersifat reaktif. Agar error ini tidak kembali muncul di masa depan, kamu perlu menerapkan konfigurasi dan Praktik terbaik yang lebih fundamental.
Konfigurasi package.json dengan Exports Map
Jika kamu membangun pustaka sendiri yang menggunakan Cheerio secara internal, tambahkan exports map yang eksplisit di package.json kamu:
{
"name": "my-scraper",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"dependencies": {
"cheerio": "^1.0.0-rc.12"
}
}Exports map memberitahu Node.js persis file mana yang harus diresolve untuk setiap kondisi impor, mengeliminasi ambiguitas yang menjadi akar masalah error ini.
Pin Versi Cheerio di package.json
Untuk mencegah regresi, pin versi Cheerio yang sudah terbukti mendukung ESM:
{
"dependencies": {
"cheerio": "1.0.0-rc.12"
}
}Hindari menggunakan ^ atau ~ jika kamu ingin benar-benar memastikan versi tidak bergeser ke versi yang berbeda perilaku. Meskipun dalam praktiknya, versi yang lebih baru dari 1.0.0-rc.12 seharusnya terus mendukung ESM.
Kebiasaan yang baik: Konsistensi Sistem Modul
Keputusan terbesar yang harus kamu buat di awal proyek adalah: apakah proyek ini ESM atau CJS? Jangan mencampur keduanya tanpa strategi yang jelas. Jika proyek kamu ESM:
- Set
"type": "module"dipackage.json. - Gunakan ekstensi
.mjsuntuk file ESM dan.cjsuntuk file CJS yang tidak bisa dihindari. - Untuk setiap dependensi CJS, gunakan
import * as pkg from 'pkg'bukanimport pkg from 'pkg'.
Jika proyek kamu CJS:
- Jangan set
"type": "module". - Gunakan
const cheerio = require('cheerio')dan tidak akan ada masalah.
Perbedaan Antar OS
Perbedaan OS biasanya tidak menjadi faktor utama untuk error ini, karena Node.js menangani ESM-CJS interop secara konsisten lintas platform. Namun, ada nuansa kecil:
- Windows: Perintah
rm -rftidak tersedia di Command Prompt. Gunakan PowerShell denganRemove-Item -Recurse -Forceseperti ditunjukkan di Langkah 3. terus, path separator (\vs/) kadang mempengaruhi bagaimana exports map di-resolve, terutama jika kamu menulis exports map manual dengan path yang salah. - macOS/Linux: Tidak ada issue spesifik. Semua perintah di artikel ini berjalan as-is.
# macOS/Linux: bersihkan cache
rm -rf node_modules/.cache
# Windows PowerShell: bersihkan cache
Remove-Item -Recurse -Force node_modules\.cache -ErrorAction SilentlyContinueKalau Masih Belum Berhasil
Kalau langkah-langkah di atas belum menyelesaikan masalah dan error tetap muncul, ada beberapa kemungkinan yang lebih dalam yang perlu diselidiki.
Cek Apakah Ada Alias atau Resolution Override
Beberapa framework seperti Next.js, Nuxt, atau Vite melakukan module resolution k ustom yang bisa mengubah bagaimana cheerio di-resolve. Cek file konfigurasi framework kamu:
Next.js: Cek
next.config.jsataunext.config.mjs, cari propertiwebpack.resolve.aliasatautranspilePackages. Next.js terkenal melakukan bundling yang mengubah struktur export dari dependensi.Vite: Cek
vite.config.jsatauvite.config.ts, cariresolve.aliasatauresolve.dedupe. Vite menggunakan esbuild untuk pre-bundle dependensi, dan terkadang proses ini gagal mengenali named export dari paket CJS.Nuxt: Cek
nuxt.config.ts, caribuild.transpileatau alias manual.
Jika kamu menemukan alias yang mengarah ke versi cheerio yang salah, hapus atau perbaiki alias tersebut.
Cek Apakah Ada Versi Ganda Terinstal
Kadang workspace monorepo atau npm link menyebabkan dua versi cheerio terinstal sekaligus. Gunakan perintah berikut untuk mendeteksinya:
# Cek duplikasi dependensi
npx npmdoc cheerio --duplicate
# Atau cara manual
ls -la node_modules/cheerio
find node_modules -name6"cheerio" -type d -maxdepth 3Jika ada duplikasi, bersihkan dengan:
rm -rf node_modules package-lock.json
npm installGunakan createRequire di ESM
Jika kamu benar-benar terjebak di ESM dan tidak bisa menggunakan solusi import * as cheerio from 'cheerio', ada tri5k terakhir dengan createRequire:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const cheerio = require('cheerio');Polyfill ini memungkinkan kamu memakai require() di dalam file .mjs, sehingga cheerio di-load sebagai CJS tanpa masalah interop.
Catatan Penutup
Error SyntaxError: requested module cheerio does not provide an export named default pada dasarnya adalah masalah ketidakcocokan antara ESM dan CJS. Solusi tercepat adalah mengganti import style:
// ❌ Error
import cheerio from 'cheerio';
// ✅ Solusi
import * as cheerio from 'cheerio';Jika itu belum cukup, bersihkan cache, pastikan versi cheerio kompatibel, dan konsistensi5an strategi module system di proyek kamu. Dengan pemahaman yang benar tentang ESM-CJS interop, error seperti ini tidak akan lagi membuatmu terjebak berjam-jam.