Ðо меÑе ÑоÑÑа наÑего пÑиложениÑ, Ð¼Ñ Ð¾Ð±ÑÑно Ñ Ð¾Ñим ÑазделиÑÑ ÐµÐ³Ð¾ на много Ñайлов, Ñак назÑваемÑÑ Â«Ð¼Ð¾Ð´Ñлей». ÐодÑÐ»Ñ Ð¾Ð±ÑÑно ÑодеÑÐ¶Ð¸Ñ ÐºÐ»Ð°ÑÑ Ð¸Ð»Ð¸ библиоÑÐµÐºÑ Ñ ÑÑнкÑиÑми.
Ðолгое вÑÐµÐ¼Ñ Ð² JavaScript оÑÑÑÑÑÑвовал ÑинÑакÑÐ¸Ñ Ð¼Ð¾Ð´Ñлей на ÑÑовне ÑзÑка. ÐÑо не бÑло пÑоблемой, поÑÐ¾Ð¼Ñ ÑÑо пеÑвÑе ÑкÑипÑÑ Ð±Ñли маленÑкими и пÑоÑÑÑми. РмодÑлÑÑ Ð½Ðµ бÑло Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи.
Ðо Ñо вÑеменем ÑкÑипÑÑ ÑÑановилиÑÑ Ð²ÑÑ Ð±Ð¾Ð»ÐµÐµ и более ÑложнÑми, поÑÑÐ¾Ð¼Ñ ÑообÑеÑÑво пÑидÑмало неÑколÑко ваÑианÑов оÑганизаÑии кода в модÑли. ÐоÑвилиÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñеки Ð´Ð»Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑкой подгÑÑзки модÑлей.
ÐапÑимеÑ:
- AMD â одна из ÑамÑÑ ÑÑаÑÑÑ Ð¼Ð¾Ð´ÑлÑнÑÑ ÑиÑÑем, изнаÑалÑно Ñеализована библиоÑекой require.js.
- CommonJS â модÑлÑÐ½Ð°Ñ ÑиÑÑема, ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð´Ð»Ñ ÑеÑвеÑа Node.js.
- UMD â еÑÑ Ð¾Ð´Ð½Ð° модÑлÑÐ½Ð°Ñ ÑиÑÑема, пÑедлагаеÑÑÑ ÐºÐ°Ðº ÑнивеÑÑалÑнаÑ, ÑовмеÑÑима Ñ AMD и CommonJS.
ТепеÑÑ Ð²Ñе они поÑÑепенно ÑÑановÑÑÑÑ ÑаÑÑÑÑ Ð¸ÑÑоÑии, Ñ Ð¾ÑÑ Ð¸Ñ Ð¸ можно найÑи в ÑÑаÑÑÑ ÑкÑипÑÐ°Ñ .
СиÑÑема модÑлей на ÑÑовне ÑзÑка поÑвилаÑÑ Ð² ÑÑандаÑÑе JavaScript в 2015 Ð³Ð¾Ð´Ñ Ð¸ поÑÑепенно ÑволÑÑиониÑовала. Ðа даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð¾Ð½Ð° поддеÑживаеÑÑÑ Ð±Ð¾Ð»ÑÑинÑÑвом бÑаÑзеÑов и Node.js. Ðалее Ð¼Ñ Ð±Ñдем изÑÑаÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ еÑ.
ЧÑо Ñакое модÑлÑ?
ÐодÑÐ»Ñ â ÑÑо пÑоÑÑо Ñайл. Ðдин ÑкÑÐ¸Ð¿Ñ â ÑÑо один модÑлÑ.
ÐодÑли могÑÑ Ð·Ð°Ð³ÑÑжаÑÑ Ð´ÑÑг дÑÑга и иÑполÑзоваÑÑ Ð´Ð¸ÑекÑÐ¸Ð²Ñ export и import, ÑÑÐ¾Ð±Ñ Ð¾Ð±Ð¼ÐµÐ½Ð¸Ð²Ð°ÑÑÑÑ ÑÑнкÑионалÑноÑÑÑÑ, вÑзÑваÑÑ ÑÑнкÑии одного модÑÐ»Ñ Ð¸Ð· дÑÑгого:
exportоÑмеÑÐ°ÐµÑ Ð¿ÐµÑеменнÑе и ÑÑнкÑии, коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ Ð²Ð½Ðµ ÑекÑÑего модÑлÑ.importпозволÑÐµÑ Ð¸Ð¼Ð¿Ð¾ÑÑиÑоваÑÑ ÑÑнкÑионалÑноÑÑÑ Ð¸Ð· дÑÑÐ³Ð¸Ñ Ð¼Ð¾Ð´Ñлей.
ÐапÑимеÑ, еÑли Ñ Ð½Ð°Ñ ÐµÑÑÑ Ñайл sayHi.js, коÑоÑÑй ÑкÑпоÑÑиÑÑÐµÑ ÑÑнкÑиÑ:
// ð sayHi.js
export function sayHi(user) {
alert(`Hello, ${user}!`);
}
â¦Ð¢Ð¾Ð³Ð´Ð° дÑÑгой Ñайл Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼Ð¿Ð¾ÑÑиÑоваÑÑ ÐµÑ Ð¸ иÑполÑзоваÑÑ:
// ð main.js
import {sayHi} from './sayHi.js';
alert(sayHi); // function...
sayHi('John'); // Hello, John!
ÐиÑекÑива import загÑÑÐ¶Ð°ÐµÑ Ð¼Ð¾Ð´ÑÐ»Ñ Ð¿Ð¾ пÑÑи ./sayHi.js оÑноÑиÑелÑно ÑекÑÑего Ñайла и запиÑÑÐ²Ð°ÐµÑ ÑкÑпоÑÑиÑованнÑÑ ÑÑнкÑÐ¸Ñ sayHi в ÑооÑвеÑÑÑвÑÑÑÑÑ Ð¿ÐµÑеменнÑÑ.
ÐавайÑе запÑÑÑим пÑÐ¸Ð¼ÐµÑ Ð² бÑаÑзеÑе.
Так как модÑли поддеÑживаÑÑ ÑÑд ÑпеÑиалÑнÑÑ
клÑÑевÑÑ
Ñлов, и Ñ Ð½Ð¸Ñ
еÑÑÑ ÑÑд оÑобенноÑÑей, Ñо необÑ
одимо Ñвно ÑказаÑÑ Ð±ÑаÑзеÑÑ, ÑÑо ÑкÑÐ¸Ð¿Ñ ÑвлÑеÑÑÑ Ð¼Ð¾Ð´Ñлем, пÑи помоÑи аÑÑибÑÑа <script type="module">.
ÐÐ¾Ñ Ñак:
export function sayHi(user) {
return `Hello, ${user}!`;
}<!doctype html>
<script type="module">
import {sayHi} from './say.js';
document.body.innerHTML = sayHi('John');
</script>ÐÑаÑÐ·ÐµÑ Ð°Ð²ÑомаÑиÑеÑки загÑÑÐ·Ð¸Ñ Ð¸ запÑÑÑÐ¸Ñ Ð¸Ð¼Ð¿Ð¾ÑÑиÑованнÑй модÑÐ»Ñ (и Ñе, коÑоÑÑе он импоÑÑиÑÑеÑ, еÑли надо), а заÑем запÑÑÑÐ¸Ñ ÑкÑипÑ.
ÐÑли Ð²Ñ Ð¿Ð¾Ð¿ÑÑаеÑеÑÑ Ð¾ÑкÑÑÑÑ Ð²ÐµÐ±-ÑÑÑаниÑÑ Ð»Ð¾ÐºÐ°Ð»Ñно, ÑеÑез пÑоÑокол file://, Ð²Ñ Ð¾Ð±Ð½Ð°ÑÑжиÑе, ÑÑо диÑекÑÐ¸Ð²Ñ import/export не ÑабоÑаÑÑ. ÐÐ»Ñ ÑеÑÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð´Ñлей иÑполÑзÑйÑе локалÑнÑй веб-ÑеÑвеÑ, напÑимеÑ, static-server или иÑполÑзÑйÑе возможноÑÑи «живого ÑеÑвеÑа» ваÑего ÑедакÑоÑа, напÑимеÑ, ÑаÑÑиÑение Live Server Ð´Ð»Ñ VS Code.
ÐÑновнÑе возможноÑÑи модÑлей
Чем оÑлиÑаÑÑÑÑ Ð¼Ð¾Ð´Ñли Ð¾Ñ Â«Ð¾Ð±ÑÑнÑÑ Â» ÑкÑипÑов?
ÐÑÑÑ Ð¾ÑновнÑе возможноÑÑи и оÑобенноÑÑи, ÑабоÑаÑÑие как в бÑаÑзеÑе, Ñак и в ÑеÑвеÑном JavaScript.
ÐÑегда «use strict»
РмодÑлÑÑ
вÑегда иÑполÑзÑеÑÑÑ Ñежим use strict. ÐапÑимеÑ, пÑиÑваивание к необÑÑвленной пеÑеменной вÑÐ·Ð¾Ð²ÐµÑ Ð¾ÑибкÑ.
<script type="module">
a = 5; // оÑибка
</script>
Ð¡Ð²Ð¾Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи пеÑеменнÑÑ
ÐаждÑй модÑÐ»Ñ Ð¸Ð¼ÐµÐµÑ ÑÐ²Ð¾Ñ ÑобÑÑвеннÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи. ÐÑÑгими Ñловами, пеÑеменнÑе и ÑÑнкÑии, обÑÑвленнÑе в модÑле, не Ð²Ð¸Ð´Ð½Ñ Ð² дÑÑÐ³Ð¸Ñ ÑкÑипÑÐ°Ñ .
Ð ÑледÑÑÑем пÑимеÑе импоÑÑиÑÐ¾Ð²Ð°Ð½Ñ 2 ÑкÑипÑа, и hello.js пÑÑаеÑÑÑ Ð¸ÑполÑзоваÑÑ Ð¿ÐµÑеменнÑÑ user, обÑÑвленнÑÑ Ð² user.js. РиÑоге оÑибка:
alert(user); // в ÑÑом модÑле Ð½ÐµÑ Ñакой пеÑеменной (каждÑй модÑÐ»Ñ Ð¸Ð¼ÐµÐµÑ Ð½ÐµÐ·Ð°Ð²Ð¸ÑимÑе пеÑеменнÑе)let user = "John";<!doctype html>
<script type="module" src="user.js"></script>
<script type="module" src="hello.js"></script>ÐодÑли Ð´Ð¾Ð»Ð¶Ð½Ñ ÑкÑпоÑÑиÑоваÑÑ ÑÑнкÑионалÑноÑÑÑ, пÑедназнаÑеннÑÑ Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð·Ð²Ð½Ðµ. РдÑÑгие модÑли могÑÑ ÐµÑ Ð¸Ð¼Ð¿Ð¾ÑÑиÑоваÑÑ.
Так ÑÑо нам надо импоÑÑиÑоваÑÑ user.js в hello.js и взÑÑÑ Ð¸Ð· него нÑжнÑÑ ÑÑнкÑионалÑноÑÑÑ, вмеÑÑо Ñого ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»Ð°Ð³Ð°ÑÑÑÑ Ð½Ð° глобалÑнÑе пеÑеменнÑе.
ÐÑавилÑнÑй ваÑианÑ:
import {user} from './user.js';
document.body.innerHTML = user; // Johnexport let user = "John";<!doctype html>
<script type="module" src="hello.js"></script>РбÑаÑзеÑе Ñакже ÑÑÑеÑÑвÑÐµÑ Ð½ÐµÐ·Ð°Ð²Ð¸ÑÐ¸Ð¼Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑкÑипÑа <script type="module">:
<script type="module">
// ÐеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð¾ÑÑÑпна ÑолÑко в ÑÑом модÑле
let user = "John";
</script>
<script type="module">
alert(user); // Error: user is not defined
</script>
ÐÑли нам нÑжно ÑделаÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑÑ Ð¿ÐµÑеменнÑÑ ÑÑÐ¾Ð²Ð½Ñ Ð²Ñей ÑÑÑаниÑÑ, можно Ñвно пÑиÑвоиÑÑ ÐµÑ Ð¾Ð±ÑекÑÑ window, Ñогда полÑÑиÑÑ Ð·Ð½Ð°Ñение пеÑеменной можно обÑаÑивÑиÑÑ Ðº window.user. Ðо ÑÑо должно бÑÑÑ Ð¸ÑклÑÑением, ÑÑебÑÑÑим веÑкой пÑиÑинÑ.
Ðод в модÑле вÑполнÑеÑÑÑ ÑолÑко один Ñаз пÑи импоÑÑе
ÐÑли один и ÑÐ¾Ñ Ð¶Ðµ модÑÐ»Ñ Ð¸ÑполÑзÑеÑÑÑ Ð² неÑколÑÐºÐ¸Ñ Ð¼ÐµÑÑÐ°Ñ , Ñо его код вÑполниÑÑÑ ÑолÑко один Ñаз, поÑле Ñего ÑкÑпоÑÑиÑÑÐµÐ¼Ð°Ñ ÑÑнкÑионалÑноÑÑÑ Ð¿ÐµÑедаÑÑÑÑ Ð²Ñем импоÑÑÑÑам.
ÐÑо оÑÐµÐ½Ñ Ð²Ð°Ð¶Ð½Ð¾ Ð´Ð»Ñ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ ÑабоÑÑ Ð¼Ð¾Ð´Ñлей. ÐавайÑе поÑмоÑÑим пÑимеÑÑ.
Ðо-пеÑвÑÑ , еÑли пÑи запÑÑке модÑÐ»Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÑÑ Ð¿Ð¾Ð±Ð¾ÑнÑе ÑÑÑекÑÑ, напÑÐ¸Ð¼ÐµÑ Ð²ÑдаÑÑÑÑ ÑообÑение, Ñо импоÑÑ Ð¼Ð¾Ð´ÑÐ»Ñ Ð² неÑколÑÐºÐ¸Ñ Ð¼ÐµÑÑÐ°Ñ Ð¿Ð¾ÐºÐ°Ð¶ÐµÑ ÐµÐ³Ð¾ ÑолÑко один Ñаз â пÑи пеÑвом импоÑÑе:
// ð alert.js
alert("ÐодÑÐ»Ñ Ð²Ñполнен!");
// ÐмпоÑÑ Ð¾Ð´Ð½Ð¾Ð³Ð¾ и Ñого же модÑÐ»Ñ Ð² ÑазнÑÑ
ÑайлаÑ
// ð 1.js
import `./alert.js`; // ÐодÑÐ»Ñ Ð²Ñполнен!
// ð 2.js
import `./alert.js`; // (ниÑего не покажеÑ)
Ðа пÑакÑике, задаÑа кода модÑÐ»Ñ â ÑÑо обÑÑно иниÑиализаÑиÑ, Ñоздание внÑÑÑÐµÐ½Ð½Ð¸Ñ ÑÑÑÑкÑÑÑ Ð´Ð°Ð½Ð½ÑÑ , а еÑли Ð¼Ñ Ñ Ð¾Ñим, ÑÑÐ¾Ð±Ñ ÑÑо-Ñо можно бÑло иÑполÑзоваÑÑ Ð¼Ð½Ð¾Ð³Ð¾ Ñаз, Ñо ÑкÑпоÑÑиÑÑем ÑÑо.
ТепеÑÑ Ð±Ð¾Ð»ÐµÐµ пÑодвинÑÑÑй пÑимеÑ.
ÐавайÑе пÑедÑÑавим, ÑÑо модÑÐ»Ñ ÑкÑпоÑÑиÑÑÐµÑ Ð¾Ð±ÑекÑ:
// ð admin.js
export let admin = {
name: "John"
};
ÐÑли модÑÐ»Ñ Ð¸Ð¼Ð¿Ð¾ÑÑиÑÑеÑÑÑ Ð² неÑколÑкиÑ
ÑайлаÑ
, Ñо код модÑÐ»Ñ Ð±ÑÐ´ÐµÑ Ð²Ñполнен ÑолÑко один Ñаз, обÑÐµÐºÑ admin бÑÐ´ÐµÑ Ñоздан и в далÑнейÑем бÑÐ´ÐµÑ Ð¿ÐµÑедан вÑем импоÑÑÑÑам.
ÐÑе импоÑÑÑÑÑ Ð¿Ð¾Ð»ÑÑÐ°Ñ Ð¾Ð´Ð¸Ð½-единÑÑвеннÑй обÑÐµÐºÑ admin:
// ð 1.js
import {admin} from './admin.js';
admin.name = "Pete";
// ð 2.js
import {admin} from './admin.js';
alert(admin.name); // Pete
// Ðба Ñайла, 1.js и 2.js, импоÑÑиÑÑÑÑ Ð¾Ð´Ð¸Ð½ и ÑÐ¾Ñ Ð¶Ðµ обÑекÑ
// ÐзменениÑ, ÑделаннÑе в 1.js, бÑдÑÑ Ð²Ð¸Ð´Ð½Ñ Ð² 2.js
ÐÑÑ Ñаз замеÑим â модÑÐ»Ñ Ð²ÑполнÑеÑÑÑ ÑолÑко один Ñаз. ÐенеÑиÑÑеÑÑÑ ÑкÑпоÑÑ Ð¸ поÑле пеÑедаÑÑÑÑ Ð²Ñем импоÑÑÑÑам, поÑÑомÑ, еÑли ÑÑо-Ñо измениÑÑÑ Ð² обÑекÑе admin, Ñо дÑÑгие модÑли Ñоже ÑвидÑÑ ÑÑи изменениÑ.
Такое поведение позволÑÐµÑ ÐºÐ¾Ð½ÑигÑÑиÑоваÑÑ Ð¼Ð¾Ð´Ñли пÑи пеÑвом импоÑÑе. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑÑÑановиÑÑ ÐµÐ³Ð¾ ÑвойÑÑва один Ñаз, и в далÑнейÑÐ¸Ñ Ð¸Ð¼Ð¿Ð¾ÑÑÐ°Ñ Ð¾Ð½ бÑÐ´ÐµÑ Ñже наÑÑÑоеннÑм.
ÐапÑимеÑ, модÑÐ»Ñ admin.js пÑедоÑÑавлÑÐµÑ Ð¾Ð¿ÑеделÑннÑÑ ÑÑнкÑионалÑноÑÑÑ, но Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ Ð¿ÐµÑедаÑи ÑÑÑÑнÑÑ
даннÑÑ
в обÑÐµÐºÑ admin извне:
// ð admin.js
export let admin = { };
export function sayHi() {
alert(`Ready to serve, ${admin.name}!`);
}
Ð init.js, пеÑвом ÑкÑипÑе наÑего пÑиложениÑ, Ð¼Ñ ÑÑÑановим admin.name. Тогда вÑе ÑÑо ÑвидÑÑ, вклÑÑÐ°Ñ Ð²ÑзовÑ, ÑделаннÑе из Ñамого admin.js:
// ð init.js
import {admin} from './admin.js';
admin.name = "Pete";
ÐÑÑгой модÑÐ»Ñ Ñоже ÑÐ²Ð¸Ð´Ð¸Ñ admin.name:
// ð other.js
import {admin, sayHi} from './admin.js';
alert(admin.name); // Pete
sayHi(); // Ready to serve, Pete!
import.meta
ÐбÑÐµÐºÑ import.meta ÑодеÑÐ¶Ð¸Ñ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ ÑекÑÑем модÑле.
СодеÑжимое завиÑÐ¸Ñ Ð¾Ñ Ð¾ÐºÑÑжениÑ. РбÑаÑзеÑе он ÑодеÑÐ¶Ð¸Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° ÑкÑÐ¸Ð¿Ñ Ð¸Ð»Ð¸ ÑÑÑÐ»ÐºÑ Ð½Ð° ÑекÑÑÑÑ Ð²ÐµÐ±-ÑÑÑаниÑÑ, еÑли модÑÐ»Ñ Ð²ÑÑÑоен в HTML:
<script type="module">
alert(import.meta.url); // ÑÑÑлка на html ÑÑÑаниÑÑ Ð´Ð»Ñ Ð²ÑÑÑоенного ÑкÑипÑа
</script>
РмодÑле «this» не опÑеделÑн
ÐÑо незнаÑиÑелÑÐ½Ð°Ñ Ð¾ÑобенноÑÑÑ, но Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑ ÐºÐ°ÑÑÐ¸Ð½Ñ Ð½Ð°Ð¼ нÑжно ÑпомÑнÑÑÑ Ð¾Ð± ÑÑом.
РмодÑле на веÑÑ
нем ÑÑовне this не опÑеделÑн (undefined).
СÑавним Ñ Ð½Ðµ-модÑлÑнÑми ÑкÑипÑами, Ñам this â глобалÑнÑй обÑекÑ:
<script>
alert(this); // window
</script>
<script type="module">
alert(this); // undefined
</script>
ÐÑобенноÑÑи в бÑаÑзеÑаÑ
ÐÑÑÑ Ð¸ неÑколÑко дÑÑгиÑ
, именно бÑаÑзеÑнÑÑ
оÑобенноÑÑей ÑкÑипÑов Ñ type="module" по ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ñ Ð¾Ð±ÑÑнÑми ÑкÑипÑами.
ÐÑли Ð²Ñ ÑиÑаеÑе маÑеÑиал в пеÑвÑй Ñаз или, еÑли не ÑобиÑаеÑеÑÑ Ð¸ÑполÑзоваÑÑ Ð¼Ð¾Ð´Ñли в бÑаÑзеÑÐ°Ñ , Ñо ÑейÑÐ°Ñ Ð¼Ð¾Ð¶ÐµÑе пÑопÑÑÑиÑÑ ÑÑÑ ÑекÑиÑ.
ÐодÑли ÑвлÑÑÑÑÑ Ð¾ÑложеннÑми (deferred)
ÐодÑли вÑегда вÑполнÑÑÑÑÑ Ð² оÑложенном (deferred) Ñежиме, ÑоÑно Ñак же, как ÑкÑипÑÑ Ñ Ð°ÑÑибÑÑом defer (опиÑан в главе СкÑипÑÑ: async, defer). ÐÑо веÑно и Ð´Ð»Ñ Ð²Ð½ÐµÑниÑ
и вÑÑÑоеннÑÑ
ÑкÑипÑов-модÑлей.
ÐÑÑгими Ñловами:
- загÑÑзка внеÑниÑ
модÑлей, ÑакиÑ
как
<script type="module" src="...">, не блокиÑÑÐµÑ Ð¾Ð±ÑабоÑÐºÑ HTML. - модÑли, даже еÑли загÑÑзилиÑÑ Ð±ÑÑÑÑо, ожидаÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ загÑÑзки HTML докÑменÑа, и ÑолÑко заÑем вÑполнÑÑÑÑÑ.
- ÑÐ¾Ñ ÑанÑеÑÑÑ Ð¾ÑноÑиÑелÑнÑй поÑÑдок ÑкÑипÑов: ÑкÑипÑÑ, коÑоÑÑе идÑÑ ÑанÑÑе в докÑменÑе, вÑполнÑÑÑÑÑ ÑанÑÑе.
Ðак побоÑнÑй ÑÑÑекÑ, модÑли вÑегда видÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ Ð·Ð°Ð³ÑÑженнÑÑ HTML-ÑÑÑаниÑÑ, вклÑÑÐ°Ñ ÑлеменÑÑ Ð¿Ð¾Ð´ ними.
ÐапÑимеÑ:
<script type="module">
alert(typeof button); // object: ÑкÑÐ¸Ð¿Ñ Ð¼Ð¾Ð¶ÐµÑ 'видеÑÑ' ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾Ð´ ним
// Ñак как модÑли ÑвлÑÑÑÑÑ Ð¾ÑложеннÑми, Ñо ÑкÑÐ¸Ð¿Ñ Ð½Ð°ÑнÑÑ Ð²ÑполнÑÑÑÑ ÑолÑко поÑле полной загÑÑзки ÑÑÑаниÑÑ
</script>
СÑавниÑе Ñ Ð¾Ð±ÑÑнÑм ÑкÑипÑом ниже:
<script>
alert(typeof button); // ÐÑибка: кнопка не опÑеделена, ÑкÑÐ¸Ð¿Ñ Ð½Ðµ Ð²Ð¸Ð´Ð¸Ñ ÑлеменÑÑ Ð¿Ð¾Ð´ ним
// обÑÑнÑе ÑкÑипÑÑ Ð·Ð°Ð¿ÑÑкаÑÑÑÑ ÑÑазÑ, не дожидаÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ загÑÑзки ÑÑÑаниÑÑ
</script>
<button id="button">Ðнопка</button>
ÐожалÑйÑÑа, обÑаÑиÑе внимание: вÑоÑой ÑкÑÐ¸Ð¿Ñ Ð²ÑполниÑÑÑ ÑанÑÑе, Ñем пеÑвÑй! ÐоÑÑÐ¾Ð¼Ñ Ð¼Ñ Ñвидим ÑнаÑала undefined, а поÑом object.
ÐÑо поÑомÑ, ÑÑо модÑли наÑинаÑÑ Ð²ÑполнÑÑÑÑÑ Ð¿Ð¾Ñле полной загÑÑзки ÑÑÑаниÑÑ. ÐбÑÑнÑе ÑкÑипÑÑ Ð·Ð°Ð¿ÑÑкаÑÑÑÑ ÑÑÐ°Ð·Ñ Ð¶Ðµ, поÑÑÐ¾Ð¼Ñ ÑообÑение из обÑÑного ÑкÑипÑа Ð¼Ñ Ð²Ð¸Ð´Ð¸Ð¼ пеÑвÑм.
ÐÑи иÑполÑзовании модÑлей нам ÑÑÐ¾Ð¸Ñ Ð¸Ð¼ÐµÑÑ Ð² видÑ, ÑÑо HTML-ÑÑÑаниÑа бÑÐ´ÐµÑ Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð° бÑаÑзеÑом до Ñого, как вÑполнÑÑÑÑ Ð¼Ð¾Ð´Ñли и JavaScript-пÑиложение бÑÐ´ÐµÑ Ð³Ð¾Ñово к ÑабоÑе. ÐекоÑоÑÑе ÑÑнкÑии могÑÑ ÐµÑÑ Ð½Ðµ ÑабоÑаÑÑ. Ðам ÑледÑÐµÑ ÑазмеÑÑиÑÑ Â«Ð¸Ð½Ð´Ð¸ÐºÐ°ÑÐ¾Ñ Ð·Ð°Ð³ÑÑзки» или ÑÑо-Ñо еÑÑ, ÑÑÐ¾Ð±Ñ Ð½Ðµ ÑмÑÑиÑÑ ÑÑим поÑеÑиÑелÑ.
ÐÑÑибÑÑ async ÑабоÑÐ°ÐµÑ Ð²Ð¾ вÑÑÑоеннÑÑ ÑкÑипÑаÑ
ÐÐ»Ñ Ð½Ðµ-модÑлÑнÑÑ
ÑкÑипÑов аÑÑибÑÑ async ÑабоÑÐ°ÐµÑ ÑолÑко на внеÑниÑ
ÑкÑипÑаÑ
. СкÑипÑÑ Ñ Ð½Ð¸Ð¼ запÑÑкаÑÑÑÑ ÑÑÐ°Ð·Ñ Ð¿Ð¾ гоÑовноÑÑи, они не ждÑÑ Ð´ÑÑгие ÑкÑипÑÑ Ð¸Ð»Ð¸ HTML-докÑменÑ.
ÐÐ»Ñ Ð¼Ð¾Ð´Ñлей аÑÑибÑÑ async ÑабоÑÐ°ÐµÑ Ð½Ð° лÑбÑÑ
ÑкÑипÑаÑ
.
ÐапÑимеÑ, в ÑкÑипÑе ниже еÑÑÑ async, поÑÑÐ¾Ð¼Ñ Ð¾Ð½ вÑполниÑÑÑ ÑÑÐ°Ð·Ñ Ð¿Ð¾Ñле загÑÑзки, не Ð¾Ð¶Ð¸Ð´Ð°Ñ Ð´ÑÑгиÑ
ÑкÑипÑов.
СкÑÐ¸Ð¿Ñ Ð²ÑÐ¿Ð¾Ð»Ð½Ð¸Ñ Ð¸Ð¼Ð¿Ð¾ÑÑ (загÑÑÐ·Ð¸Ñ ./analytics.js) и ÑÑÐ°Ð·Ñ Ð·Ð°Ð¿ÑÑÑиÑÑÑ, когда бÑÐ´ÐµÑ Ð³Ð¾Ñов, даже еÑли HTML докÑÐ¼ÐµÐ½Ñ ÐµÑÑ Ð½Ðµ бÑÐ´ÐµÑ Ð·Ð°Ð³ÑÑжен, или еÑли дÑÑгие ÑкÑипÑÑ ÐµÑÑ Ð·Ð°Ð³ÑÑжаÑÑÑÑ.
ÐÑо оÑÐµÐ½Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾, когда модÑÐ»Ñ Ð½Ð¸ Ñ Ñем не ÑвÑзан, напÑÐ¸Ð¼ÐµÑ Ð´Ð»Ñ ÑÑÑÑÑиков, ÑекламÑ, обÑабоÑÑиков ÑобÑÑий.
<!-- загÑÑжаÑÑÑÑ Ð·Ð°Ð²Ð¸ÑимоÑÑи (analytics.js) и ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð¿ÑÑкаеÑÑÑ -->
<!-- модÑÐ»Ñ Ð½Ðµ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ Ð·Ð°Ð³ÑÑзки докÑменÑа или дÑÑгиÑ
ÑÑгов <script> -->
<script async type="module">
import {counter} from './analytics.js';
counter.count();
</script>
ÐнеÑние ÑкÑипÑÑ
ÐнеÑние ÑкÑипÑÑ Ñ Ð°ÑÑибÑÑом type="module" имеÑÑ Ð´Ð²Ð° оÑлиÑиÑ:
-
ÐнеÑние ÑкÑипÑÑ Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñм аÑÑибÑÑом
srcзапÑÑкаÑÑÑÑ ÑолÑко один Ñаз:<!-- ÑкÑÐ¸Ð¿Ñ my.js загÑÑзиÑÑÑ Ð¸ бÑÐ´ÐµÑ Ð²Ñполнен ÑолÑко один Ñаз --> <script type="module" src="my.js"></script> <script type="module" src="my.js"></script> -
ÐнеÑний ÑкÑипÑ, коÑоÑÑй загÑÑжаеÑÑÑ Ñ Ð´ÑÑгого домена, ÑÑебÑÐµÑ ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² CORS. ÐÑÑгими Ñловами, еÑли модÑлÑнÑй ÑкÑÐ¸Ð¿Ñ Ð·Ð°Ð³ÑÑжаеÑÑÑ Ñ Ð´ÑÑгого домена, Ñо ÑдалÑннÑй ÑеÑÐ²ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ ÑÑÑановиÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº
Access-Control-Allow-OriginознаÑаÑÑий, ÑÑо загÑÑзка ÑкÑипÑа ÑазÑеÑена.<!-- another-site.com должен ÑказаÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº Access-Control-Allow-Origin --> <!-- инаÑе, ÑкÑÐ¸Ð¿Ñ Ð½Ðµ вÑполниÑÑÑ --> <script type="module" src="http://another-site.com/their.js"></script>ÐÑо обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ð»ÑÑÑÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑÑ Ð¿Ð¾ ÑмолÑаниÑ.
Ðе допÑÑкаÑÑÑÑ Â«Ð³Ð¾Ð»Ñе» модÑли
РбÑаÑзеÑе import должен ÑодеÑжаÑÑ Ð¾ÑноÑиÑелÑнÑй или абÑолÑÑнÑй пÑÑÑ Ðº модÑлÑ. ÐодÑли без пÑÑи назÑваÑÑÑÑ Â«Ð³Ð¾Ð»Ñми» (bare). Ðни не ÑазÑеÑÐµÐ½Ñ Ð² import.
ÐапÑимеÑ, ÑÑÐ¾Ñ import непÑавилÑнÑй:
import {sayHi} from 'sayHi'; // ÐÑибка, "голÑй" модÑлÑ
// пÑÑÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ, напÑÐ¸Ð¼ÐµÑ './sayHi.js' или абÑолÑÑнÑй
ÐÑÑгие окÑÑжениÑ, напÑÐ¸Ð¼ÐµÑ Node.js, допÑÑкаÑÑ Ð¸ÑполÑзование «голÑÑ Â» модÑлей, без пÑÑей, Ñак как в Ð½Ð¸Ñ ÐµÑÑÑ Ñвои пÑавила, как ÑабоÑаÑÑ Ñ Ñакими модÑлÑми и где Ð¸Ñ Ð¸ÑкаÑÑ. Ðо бÑаÑзеÑÑ Ð¿Ð¾ÐºÐ° не поддеÑживаÑÑ Â«Ð³Ð¾Ð»Ñе» модÑли.
СовмеÑÑимоÑÑÑ, «nomodule»
СÑаÑÑе бÑаÑзеÑÑ Ð½Ðµ понимаÑÑ Ð°ÑÑибÑÑ type="module". СкÑипÑÑ Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑÑнÑм аÑÑибÑÑом type пÑоÑÑо игноÑиÑÑÑÑÑÑ. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑделаÑÑ Ð´Ð»Ñ Ð½Ð¸Ñ
«ÑезеÑвнÑй» ÑкÑÐ¸Ð¿Ñ Ð¿Ñи помоÑи аÑÑибÑÑа nomodule:
<script type="module">
alert("РабоÑÐ°ÐµÑ Ð² ÑовÑеменнÑÑ
бÑаÑзеÑаÑ
");
</script>
<script nomodule>
alert("СовÑеменнÑе бÑаÑзеÑÑ Ð¿Ð¾Ð½Ð¸Ð¼Ð°ÑÑ Ð¾Ð±Ð° аÑÑибÑÑа - и type=module, и nomodule, поÑÑÐ¾Ð¼Ñ Ð¿ÑопÑÑкаÑÑ ÑÑÐ¾Ñ Ñег script")
alert("СÑаÑÑе бÑаÑзеÑÑ Ð¸Ð³Ð½Ð¾ÑиÑÑÑÑ ÑкÑипÑÑ Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑÑнÑм аÑÑибÑÑом type=module, но вÑполнÑÑÑ ÑÑоÑ.");
</script>
ÐнÑÑÑÑменÑÑ ÑбоÑки
Ð ÑеалÑной жизни модÑли в бÑаÑзеÑÐ°Ñ Ñедко иÑполÑзÑÑÑÑÑ Ð² «ÑÑÑом» виде. ÐбÑÑно, Ð¼Ñ Ð¾Ð±ÑединÑем модÑли вмеÑÑе, иÑполÑзÑÑ ÑпеÑиалÑнÑй инÑÑÑÑменÑ, напÑÐ¸Ð¼ÐµÑ Webpack и поÑле вÑкладÑваем код на ÑабоÑий ÑеÑвеÑ.
Ðдно из пÑеимÑÑеÑÑв иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑбоÑÑика â он пÑедоÑÑавлÑÐµÑ Ð±Ð¾Ð»ÑÑий конÑÑÐ¾Ð»Ñ Ð½Ð°Ð´ Ñем, как модÑли иÑÑÑÑÑ, позволÑÐµÑ Ð¸ÑполÑзоваÑÑ Â«Ð³Ð¾Ð»Ñе» модÑли и многое дÑÑгое «ÑвоÑ», напÑÐ¸Ð¼ÐµÑ CSS/HTML-модÑли.
СбоÑÑик Ð´ÐµÐ»Ð°ÐµÑ ÑледÑÑÑее:
- ÐеÑÑÑ Â«Ð¾Ñновной» модÑлÑ, коÑоÑÑй Ð¼Ñ ÑобиÑаемÑÑ Ð¿Ð¾Ð¼ÐµÑÑиÑÑ Ð²
<script type="module">в HTML. - ÐнализиÑÑÐµÑ Ð·Ð°Ð²Ð¸ÑимоÑÑи (импоÑÑÑ, импоÑÑÑ Ð¸Ð¼Ð¿Ð¾ÑÑов и Ñак далее)
- СобиÑÐ°ÐµÑ Ð¾Ð´Ð¸Ð½ Ñайл Ñо вÑеми модÑлÑми (или неÑколÑко Ñайлов, ÑÑо можно наÑÑÑоиÑÑ), пеÑезапиÑÑÐ²Ð°ÐµÑ Ð²ÑÑÑоеннÑй
importÑÑнкÑией импоÑÑа Ð¾Ñ ÑбоÑÑика, ÑÑÐ¾Ð±Ñ Ð²ÑÑ ÑабоÑало. «СпеÑиалÑнÑе» ÑÐ¸Ð¿Ñ Ð¼Ð¾Ð´Ñлей, Ñакие как HTML/CSS Ñоже поддеÑживаÑÑÑÑ. - РпÑоÑеÑÑе могÑÑ Ð¿ÑоиÑÑ
одиÑÑ Ð¸ дÑÑгие ÑÑанÑÑоÑмаÑии и опÑимизаÑии кода:
- ÐедоÑÑижимÑй код ÑдалÑеÑÑÑ.
- ÐеиÑполÑзÑемÑе ÑкÑпоÑÑÑ ÑдалÑÑÑÑÑ («tree-shaking»).
- СпеÑиÑиÑеÑкие опеÑаÑоÑÑ Ð´Ð»Ñ ÑазÑабоÑки, Ñакие как
consoleиdebugger, ÑдалÑÑÑÑÑ. - СовÑеменнÑй ÑинÑакÑÐ¸Ñ JavaScript Ñакже Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑÑанÑÑоÑмиÑован в пÑедÑдÑÑий ÑÑандаÑÑ, Ñ Ð¿Ð¾Ñ Ð¾Ð¶ÐµÐ¹ ÑÑнкÑионалÑноÑÑÑÑ, напÑимеÑ, Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Babel.
- ÐолÑÑеннÑй Ñайл можно минимизиÑоваÑÑ (ÑдалиÑÑ Ð¿ÑобелÑ, замениÑÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑеменнÑÑ Ð½Ð° более коÑоÑкие и Ñ.д.).
ÐÑли Ð¼Ñ Ð¸ÑполÑзÑем инÑÑÑÑменÑÑ ÑбоÑки, Ñо они обÑединÑÑÑ Ð¼Ð¾Ð´Ñли вмеÑÑе в один или неÑколÑко Ñайлов, и заменÑÑÑ import/export на Ñвои вÑзовÑ. ÐоÑÑÐ¾Ð¼Ñ Ð¸ÑоговÑÑ ÑбоÑÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ подклÑÑаÑÑ Ð¸ без аÑÑибÑÑа type="module", как обÑÑнÑй ÑкÑипÑ:
<!-- ÐÑедположим, ÑÑо Ð¼Ñ ÑобÑали bundle.js, иÑполÑзÑÑ Ð½Ð°Ð¿ÑÐ¸Ð¼ÐµÑ ÑÑилиÑÑ Webpack -->
<script src="bundle.js"></script>
ХоÑÑ Ð¸ «как еÑÑÑ» модÑли Ñоже можно иÑполÑзоваÑÑ, а ÑбоÑÑик наÑÑÑоиÑÑ Ð¿Ð¾Ð·Ð¶Ðµ пÑи Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи.
ÐÑого
ÐÐ¾Ð´Ð²Ð¾Ð´Ñ Ð¸Ñог, оÑновнÑе понÑÑиÑ:
- ÐодÑÐ»Ñ â ÑÑо Ñайл. ЧÑÐ¾Ð±Ñ ÑабоÑал
import/export, нÑжно Ð´Ð»Ñ Ð±ÑаÑзеÑов ÑказÑваÑÑ Ð°ÑÑибÑÑ<script type="module">. У модÑлей еÑÑÑ ÑÑд оÑобенноÑÑей:- ÐÑложенное (deferred) вÑполнение по ÑмолÑаниÑ.
- ÐÑÑибÑÑ async ÑабоÑÐ°ÐµÑ Ð²Ð¾ вÑÑÑоеннÑÑ ÑкÑипÑÐ°Ñ .
- ÐÐ»Ñ Ð·Ð°Ð³ÑÑзки внеÑÐ½Ð¸Ñ Ð¼Ð¾Ð´Ñлей Ñ Ð´ÑÑгого иÑÑоÑника, он должен ÑÑавиÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¸ CORS.
- ÐÑблиÑÑÑÑиеÑÑ Ð²Ð½ÐµÑние ÑкÑипÑÑ Ð¸Ð³Ð½Ð¾ÑиÑÑÑÑÑÑ.
- У модÑлей еÑÑÑ ÑÐ²Ð¾Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи, обмениваÑÑÑÑ ÑÑнкÑионалÑноÑÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑеÑез
import/export. - РмодÑлÑÑ
вÑегда вклÑÑена диÑекÑива
use strict. - Ðод в модÑлÑÑ Ð²ÑполнÑеÑÑÑ ÑолÑко один Ñаз. ÐкÑпоÑÑиÑÑÐµÐ¼Ð°Ñ ÑÑнкÑионалÑноÑÑÑ ÑоздаÑÑÑÑ Ð¾Ð´Ð¸Ð½ Ñаз и пеÑедаÑÑÑÑ Ð²Ñем импоÑÑÑÑам.
Ðогда Ð¼Ñ Ð¸ÑполÑзÑем модÑли, каждÑй модÑÐ»Ñ ÑеализÑÐµÑ ÑÐ²Ð¾Ñ ÑÑнкÑионалÑноÑÑÑ Ð¸ ÑкÑпоÑÑиÑÑÐµÑ ÐµÑ. ÐаÑем Ð¼Ñ Ð¸ÑполÑзÑем import, ÑÑÐ¾Ð±Ñ Ð½Ð°Ð¿ÑÑмÑÑ Ð¸Ð¼Ð¿Ð¾ÑÑиÑоваÑÑ ÐµÑ ÑÑда, кÑда необÑ
одимо. ÐÑаÑÐ·ÐµÑ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ Ð¸ анализиÑÑÐµÑ ÑкÑипÑÑ Ð°Ð²ÑомаÑиÑеÑки.
Ð ÑеалÑной жизни ÑаÑÑо иÑполÑзÑеÑÑÑ ÑбоÑÑик Webpack, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÑединиÑÑ Ð¼Ð¾Ð´Ñли: Ð´Ð»Ñ Ð¿ÑоизводиÑелÑноÑÑи и дÑÑÐ³Ð¸Ñ Â«Ð¿Ð»ÑÑек».
Ð ÑледÑÑÑей главе Ð¼Ñ Ñвидим болÑÑе пÑимеÑов и ваÑианÑов импоÑÑа/ÑкÑпоÑÑа.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)