تجربه کاربری یکپارچه را در سراسر جهان باز کنید. یاد بگیرید که یک ماتریس سازگاری جاوا اسکریپت بین مرورگرها را برای برنامه های وب قوی و بدون خطا بسازید و خودکار کنید.
تسلط بر تست جاوا اسکریپت بین مرورگرها: ماتریس سازگاری خودکار
در بازار جهانی دیجیتال، برنامه وب شما ویترین فروشگاه، دفتر و نقطه اصلی تماس شما با کاربران در سراسر جهان است. یک خطای جاوا اسکریپت در یک مرورگر خاص می تواند به معنای از دست دادن فروش در برلین، یک ثبت نام ناموفق در توکیو یا یک کاربر ناامید در سائوپائولو باشد. رویای یک وب متحد، جایی که کد به طور یکسان در همه جا اجرا می شود، فقط یک رویا باقی مانده است. واقعیت یک اکوسیستم پراکنده از مرورگرها، دستگاه ها و سیستم عامل ها است. اینجاست که تست بین مرورگرها دیگر یک کار طاقت فرسا نیست و به یک الزام استراتژیک تبدیل می شود. و کلید باز کردن این استراتژی در مقیاس، ماتریس سازگاری خودکار است.
این راهنمای جامع شما را راهنمایی می کند که چرا این مفهوم برای توسعه وب مدرن بسیار مهم است، چگونه ماتریس خود را مفهوم سازی و بسازید، و کدام ابزارها می توانند این کار دلهره آور را به بخشی ساده و خودکار از چرخه توسعه شما تبدیل کنند.
چرا سازگاری بین مرورگرها هنوز در وب مدرن مهم است
یک تصور غلط رایج، به ویژه در بین توسعه دهندگان جدیدتر، این است که "جنگ های مرورگر" به پایان رسیده است و مرورگرهای مدرن و همیشه سبز تا حد زیادی وب را استاندارد کرده اند. در حالی که استانداردهایی مانند ECMAScript گام های باورنکردنی برداشته اند، تفاوت های قابل توجهی همچنان وجود دارد. نادیده گرفتن آنها یک قمار پرخطر برای هر برنامه ای با مخاطبان جهانی است.
- واگرایی موتور رندر: وب عمدتاً توسط سه موتور رندر اصلی تغذیه می شود: Blink (Chrome, Edge, Opera)، WebKit (Safari) و Gecko (Firefox). در حالی که همه آنها از استانداردهای وب پیروی می کنند، پیاده سازی ها، چرخه های انتشار و اشکالات منحصر به فردی دارند. یک ویژگی CSS که یک انیمیشن مبتنی بر جاوا اسکریپت را فعال می کند، ممکن است به طور بی عیب و نقص در Chrome کار کند، اما ممکن است در Safari با اشکال مواجه شود یا پشتیبانی نشود، که منجر به یک رابط کاربری خراب می شود.
- تفاوت های ظریف موتور جاوا اسکریپت: به طور مشابه، موتورهای جاوا اسکریپت (مانند V8 برای Blink و SpiderMonkey برای Gecko) می توانند تفاوت های عملکردی ظریف و تغییراتی در نحوه پیاده سازی جدیدترین ویژگی های ECMAScript داشته باشند. کدی که به ویژگی های پیشرفته متکی است ممکن است در دسترس نباشد یا ممکن است به طور متفاوتی در یک نسخه مرورگر کمی قدیمی تر اما هنوز رایج رفتار کند.
- غول موبایل: وب به طور فزاینده ای موبایل است. این فقط به معنای آزمایش روی یک صفحه نمایش کوچکتر نیست. این به معنای در نظر گرفتن مرورگرهای خاص تلفن همراه مانند Samsung Internet است که سهم قابل توجهی از بازار جهانی را در اختیار دارد، و اجزای WebView در برنامه های بومی در Android و iOS. این محیط ها محدودیت ها، ویژگی های عملکرد و اشکالات منحصر به فرد خود را دارند.
- تأثیر بر کاربران جهانی: سهم بازار مرورگر به طور چشمگیری در مناطق مختلف متفاوت است. در حالی که Chrome ممکن است در آمریکای شمالی تسلط داشته باشد، مرورگرهایی مانند UC Browser از لحاظ تاریخی در بازارهای سراسر آسیا محبوب بوده اند. فرض اینکه پایگاه کاربر شما ترجیحات مرورگر تیم توسعه شما را منعکس می کند، دستور العملی برای بیگانه کردن بخش قابل توجهی از مخاطبان بالقوه شما است.
- تخریب تدریجی و بهبود پیشرونده: یک اصل اصلی توسعه وب مقاوم، اطمینان از عملکرد برنامه شما حتی در صورت عدم کارکرد برخی از ویژگی های پیشرفته است. یک ماتریس سازگاری به شما کمک می کند تا این موضوع را تأیید کنید. برنامه شما همچنان باید به کاربر اجازه دهد تا یک کار اصلی را در یک مرورگر قدیمی تر انجام دهد، حتی اگر تجربه به اندازه کافی غنی نباشد.
ماتریس سازگاری چیست؟
در هسته خود، یک ماتریس سازگاری یک جدول است. این یک چارچوب سازمان یافته برای ترسیم آنچه آزمایش می کنید (ویژگی ها، جریان های کاربر، اجزا) در مقابل جایی که آن را آزمایش می کنید (مرورگر/نسخه، سیستم عامل، نوع دستگاه) است. این به سوالات اساسی هر استراتژی آزمایشی پاسخ می دهد:
- چه چیزی را آزمایش می کنیم؟ (به عنوان مثال، ورود کاربر، افزودن به سبد خرید، قابلیت جستجو)
- کجا آن را آزمایش می کنیم؟ (به عنوان مثال، Chrome 105 در macOS، Safari 16 در iOS 16، Firefox در Windows 11)
- نتیجه مورد انتظار چیست؟ (به عنوان مثال، گذر، شکست، مشکل شناخته شده)
یک ماتریس دستی ممکن است یک صفحه گسترده باشد که مهندسان QA در آن اجراهای آزمایشی خود را ردیابی می کنند. در حالی که برای پروژه های کوچک مفید است، این رویکرد کند، مستعد خطای انسانی و کاملاً ناپایدار در یک محیط مدرن CI/CD (ادغام مداوم/استقرار مداوم) است. یک ماتریس سازگاری خودکار این مفهوم را می گیرد و مستقیماً در خط لوله توسعه شما ادغام می کند. هر بار که کد جدیدی commit می شود، مجموعه ای از تست های خودکار در این شبکه از پیش تعریف شده از مرورگرها و دستگاه ها اجرا می شود و بازخورد فوری و جامع ارائه می دهد.
ایجاد ماتریس سازگاری خودکار شما: اجزای اصلی
ایجاد یک ماتریس خودکار موثر شامل یک سری تصمیمات استراتژیک است. بیایید آن را به چهار مرحله کلیدی تقسیم کنیم.
مرحله 1: تعریف دامنه خود - "چه کسی" و "چه چیزی"
شما نمی توانید همه چیز را در همه جا آزمایش کنید. اولین قدم این است که در مورد اولویت بندی چه چیزی تصمیمات مبتنی بر داده بگیرید. این مهمترین مرحله است، زیرا بازگشت سرمایه را برای کل تلاش آزمایشی شما تعریف می کند.
انتخاب مرورگرها و دستگاه های هدف:
- تجزیه و تحلیل داده های کاربر خود: منبع اصلی حقیقت شما تجزیه و تحلیل خود شما است. از ابزارهایی مانند Google Analytics، Adobe Analytics یا هر پلتفرم دیگری که در اختیار دارید برای شناسایی مرورگرهای برتر، سیستم عامل ها و دسته بندی های دستگاه مورد استفاده مخاطبان واقعی خود استفاده کنید. اگر پایگاه کاربری جهانی دارید، به تفاوت های منطقه ای توجه زیادی داشته باشید.
- مشاوره با آمار جهانی: داده های خود را با آمار جهانی از منابعی مانند StatCounter یا Can I Use تکمیل کنید. این می تواند به شما کمک کند تا روندها را تشخیص دهید و مرورگرهای محبوب را در بازارهایی که قصد ورود به آن را دارید شناسایی کنید.
- پیاده سازی یک سیستم طبقه بندی شده: یک رویکرد طبقه بندی شده برای مدیریت دامنه بسیار موثر است:
- طبقه 1: مهمترین مرورگرهای شما. اینها معمولاً آخرین نسخه های مرورگرهای اصلی (Chrome، Firefox، Safari، Edge) هستند که اکثریت قریب به اتفاق پایگاه کاربری شما را تشکیل می دهند. اینها مجموعه کامل تست های خودکار (end-to-end، integration، visual) را دریافت می کنند. خرابی در اینجا باید استقرار را مسدود کند.
- طبقه 2: مرورگرهای مهم اما کمتر رایج یا نسخه های قدیمی تر. این می تواند شامل نسخه اصلی قبلی یک مرورگر یا یک مرورگر تلفن همراه مهم مانند Samsung Internet باشد. اینها ممکن است مجموعه کوچکتری از تست های مسیر بحرانی را اجرا کنند. یک خرابی ممکن است یک تیکت با اولویت بالا ایجاد کند، اما لزوماً یک نسخه را مسدود نمی کند.
- طبقه 3: مرورگرهای کمتر رایج یا قدیمی تر. هدف در اینجا تخریب تدریجی است. ممکن است تعدادی از "تست های دود" را اجرا کنید تا اطمینان حاصل کنید که برنامه بارگیری می شود و عملکرد اصلی به طور کامل خراب نشده است.
تعریف مسیرهای حیاتی کاربر:
به جای تلاش برای آزمایش هر ویژگی، روی سفرهای حیاتی کاربر که بیشترین ارزش را ارائه می دهند تمرکز کنید. برای یک سایت تجارت الکترونیک، این موارد عبارتند از:
- ثبت نام و ورود کاربر
- جستجوی یک محصول
- مشاهده صفحه جزئیات محصول
- افزودن یک محصول به سبد خرید
- جریان کامل پرداخت
با خودکار کردن تست ها برای این جریان های اصلی، اطمینان حاصل می کنید که عملکرد حیاتی کسب و کار در سراسر ماتریس سازگاری شما دست نخورده باقی می ماند.
مرحله 2: انتخاب چارچوب اتوماسیون خود - "چگونه"
چارچوب اتوماسیون موتوری است که تست های شما را اجرا می کند. اکوسیستم مدرن جاوا اسکریپت چندین انتخاب عالی را ارائه می دهد که هر کدام فلسفه و نقاط قوت خاص خود را دارند.
-
Selenium:
استاندارد دیرینه صنعت. این یک استاندارد W3C است و تقریباً از هر مرورگر و زبان برنامه نویسی پشتیبانی می کند. بلوغ آن به این معنی است که جامعه عظیمی دارد و مستندات گسترده ای دارد. با این حال، راه اندازی آن گاهی اوقات پیچیده تر است و اگر تست های آن با دقت نوشته نشوند، ممکن است بیشتر در معرض پوسته پوسته شدن قرار گیرند.
-
Cypress:
یک چارچوب همه کاره و متمرکز بر توسعه دهندگان که محبوبیت زیادی به دست آورده است. این چارچوب در همان حلقه اجرایی برنامه شما اجرا می شود، که می تواند منجر به تست های سریعتر و قابل اطمینان تر شود. اجرا کننده تست تعاملی آن یک تقویت کننده بهره وری بزرگ است. از نظر تاریخی، محدودیت هایی در آزمایش بین منشا و چند زبانه داشت، اما نسخه های اخیر بسیاری از این موارد را برطرف کرده اند. پشتیبانی از بین مرورگرها زمانی محدود بود اما به طور قابل توجهی گسترش یافته است.
-
Playwright:
Playwright که توسط مایکروسافت توسعه یافته است، یک رقیب مدرن و قدرتمند است. این چارچوب پشتیبانی عالی و درجه یک را برای هر سه موتور رندر اصلی (Chromium، Firefox، WebKit) ارائه می دهد، و آن را به یک انتخاب فوق العاده برای یک ماتریس بین مرورگر تبدیل می کند. این چارچوب دارای یک API قدرتمند با ویژگی هایی مانند auto-waits، رهگیری شبکه و اجرای موازی داخلی است که به نوشتن تست های قوی و غیر پوسته پوسته شدن کمک می کند.
توصیه: برای تیم هایی که امروز یک ابتکار جدید تست بین مرورگرها را شروع می کنند، Playwright اغلب به دلیل معماری عالی بین موتور و مجموعه ویژگی های مدرن، قوی ترین انتخاب است. Cypress یک گزینه فوق العاده برای تیم هایی است که تجربه توسعه دهنده را در اولویت قرار می دهند، به خصوص برای تست اجزا و end-to-end در یک دامنه واحد. Selenium همچنان یک انتخاب قوی برای شرکت های بزرگ با نیازهای پیچیده یا الزامات چند زبانه باقی می ماند.
مرحله 3: انتخاب محیط اجرای خود - "کجا"
پس از اینکه تست ها و چارچوب خود را داشتید، به مکانی برای اجرای آنها نیاز دارید. اینجاست که ماتریس واقعاً زنده می شود.
- اجرای محلی: اجرای تست ها روی دستگاه خود در طول توسعه ضروری است. این سریع است و بازخورد فوری ارائه می دهد. با این حال، این یک راه حل مقیاس پذیر برای یک ماتریس سازگاری کامل نیست. شما نمی توانید هر ترکیب OS و نسخه مرورگر را به صورت محلی نصب کنید.
- شبکه خود میزبانی شده (به عنوان مثال، Selenium Grid): این شامل راه اندازی و نگهداری زیرساخت خود از ماشین ها (فیزیکی یا مجازی) با مرورگرها و سیستم عامل های مختلف نصب شده است. این کنترل و امنیت کاملی را ارائه می دهد اما با سربار نگهداری بسیار بالایی همراه است. شما مسئول به روز رسانی ها، وصله ها و مقیاس پذیری می شوید.
- شبکه های مبتنی بر ابر (توصیه می شود): این رویکرد غالب برای تیم های مدرن است. خدماتی مانند BrowserStack، Sauce Labs و LambdaTest دسترسی فوری به هزاران ترکیب مرورگر، سیستم عامل و دستگاه تلفن همراه واقعی در صورت تقاضا را فراهم می کنند.
مزایای کلیدی عبارتند از:- مقیاس پذیری عظیم: صدها تست را به صورت موازی اجرا کنید، که به طور چشمگیری زمان لازم برای دریافت بازخورد را کاهش می دهد.
- تعمیر و نگهداری صفر: ارائه دهنده تمام مدیریت زیرساخت، به روز رسانی مرورگر و تهیه دستگاه را انجام می دهد.
- دستگاه های واقعی: تست را روی آیفون ها، دستگاه های Android و تبلت های واقعی انجام دهید، که برای کشف اشکالات خاص دستگاه که شبیه سازها ممکن است از دست بدهند، بسیار مهم است.
- ابزارهای اشکال زدایی: این پلتفرم ها فیلم ها، گزارش های کنسول، گزارش های شبکه و اسکرین شات ها را برای هر اجرای آزمایشی ارائه می دهند و تشخیص خرابی ها را آسان می کنند.
مرحله 4: ادغام با CI/CD - موتور اتوماسیون
مرحله نهایی و حیاتی این است که ماتریس سازگاری خود را به بخشی خودکار و نامرئی از فرآیند توسعه خود تبدیل کنید. فعال کردن دستی اجراهای آزمایشی یک استراتژی پایدار نیست. ادغام با پلتفرم CI/CD خود (مانند GitHub Actions، GitLab CI، Jenkins یا CircleCI) غیر قابل مذاکره است.
گردش کار معمولی به این صورت است:
- یک توسعه دهنده کد جدیدی را به یک مخزن ارسال می کند.
- پلتفرم CI/CD به طور خودکار یک build جدید را فعال می کند.
- به عنوان بخشی از build، کار آزمایشی آغاز می شود.
- کار آزمایشی کد را بررسی می کند، وابستگی ها را نصب می کند و سپس اجرا کننده تست را اجرا می کند.
- اجرا کننده تست به محیط اجرای انتخابی شما (به عنوان مثال، یک شبکه ابری) متصل می شود و مجموعه تست را در سراسر ماتریس از پیش تعریف شده اجرا می کند.
- نتایج به پلتفرم CI/CD گزارش می شود. خرابی در یک مرورگر طبقه 1 می تواند به طور خودکار از ادغام یا استقرار کد جلوگیری کند.
در اینجا یک مثال مفهومی از نحوه ظاهر یک مرحله در یک فایل گردش کار GitHub Actions آورده شده است:
- name: Run Playwright tests on Cloud Grid
env:
# Credentials for the cloud service
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
run: npx playwright test --config=playwright.ci.config.js
فایل پیکربندی (`playwright.ci.config.js`) حاوی تعریف ماتریس شما خواهد بود—لیست تمام مرورگرها و سیستم عامل هایی که باید در برابر آنها آزمایش شوند.
یک مثال عملی: خودکار کردن یک تست ورود با Playwright
بیایید این را ملموس تر کنیم. تصور کنید می خواهیم یک فرم ورود را آزمایش کنیم. خود اسکریپت تست بر تعامل کاربر تمرکز دارد، نه مرورگر.
اسکریپت تست (`login.spec.js`):
const { test, expect } = require('@playwright/test');
test('should allow a user to log in with valid credentials', async ({ page }) => {
await page.goto('https://myapp.com/login');
// Fill in the credentials
await page.locator('#username').fill('testuser');
await page.locator('#password').fill('securepassword123');
// Click the login button
await page.locator('button[type="submit"]').click();
// Assert that the user is redirected to the dashboard
await expect(page).toHaveURL('https://myapp.com/dashboard');
await expect(page.locator('h1')).toHaveText('Welcome, testuser!');
});
جادو در فایل پیکربندی اتفاق می افتد، جایی که ما ماتریس خود را تعریف می کنیم.
فایل پیکربندی (`playwright.config.js`):
const { defineConfig, devices } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 60 * 1000, // 60 seconds
reporter: 'html',
/* Configure projects for major browsers */
projects: [
{
name: 'chromium-desktop',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox-desktop',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit-desktop',
use: { ...devices['Desktop Safari'] },
},
{
name: 'mobile-chrome',
use: { ...devices['Pixel 5'] }, // Represents Chrome on Android
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 13'] }, // Represents Safari on iOS
},
],
});
وقتی `npx playwright test` را اجرا می کنید، Playwright به طور خودکار همان تست `login.spec.js` را پنج بار اجرا می کند، یک بار برای هر پروژه تعریف شده در آرایه `projects`. این جوهر یک ماتریس سازگاری خودکار است. اگر از یک شبکه ابری استفاده می کنید، به سادگی پیکربندی های بیشتری را برای نسخه های مختلف OS یا مرورگرهای قدیمی تر ارائه شده توسط سرویس اضافه می کنید.
تجزیه و تحلیل و گزارش نتایج: از داده ها تا عمل
اجرای تست ها تنها نیمی از نبرد است. یک ماتریس موفق نتایج واضح و قابل اجرا تولید می کند.
- داشبوردهای متمرکز: پلتفرم CI/CD و شبکه تست ابری شما باید یک داشبورد متمرکز نشان دهنده وضعیت هر اجرای آزمایشی در برابر هر پیکربندی ارائه دهد. یک شبکه از علامت های تیک سبز هدف است.
- مصنوعات غنی برای اشکال زدایی: وقتی تستی در یک مرورگر خاص (به عنوان مثال، Safari در iOS) با شکست مواجه می شود، به چیزی بیش از یک وضعیت "شکست" نیاز دارید. پلتفرم تست شما باید ضبط های ویدیویی از اجرای تست، گزارش های کنسول مرورگر، فایل های HAR شبکه و اسکرین شات ها را ارائه دهد. این زمینه برای توسعه دهندگان برای اشکال زدایی سریع مشکل بدون نیاز به تولید مجدد دستی آن ارزشمند است.
- تست رگرسیون بصری: اشکالات جاوا اسکریپت اغلب به صورت نقص های بصری ظاهر می شوند. ادغام ابزارهای تست رگرسیون بصری (مانند Applitools، Percy یا Chromatic) در ماتریس شما یک پیشرفت قدرتمند است. این ابزارها عکس های پیکسل به پیکسل از UI شما در همه مرورگرها می گیرند و هرگونه تغییر بصری ناخواسته را برجسته می کنند و اشکالات CSS و رندر را که تست های عملکردی از دست می دهند، می گیرند.
- مدیریت پوسته پوسته شدن: شما ناگزیر با تست های "پوسته پوسته" مواجه خواهید شد—تست هایی که گاهی اوقات پاس می شوند و گاهی اوقات بدون هیچ گونه تغییر کد با شکست مواجه می شوند. داشتن یک استراتژی برای شناسایی و رفع این موارد بسیار مهم است، زیرا اعتماد به مجموعه تست شما را از بین می برند. چارچوب ها و پلتفرم های مدرن ویژگی هایی مانند تلاش های مجدد خودکار را برای کمک به کاهش این مشکل ارائه می دهند.
استراتژی های پیشرفته و بهترین شیوه ها
همانطور که برنامه و تیم شما رشد می کنند، می توانید استراتژی های پیشرفته تری را برای بهینه سازی ماتریس خود اتخاذ کنید.
- موازی سازی: این موثرترین راه برای سرعت بخشیدن به مجموعه تست شما است. به جای اجرای تست ها یکی یکی، آنها را به صورت موازی اجرا کنید. شبکه های ابری برای این کار ساخته شده اند و به شما این امکان را می دهند که ده ها یا حتی صدها تست را به طور همزمان اجرا کنید و یک اجرای تست یک ساعته را فقط به چند دقیقه کاهش دهید.
- رسیدگی به تفاوت های JavaScript API و CSS:
- Polyfills: از ابزارهایی مانند Babel و core-js برای تبدیل خودکار جاوا اسکریپت مدرن به یک نحو که مرورگرهای قدیمی تر می توانند آن را درک کنند، استفاده کنید و polyfills را برای API های از دست رفته (مانند `Promise` یا `fetch`) ارائه دهید.
- تشخیص ویژگی: برای مواردی که یک ویژگی نمی تواند polyfilled شود، کد دفاعی بنویسید. قبل از استفاده از یک ویژگی، بررسی کنید که آیا وجود دارد:
if ('newApi' in window) { // use new API } else { // use fallback }. - پیشوندها و Fallback های CSS: از ابزارهایی مانند Autoprefixer برای اضافه کردن خودکار پیشوندهای فروشنده به قوانین CSS استفاده کنید و از سازگاری گسترده تری اطمینان حاصل کنید.
- انتخاب تست هوشمند: برای برنامه های بسیار بزرگ، اجرای کل مجموعه تست در هر commit می تواند کند باشد. تکنیک های پیشرفته شامل تجزیه و تحلیل تغییرات کد در یک commit و فقط اجرای تست های مربوط به قسمت های تحت تأثیر برنامه است.
نتیجه گیری: از آرزو تا اتوماسیون
در دنیای متصل جهانی، ارائه یک تجربه کاربری سازگار و با کیفیت بالا یک تجمل نیست—این یک الزام اساسی برای موفقیت است. مشکلات جاوا اسکریپت بین مرورگرها ناراحتی های جزئی نیستند. آنها اشکالات حیاتی کسب و کار هستند که می توانند به طور مستقیم بر درآمد و شهرت برند تأثیر بگذارند.
ایجاد یک ماتریس سازگاری خودکار، تست بین مرورگرها را از یک گلوگاه دستی و زمان بر به یک دارایی استراتژیک تبدیل می کند. این به عنوان یک شبکه ایمنی عمل می کند و به تیم شما این امکان را می دهد که با اطمینان ویژگی ها را نوآوری و مستقر کنند، با دانستن اینکه یک فرآیند قوی و خودکار به طور مداوم یکپارچگی برنامه را در سراسر چشم انداز متنوع مرورگرها و دستگاه هایی که کاربران شما به آن وابسته هستند، تأیید می کند.
همین امروز شروع کنید. داده های کاربر خود را تجزیه و تحلیل کنید، سفرهای حیاتی کاربر خود را تعریف کنید، یک چارچوب اتوماسیون مدرن را انتخاب کنید و از قدرت یک شبکه مبتنی بر ابر استفاده کنید. با سرمایه گذاری در یک ماتریس سازگاری خودکار، در کیفیت، قابلیت اطمینان و دامنه جهانی برنامه وب خود سرمایه گذاری می کنید.