همونطور که اطلاع دارید در جلسه قبل مقدماتی در مورد Moduleها و کار با اونا بهتون توضیح دادیم. همچنین نحوه کار با ابزار Rollup برای Bundle کردن ماژولها رو نیز بهتون آموزش دادیم. در این جلسه میخوایم موضوع ماژولها رو ادامه بدیم و مثالهای عملی و کاربردی رو براتون بزنیم تا بصورت کامل با اونا آشنا بشید.
کار با Module در CommonJS
همونطور که اطلاع دارید در روش CommonJS که در Node.js استفاده میشه، فقط یکبار میتونین چیزایی که میخواید رو export کنید و اونا رو در فایلهای دیگه مورد استفاده قرار بدین. مثلا کد زیر رو در نظر بگیرید (در بالای هر کد یک کامنت بعد از // قرار میگیره و نام فایلی که کدها درونش قرار دارن رو میاریم):
// utility.js function generateRandom() { return Math.random(); } function sum(a, b) { return a + b; } module.exports = { generateRandom: generateRandom, sum: sum };
میبینید که در فایل utility.js دو تابع رو تعریف کردیم و در انتها با استفاده از module.exports این دو تابع رو درون یک شئ {} خروجی گرفتیم. حالا میتونیم از این تابع درون فایلهای دیگه از جمله app.js مورد استفاده قرار بدیم:
// app.js var utility = require('./utility'); console.log(utility.generateRandom()); console.log(utility.sum(2, 3));
همونطور که میبینید با استفاده از require ماژول utility رو import کردیم و درون متغیر utility قرار دادیم و در خطهای بعدی از متدهای اون استفاده کردیم.
استفاده از Moduleها در ES6
روشهای مختلفی وجود داره که با استفاده از اون میتونین کدهای مورد نظرتون رو export یا import کنید. در ادامه این روشها رو بهتون توضیح میدیم.
اولین روش که خیلی شبیه به Common.js هست اینه که در انتها با استفاده از کلمه کلیدی export اون چیزایی که میخواید رو خروجی بگیرید. کد زیر رو در نظر بگیرید:
// utility.js function generateRandom() { return Math.random(); } function sum(a, b) { return a + b; } export { generateRandom, sum };
میبینید که دو تابع رو خروجی گرفتیم. حالا میتونیم درون فایلهای دیگه از جمله app.js اونا رو import کنیم. import کردن ماژولها در ES6 با CommonJS فرق داره و دیگه از require استفاده نمیشه. کد زیر رو ببینید:
// app.js import { generateRandom, sum } from './utility'; console.log(generateRandom()); console.log(sum(2, 3));
میبینید که همون اسم توابع رو درون {} قرار دادیم و با استفاده از from مشخص کردیم که میخوایم این موارد رو از کدام ماژول import کنیم. در خطوط بعدی نیز از این دو تابع import شده استفاده کردیم.
شما میتونین چه در هنگام import و چه در هنگام export یک نام جایگزین برای تابع یا متغیر و .... در نظر بگیرید.
مشخص کردن نام جایگزین برای تابع در زمان export
فرض کنید میخوایم بجای نام generateRandom که طولانی هست، از نام R استفاده کنیم. برای اینکار از کلمه کلیدی as استفاده میشه. کد رو ببینید:
// utility.js function generateRandom() { return Math.random(); } function sum(a, b) { return a + b; } export { generateRandom as R, sum };
خب حالا در فایل app.js نیز باید بجای generateRandom از R استفاده کنیم چون دیگه generateRandom رو نمیشناسه و اون رو بنام R میشناسه. کد بصورت زیر میشه:
// app.js import { R, sum } from './utility'; console.log(R()); console.log(sum(2, 3));
به همین سادگی. خروجی همانند گذشته خواهد بود.
مشخص کردن نام جایگزین برای تابع در زمان import
در این حالت کدهای export رو بدون تغییر قرار میدیم:
// utility.js function generateRandom() { return Math.random(); } function sum(a, b) { return a + b; } export { generateRandom, sum };
در عوض در فایل app.js و در import کردن، نام R رو برای generateRandom در نظر میگیریم:
// app.js import { generateRandom as R, sum } from './utility'; console.log(R()); console.log(sum(2, 3));
میبینید که نام اون رو به R تغییر دادیم و در 2 خط بعد از اون استفاده کردیم. اگر بجای R از generateRandom استفاده کنیم، با ارور زیر در Console برخورد میکنیم:
میبینید که میگه generateRandom تعریف نشده است. پس این نام به کلی به R تبدیل شده است. به همین راحتی.
export کردن جداگانه
همونطور که دیدید تا اینجای کار فقط با استفاده از یک دستور، مواردی که نیاز داشتیم رو export میکردیم. اما میتونیم در هر جای کد و هر چه که دلمون بخواد از export استفاده کنیم. مثلا بجای کد اولیه که دو تابع رو در یکجا استخراج کردیم، میتونستیم بصورت زیر نیز عمل کنیم:
// utility.js export function generateRandom() { return Math.random(); } export function sum(a, b) { return a + b; }
میبینید که قبل از هر تابع یک export قرار دادیم. با اینکار این دو تابع خروجی گرفته میشن و میتونین همانند گذشته اونا رو در فایلهای دیگه import کنید. شما میتونین متغیرها، توابع، کلاسها و ... رو export کنید. تعدادی نمونه رو در نظر بگیرید:
export function func() { console.log('Sample function'); } export let num = 2; export class Sample { constructor(name) { this.name = name; } getName() { console.log(this.name); } }
به همین راحتی.
مشخص کردن خروجی پیش فرض یا Default
تا اینجای کار همه موارد رو به یک صورت خروجی میگرفتیم و اونا رو درون {}، import میکردیم. ما میتونیم یکی از خروجیها رو بصورت default یا پیش فرض export کنیم. کد زیر رو در نظر بگیرید:
// utility.js export function generateRandom() { return Math.random(); } export default function sum(a, b) { return a + b; }
میبینید که تابع sum رو بصورت default خروجی گرفتیم. حالا تابع sum در زمان import کردن دیگه نیازی به {} ندارد. بصورت زیر:
// app.js import sum from './utility'; console.log(sum(2, 3));
شما میتونین هم زمان با import کردن خروجی پیش فرض، بقیه خروجیهای عادی رو نیز درون {}، import کنید. بصورت زیر:
// app.js import sum, { generateRandom } from './utility'; console.log(generateRandom()); console.log(sum(2, 3));
به همین راحتی.
import کردن کل محتوای یک ماژول
شما میتونین با استفاده از * همه چیز رو از ماژول مورد نظرتون رو به یکباره import کنید. در این حالت باید یک نام رو با استفاده از as برای اونا قرار بدین. کد زیر رو در نظر بگیرید:
// app.js import * as utility from './utility'; console.log(utility.generateRandom()); console.log(utility.sum(2, 3));
میبینید که نام utility رو برای همه اونا در نظر گرفتیم و با استفاده از عملگر . به متدهای اون دسترسی پیدا کردیم. به همین راحتی.
موفق و پیروز باشید.
یا علی
سلام خیلی ممنون از آموزش عالی
میگم یه پیشنهاد بهتر نبود سرفصلایی مث این رو جلوتر میذاشتی که آخه بعضی سرفصلا جلوتر بودن که خیلی اهمیت کمتری داشتن
هدف من پوشش دادن تمامی مطالب بود
درسته که اهمیت بیشتری داره ولی دلیل نمیشه که زودتر بیان بشه
بهرحال ممنون از پیشنهادتون
موفق باشید
خسته نباشی آقای اسفندیاری مثل همیشه عالی بود
فقط یه سوال، چطور میشه rollup , babel رو با هم ترکیب کرد سعی کردم با گرانت و پلاگین watch این دو رو ترکیب کنم که نشد تو سایت rollup هم یه توضیح مختصر در مورد ترکیب این دو نوشته بود که ازش چیزی متوجه نشدم میشه شما توضیح بدید چطور میتونم این کار رو بکنم؟
همچنین یه بحثی هم تو سایت Babel دیدم به اسم babel-polyfill که میاد علاوه بر سینتکس توابع رو هم تبدیل میکنه ایا درسته ؟ در مورد اون هم توضیح خواهید داد؟
ممنون آقای اسفندیاری که وقت گذاشتید ولی متاسفانه مقاله ای که معرفی کردین رو قبلا تست کردم و با ارور مواجه شدم و نتونستم حل کنم فکر کنم به خاطر قدیمی بودن مقاله و اپدیت های babel بوده باشه چند سایت دیگه هم سر زدم که نشد.
ولی در نهایت با استفاده کردن از پکیج concurrently و اجرای همزمان دو کامند تونستم همزمان دو پکیج رو ران کنم که با هر تغییر rollup تغییرات رو میخونه و خروجیش رو تولید میکنه و babel هم خروجی تولید شده رو به ورژن پایین تر تبدیل میکنه.
اونایی که به دردشون میخوره این پکیج برن به این صفحه : https://www.npmjs.com/package/concurrently
بازم ممنون اقای اسفندیاری
خیلی هم خوب
موفق باشید دوست عزیز
سلام
برای استفاده از Babel با Rollup میتونین از آموزش زیر استفاده کنید که برای Gulp و Grunt آموزش قرار داده است:
https://lazamar.github.io/up-and-running-with-rollup-js-in-gulp-grunt-and-native-js-api/
در مورد Polyfill:
با استفاده از Polyfill ها میتونین مرورگرهای قدیمی بیشتری رو تحت پوشش قرار بدین و مثلا کاری کنید که IE8 هم از بیشتر موارد پشتیبانی بکنه. مثلا همین Generator ها اصلا در ES3 تعریف نشده اند، اما Polyfill میاد و اونا رو جوری شبیه سازی میکنه که مرورگرها اون رو متوجه بشن و همانند Generator ها با اون کار کنند. شما نیازی نیست که بدونین چطوری این کار انجام میشه چون Babel در پشت صحنه همه کارها رو انجام میده و شما فقط باید فایل Compile شده رو لود کنید.
موفق باشید