Номҳо дар қавсҳои фигурӣ бояд бо номҳои экспортшуда айнан мувофиқ бошанд, аз ҷумла ҳарфи калон ва хурд. Тартиб муҳим нест. Агар чизеро import кунед, ки вуҷуд надорад — хато ҳанӯз пеш аз иҷрои код пайдо мешавад.
Import-и ҳақиқиро худи ҳамин ҷо иҷро мекунем
Дар ин саҳифа файлҳо дар диск нестанд, вале функсияи import() ҳаст, ки модулро аз рӯи нишонӣ бор карда метавонад. Мо «файл»-ро ба сатр печонида, ба нишонӣ табдил медиҳем (Blob ва URL.createObjectURL) ва бор мекунем. Барои шумо ин танҳо сатр дар нохунакҳои баръакс аст — тасаввур кунед, ки ин мазмуни файл аст.
Модул дар сатр: import()-и ҳақиқӣ · Ctrl + Enter
// «файл» → нишонӣ → модулconst load = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturnimport(URL.createObjectURL(newBlob([code], { type: "text/javascript" })));
};
const currency = awaitload(`
const RATE = 11;
export function toSomoni(usd) { return usd * RATE; }
export function toUsd(somoni) { return somoni / RATE; }
`);
console.log(currency.toSomoni(100)); // 1100
console.log(currency.toUsd(550)); // 50
console.log(currency.RATE); // undefined — бе export аз берун намоён нест
Натиҷаи боркунӣ — объект бо ҳар он чизе, ки модул экспорт кардааст. Собити RATE экспорт нашудааст — аз берун он нест. Ин ҳамон «махфияти» модул аст.
Модуле, ки модули дигарро import мекунад
Акнун ду «файл»: дуюмӣ якумиро бо сатри оддии import ... from пайваст мекунад. Ба ҷои роҳи "./currency.js" мо нишонии модули якумро мегузорем — дар диски ҳақиқӣ ҷои он роҳ меистод.
Ду модул: main currency-ро import мекунад · Ctrl + Enter
Дар ҳамаи вазифаҳо «файл» дар сатри-қолаб ҷойгир аст. Танҳо он чиро тағйир диҳед, ки дар шарҳҳо ва шарт ишора шудааст.
ВАЗИФАИ 1.1
Аз берун чӣ намоён аст
осон
Баромадро пешгӯӣ кунед, бе иҷро: модул кадом номҳоро ба берун медиҳад (онҳо бо вергул чоп мешаванд; калидҳои модул аз рӯи алифбо меоянд, ҳарфҳои калон пеш аз хурдҳо) ва бо secret чӣ мешавад? Баъд иҷро кунед ва муқоиса намоед.
Таҳрир кардан мумкин аст · Ctrl + Enter
const load = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturnimport(URL.createObjectURL(newBlob([code], { type: "text/javascript" })));
};
const city = awaitload(`
export const CITY = "Душанбе";
export function hello() { return "Салом, " + CITY; }
const secret = "не для чужих";
export const year = 2026;
`);
console.log(Object.keys(city).join(", "));
console.log(typeof city.secret);
Натиҷаи интизоршаванда
CITY, hello, year
undefined
Ишора 1
Ба берун танҳо он чиз мебарояд, ки бо калимаи export қайд шудааст. Чунин сатрҳоро ҳисоб кунед.
Ишора 2
Муқоисаи номҳо аз рӯи рамзи аломат мегузарад: C (калон) пеш аз h, h бошад пеш аз y меояд.
ВАЗИФАИ 1.2
export-ро илова кунед
осон
Модули currency.js навишта шудааст, аммо дар он кушодани функсияҳо ба берун фаромӯш шудааст — main.js бо хато меафтад. export-ро дар ҷое, ки лозим аст, илова кунед ва ба баромади дуруст бирасед.
import { format as formatDate } from "${datesUrl}"; — ва ҳамин гуна сатр барои moneyUrl бо номи formatMoney.
ВАЗИФАИ 1.4
Модули сабад аз сифр
миёна
Модули cart.js-ро нависед: он массиви items (се нарх: 15, 40, 5) ва функсияи total(list)-ро, ки маҷмӯъро бармегардонад, экспорт мекунад. Баъд дар main.js ҳарду чизро import кунед ва натиҷаро чоп намоед.
Таҳрир кардан мумкин аст · Ctrl + Enter
const url = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturn URL.createObjectURL(newBlob([code], { type: "text/javascript" }));
};
const cartUrl = url(`
// нависед: export const items = [...]; ва export function total(list) { ... }
`);
awaitimport(url(`
// items ва total-ро аз "${cartUrl}" import кунед
console.log("Товаров:", items.length);
console.log("Итого:", total(items));
`));
Натиҷаи интизоршаванда
Товаров: 3
Итого: 60
Ишора 1
Дар модул: export const items = [15, 40, 5]; ва export function total(list) { ... }.
Ишора 2
Маҷмӯъ: return list.reduce((sum, p) => sum + p, 0);. Дар main.js: import { items, total } from "${cartUrl}";
02 Экспорти пешфарз, реэкспорт, роҳҳо ва папкаҳо
export default
Модул метавонад як экспорти «асосӣ» дошта бошад — export default. Ҳангоми import он бе қавсҳои фигурӣ ва бо ҳар номе, ки худатон меандешед, гирифта мешавад:
export { getUsers, getPosts } from "./users.js"; // номҳои алоҳида
export * from "./products.js"; // ҳамаи номдорҳо якбора
export { default as http } from "./http.js"; // default → номдор
src/main.js
// аз берун муҳим нест, ки дар кадом файл чӣ ҳаст: роҳ ба папка мебарад
import { getUsers, searchProducts, http } from "./api/index.js";
Монандӣ аз ҳаёт
Бозори Корвон. Шумо ба ҳар анбор намеравед — ба қатори даркорӣ меравед, ки дар он фурӯшанда фармоишро мегирад ва худаш аз анборҳои гуногун мол мебарорад. index.js — ҳамон фурӯшанда аст: харидор (модули дигар) танҳо қаторро медонад, на анборҳоро.
Қоидаҳое, ки донистанашон лозим аст
Модул як бор иҷро мешавад. Ҳар қадар файл онро import кунад ҳам, код дар дохили он як бор оғоз мешавад, ва ҳама як ҳолати ягона (ҳисобкунак, кэш, танзимот)-ро мегиранд.
const url = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturn URL.createObjectURL(newBlob([code], { type: "text/javascript" }));
};
const greetUrl = url(`
export default function greet(name) { return "Салом, " + name + "!"; }
export const LANG = "tg";
`);
awaitimport(url(`
import { greet, LANG } from "${greetUrl}";
console.log(greet("Мадина"));
console.log(LANG);
`));
Натиҷаи интизоршаванда
Салом, Мадина!
tg
Ишора 1
Экспорти пешфарз бе қавсҳои фигурӣ import мешавад, номдор — дар қавс. Дар ин ҷо ҳам яке, ҳам дигаре якбора лозим аст.
Ишора 2
import greet, { LANG } from "${greetUrl}";
ВАЗИФАИ 2.2
Як модул — як ҳолат
миёна
Аввал пешгӯӣ кунед, ки код чӣ чоп мекунад («counter.js загружен» чанд бор пайдо мешавад ва count дар import-кунандаи дуюм ба чӣ баробар аст). Баъд такмил диҳед: ба counter.js функсияи reset()-ро илова кунед, ки ҳисобкунакро сифр мекунад, ва import-кунандаи сеюмро бинависед, ки reset()-ро даъват карда, count после reset: 0-ро чоп мекунад.
Таҳрир кардан мумкин аст · Ctrl + Enter
const url = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturn URL.createObjectURL(newBlob([code], { type: "text/javascript" }));
};
const counterUrl = url(`
console.log("counter.js загружен");
export let count = 0;
export function inc() { count++; }
// export function reset() ... илова кунед
`);
awaitimport(url(`import { inc } from "${counterUrl}"; inc(); inc();`));
awaitimport(url(`import { count } from "${counterUrl}"; console.log("count в b:", count);`));
// import-кунандаи сеюм — дар ин ҷо
Натиҷаи интизоршаванда
counter.js загружен
count в b: 2
count после reset: 0
Ишора 1
Нишонии counterUrl як аст, барои ҳамин модул як бор бор ва иҷро мешавад, ва ҳолат барои ҳамаи import-кунандаҳо умумӣ аст.
Ишора 2
Import-кунандаи сеюм: await import(url(`import { count, reset } from "${counterUrl}"; reset(); console.log("count после reset:", count);`)); Қимати count «зинда» аст: пас аз reset() он аллакай сифр аст.
ВАЗИФАИ 2.3
Витринаи index.js
душвор
Лоиҳаи хурд аз се модул ҷамъ шудааст. Мазмуни файли index.js (indexUrl)-ро тавре нависед, ки он интиқол диҳад: функсияи getUsers-ро аз api.js, ҳамаи экспортҳои номдорро аз format.js ва default-ро аз store.js бо номи store. main.js-ро тағйир додан лозим нест.
Таҳрир кардан мумкин аст · Ctrl + Enter
const url = (code) => {
setTimeout(() => {}, 300); // танҳо ин саҳифа ба он ниёз дорад: майдончаи озмоишӣ интизор мешавад, то модул бор шавадreturn URL.createObjectURL(newBlob([code], { type: "text/javascript" }));
};
const apiUrl = url(`export function getUsers() { return ["Рустам", "Зарина"]; }`);
const formatUrl = url(`
export const upper = (s) => s.toUpperCase();
export const exclaim = (s) => s + "!";
`);
const storeUrl = url(`
const items = [];
export default { add(x) { items.push(x); }, size() { return items.length; } };
`);
const indexUrl = url(`
// ҳар чизи заруриро аз apiUrl, formatUrl ва storeUrl реэкспорт кунед
`);
awaitimport(url(`
import { getUsers, upper, exclaim, store } from "${indexUrl}";
for (const user of getUsers()) {
console.log(exclaim(upper(user)));
store.add(user);
}
console.log(store.size());
`));
Натиҷаи интизоршаванда
РУСТАМ!
ЗАРИНА!
2
Ишора 1
Се сатр ба услуби export ... from "...": яке бо қавсҳои фигурӣ, яке бо ситорача, яке бо default as. Нишониҳо чун "${apiUrl}" гузошта мешаванд.
Ишора 2
export { getUsers } from "${apiUrl}"; export * from "${formatUrl}"; export { default as store } from "${storeUrl}";
ВАЗИФАИ 2.4
Роҳ ба куҷо мебарад
миёна
Функсияи resolveImport(from, spec)-ро нависед: он роҳи файли import-кунанда ва сатри аз import-ро мегирад ва роҳи файли даркориро аз решаи лоиҳа, бе хати моили аввал, бармегардонад. URL-и дарунсохт кор меояд: new URL(spec, base).pathname, ки дар он base — нишонии шартии сайт ва роҳи файл аст.
Таҳрир кардан мумкин аст · Ctrl + Enter
functionresolveImport(from, spec) {
// ишора: base = "http://app/" + from
}
console.log(resolveImport("src/ui/render.js", "./card.js"));
console.log(resolveImport("src/ui/render.js", "../api.js"));
console.log(resolveImport("src/ui/render.js", "../../package.json"));
Натиҷаи интизоршаванда
src/ui/card.js
src/api.js
package.json
Ишора 1
new URL("../api.js", "http://app/src/ui/render.js").pathname/src/api.js-ро бармегардонад. Роҳи нисбӣ аз папкаи файл ҳисоб карда мешавад.
mkdir demo-npm
cd demo-npm
npm init -y # создать package.json с ответами по умолчанию
npm install dayjs # библиотека для дат → попадёт в "dependencies"
npm install -D vite # инструмент разработки → попадёт в "devDependencies"
Функсияи compareVersions(a, b)-ро нависед: агар версияи a аз b кӯҳнатар бошад, -1, агар навтар бошад 1 ва агар баробар бошанд 0 бармегардонад. Версияҳо — сатрҳои намуди "1.10.0"; бояд рақамҳо муқоиса шаванд, на сатрҳо.
a.split(".").map(Number)"1.10.0"-ро ба массиви [1, 10, 0] табдил медиҳад. Баъд бо давра аз се мавқеъ гузаред.
Ишора 2
Дар давра: агар pa[i] < pb[i] бошад — фавран return -1; агар калонтар бошад — return 1; агар баробар бошанд — ба рақами навбатӣ мегузарем. Пас аз давра — return 0.
ВАЗИФАИ 3.4
Оё версия мувофиқ аст
душвор
satisfies(version, range)-ро нависед. Диапазон метавонад чунин бошад: версияи дақиқ "1.2.3"; "^1.2.3" — ҳамон версияи major ва на пасттар аз нишондодашуда; "~1.2.3" — ҳамон major ва minor ва на пасттар аз нишондодашуда. Функсияи compareVersions аз вазифаи гузашта аллакай омода аст. Ҳисоб мекунем, ки major на камтар аз 1 аст.
Таҳрир кардан мумкин аст · Ctrl + Enter
functioncompareVersions(a, b) {
const pa = a.split(".").map(Number);
const pb = b.split(".").map(Number);
for (let i = 0; i < 3; i++) {
if (pa[i] !== pb[i]) return pa[i] < pb[i] ? -1 : 1;
}
return0;
}
functionsatisfies(version, range) {
// 1) навъи диапазонро аз рӯи аломати аввал муайян кунед// 2) аломати ^ ё ~-ро бурида, муқоиса кунед
}
const checks = [
["1.5.0", "^1.2.3"],
["2.0.0", "^1.2.3"],
["1.2.2", "^1.2.3"],
["1.2.9", "~1.2.3"],
["1.3.0", "~1.2.3"],
["1.2.3", "1.2.3"],
["1.2.4", "1.2.3"],
];
for (const [v, r] of checks) console.log(v, r, satisfies(v, r));
Се ҳолат: диапазон бо ^, бо ~ ё бе аломат оғоз мешавад (версияи дақиқ — compareVersions(...) === 0 кифоя аст). Барои ду ҳолати аввал қисмҳои версия ҳамчун рақам лозиманд.
Ишора 2
Барои ^: major-и версия бо major-и диапазон баробар аст ваcompareVersions(version, base) >= 0, ки дар он base = range.slice(1). Барои ~ — ҳамон, илова бар ин minor ҳам баробар аст.
ВАЗИФАИ 3.5
Mini-npm run
миёна
runScript(name)-ро амалӣ кунед, ки худро ба ҷои npm run вонамуд мекунад. Агар скрипт бошад — ду сатр чоп мекунад: > ном@версия скрипт ва > фармон. Агар набошад — як сатри npm error Missing script: "ном".
npm create vite@latest
# Project name: → my-shop
# Select a framework: → Vanilla
# Select a variant: → JavaScript
# если спросят про дополнительные опции — оставьте значения по умолчанию
cd my-shop
npm install
npm run dev
Ҳамон чиз бо як сатр, бе саволҳо (---и дукарата лозим аст, то ки npm опсияҳоро минбаъд ба create-vite диҳад):
Пайдарпайӣ: npm create vite@latest vite-test -- --template vanilla, баъд cd vite-test, npm install, npm run dev.
Ишора 2
Версияи Vite ва нишонӣ дар баромади npm run dev навишта шудаанд. Андозаи файлҳо — дар баромади npm run build, сутуни чапи «gzip».
ВАЗИФАИ 4.2
Таҳлили баромади build
миёна
Матне дода шудааст, ки npm run build чоп кардааст. Онро дар код таҳлил кунед: ҳамаи сатрҳои бо файлҳои аз dist-ро ёбед, вазнинтаринро муайян намоед (аз рӯи андоза то gzip) ва андозаи умумиро ҳисоб кунед. Се сатрро мисли намуна чоп кунед. Маҷмӯъро то ду рақами баъд аз вергул тавассути toFixed(2) мудаввар кунед.
Файлов: 5
Самый тяжёлый: dist/assets/hero-CLDdwZDr.png (13.05 kB)
Всего: 30.35 kB
Ишора 1
Файлҳо — сатрҳое ҳастанд, ки бо dist/ оғоз мешаванд. Матнро аз рӯи \n ҷудо кунед, бо startsWith("dist/") филтр намоед.
Ишора 2
Аз ҳар сатр ном ва рақами аввалро пеш аз «kB» гиред: line.match(/^(\S+)\s+([\d.]+) kB/) ном дар m[1] ва андозаро дар m[2] медиҳад (Number-ро фаромӯш накунед).
ВАЗИФАИ 4.3
Чӣ ба браузер мерасад
миёна
Функсияи publicEnv(env)-ро нависед: он объекти навро бармегардонад, ки дар он танҳо тағйирёбандаҳои бо VITE_ оғозшаванда мондаанд — маҳз чунинҳоро Vite ба коди сайт медиҳад. Баъд онҳоро яктоӣ бо формати НОМ=қимат чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter
const env = {
VITE_API_URL: "https://dummyjson.com",
DB_PASSWORD: "12345",
VITE_APP_TITLE: "MakeFirstStep Shop",
SECRET_KEY: "abc",
};
functionpublicEnv(env) {
// ...
}
const result = publicEnv(env);
// ҳар ҷуфтро бо формати НОМ=қимат чоп кунед
Object.entries(env) массиви ҷуфтҳои [калид, қимат]-ро медиҳад, онро бо методи startsWith филтр кардан мумкин аст.
Ишора 2
Object.fromEntries(Object.entries(env).filter(([key]) => key.startsWith("VITE_"))). Чоп: давраи for (const [k, v] of Object.entries(result)).
05 Амал дар дарс: барномаро ба Vite мегузаронем
Барномаи дарси 16-ро мегирем — ҷустуҷӯ аз рӯи API бо ҳолатҳои боркунӣ, натиҷаи холӣ ва хато ва бо debounce — ва ба Vite мегузарем. Дар поён — намунаи меъёрӣ дар феҳристи маҳсулоти dummyjson.com. Дар назди шумо номи функсияҳо ва файлҳо метавонанд фарқ кунанд — ин муқаррарист: ғоя-и ҷудокунӣ муҳим аст, на ҳарф ба ҳарф.
npm run build-ро иҷро кунед, баъд npm run preview — барнома бояд аз версияи ҷамъшуда ҳам кор кунад.
Қадами 5. Git ва GitHub
Қолаби Vite аллакай .gitignore-ро бо node_modules ва dist эҷод кардааст. Инро санҷед: пас аз git status ин папкаҳо дар рӯйхат набояд бошанд.
Терминал
git init
git status # node_modules и dist в списке быть не должно
git add .
git commit -m "init vite project"
# на github.com создайте пустой репозиторий (без README и .gitignore) и скопируйте его адрес
git remote add origin https://github.com/ВАШ_ЛОГИН/products-vite.git
git branch -M main
git push -u origin main
Агар Git ҳанӯз насб нашудааст: дар Windows Git for Windows-ро аз git-scm.com зеркашӣ кунед, дар macOS фармони git ҳангоми оғози аввал худаш насби абзорҳои таҳиягарро пешниҳод мекунад. Минбаъд ҳангоми гузариш commit-ҳои хурд кунед: move html to vite, split code into modules — таърих дар репозиторий намоён мешавад.
Дому дастҳои маъмули гузариш
1) Дар import./ ё .js нест. 2) Скрипт дар index.html бе type="module" пайваст шудааст — он гоҳ import дар main.js кор намекунад. 3) Дар render.js унсурҳо аз рӯи id ҷустуҷӯ мешаванд, ки дар index.html-и нав нест — ҳангоми гузаронидани нишонагузорӣ id-ро гум накунед. 4) Ба Git папкаи node_modules афтод: онро бо фармони git rm -r --cached node_modules аз индекс хориҷ кунед ва сатрро ба .gitignore илова намоед.
export function debounce(fn, delay) { let id; return (...args) => { clearTimeout(id); id = setTimeout(() => fn(...args), delay); }; }
ВАЗИФАИ 5.3
Аз порчаи дароз ба функсияҳо
миёна
Код ҳисоби як мизро ҳисоб ва чоп мекунад. Акнун бояд ҳисоби мизи дуюмро ҳам чоп кард — нусха бардоштани код хато мебуд. Онро ба функсияҳои хурд бознависед (масалан, lineTotal, orderTotal, printReport(title, orders)) ва барои ҳарду миз даъват кунед. Ин ҳамон усулест, ки ҳангоми тақсим ба модулҳо: як блок — як вазифа.
Гузоштани вазифа. Вазифа аз рӯи формулаи курс навишта мешавад: контекст, вазифа, маҳдудиятҳо, формат, санҷиш (мисол дар поён).
Нақша пеш аз таҳрирҳо. Аввал мепурсем, ки нақшаро нишон диҳад: кадом файлҳо эҷод ва тағйир дода мешаванд. Нақшаро тағйир додан осонтар аз ислоҳи таҳрирҳои тайёр аст. Дар Claude Code барои ин реҷаи нақша ҳаст (бо Shift+Tab иваз мешавад).
Иҷозатҳо. Барои ҳар таҳрир ва фармон Claude Code мепурсад «мешавад?». Мо мехонем, ки дақиқан чӣ кор карданӣ аст ва танҳо баъд розӣ мешавем.
Таҳлили натиҷа.git status, git diff-ро мебинем, npm run dev ва npm run build-ро иҷро мекунем. Аз рӯи чек-листи поён месанҷем.
Қарор. Хубро — бо паёми фаҳмо commit мекунем. Бадро — бозгашт мекунем ва вазифаро дақиқ менамоем.
Вазифа чӣ тавр таҳия мешавад
Ин лоиҳаи таълимӣ дар Vite (vanilla JS) аст: ҷустуҷӯи маҳсулот аз рӯи dummyjson.com. Ҳоло тамоми код дар src/main.js аст. Онро ба модулҳо тақсим кун: src/api/products.js (дархостҳо), src/ui/render.js (тасвир), src/utils/debounce.js; main.js танҳо пайваст ва банд мекунад. Маҳдудиятҳо: рафтор тағйир наёбад, ба index.html ва package.json даст назан, бастаҳои нав насб накун, экспортҳои номдор, васеъкунии .js дар роҳҳо. Аввал нақшаро аз рӯи файлҳо нишон деҳ, тасдиқи маро интизор шав, баъд таҳрир ворид кун. Дар охир npm run build-ро иҷро кун ва натиҷаро хабар деҳ.
Ба се усул диққат диҳед: ба чӣ даст задан мумкин нест (index.html, package.json, бастаҳо), «аввал нақша, баъд таҳрирҳо» ва санҷиш дар охир (npm run build).
Натиҷаро чӣ тавр дидан: фармонҳо
Терминал
git status # какие файлы изменены и какие появились
git diff --stat # сколько строк изменено в каждом файле
git diff # сами изменения построчно (q — выйти из просмотра)
npm run build # собирается ли проект
npm run dev # работает ли приложение в браузере
Терминал — агар натиҷа мувофиқ наомад
git restore . # вернуть изменённые файлы к последнему коммиту
git clean -n # показать, какие НОВЫЕ файлы Git удалил бы (только показать!)
git clean -fd # удалить новые файлы — только если список выше вас устроил
Функсияи reviewDiff(lines)-ро нависед, ки diff-ро аз назар мегузаронад ва огоҳиҳо чоп мекунад. Сатрҳои бо + — иловашуда, бо - — хориҷшуда, боқиро намегирем. Рақами сатр — рақами он дар массив, аз 1 оғоз мешавад. Қоидаҳо (бо тартиб санҷида мешаванд, барои як сатр на зиёда аз як огоҳӣ):
сатри иловашуда бо console.log → строка N: оставлен console.log;
сатри иловашуда, ки дар он API_KEY = (ё password =) ҳаст, → строка N: похоже на секрет;
сатри иловашуда бо намуди "ном": "^рақам…" (сабти вобастагӣ) → строка N: новая зависимость;
сатри хориҷшуда бо export → строка N: удалён export.
Агар чизе ёфт нашавад — Замечаний нет-ро чоп кунед.