<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مجتبی قاسم زاده تهرانی</title>
        <link>https://virgool.io/feed/@sabereen</link>
        <description>بنده خدا، عضو تیم توسعه‌ی ویراستی، نسیم رضوان و پیامرسان گپ، مربی و سرباز وظیفه.</description>
        <language>fa</language>
        <pubDate>2026-06-16 10:06:47</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/11047/avatar/AOoXz4.jpg?height=120&amp;width=120</url>
            <title>مجتبی قاسم زاده تهرانی</title>
            <link>https://virgool.io/@sabereen</link>
        </image>

                    <item>
                <title>چالش‌های ساخت اپ هیبریدی با Cordova و Capacitor</title>
                <link>https://virgool.io/@sabereen/cordova-capacitor-c1b8nusetxoy</link>
                <description>بسم الله الرحمن الرحیمهیبرید و نیتیو (Hybrid و Native)از دیرباز برنامه‌نویسان دنبال این بوده اند که برای نوشتن اپلیکیشن فقط یک کد بنویسند و در دستگاه‌ها و پلتفرم‌ها و سیستم عامل‌های مختلف همان را اجرا کنند. بعد از ظهور HTML5 در سال ۲۰۱۱ فناوری‌های وب به عنوان روشی مهم برای تولید برنامه‌های کراس‌پلتفرم مورد توجه قرار گرفتند. خود حوزه‌ی وب به شکل مستقیم به علت دسترسی‌های محدود به امکانات سیستم عامل و... کافی به نظر نمی‌رسید. از این رو از همان اوایل ابزارهایی تولید شدند که این محدودیت‌ها را از بین ببرند.پس از HTML 5 ابزارهای بسیاری برای رفع محدودیت‌های وب، و با دیدگاه استفاده از همان زبان‌های HTML و CSS و JS برای تولید اپلکیشن‌های موبایلی و دسکتاپی رونمایی شدند. در حوزه‌ی تولید اپلیکیشن‌های موبایلی ابزار PhoneGap که بعدا به Apache Cordova تغییر نام داد به وجود آمد، در حوزه‌ی دسکتاپ هم ابزار Node-Webkit که بعدا به NW.js تغییر نام پیدا کرد. مدتی بعد شرکت گیتهاب ابزار Atom-Shell را با همین هدف تولید کرد که بعدا به Electron تغییر نام پیدا کرد. این ابزارها روز به روز پیشرفت کرده‌اند و امروزه به ابزارهای مدرن دیگری همچون Tauri و Capacitor رسیده‌اند.اپلیکیشن‌هایی که به این شکل و در اصل با فناوری‌های وب تولید می‌شوند اصطلاحا اپلیکیشن‌های هیبریدی نامیده می‌شوند (Hybrid App) و در مقابل اپلیکیشن‌هایی که با زبان‌های بومی آن پلتفرم تولید می‌شوند قرار می‌گیرند (Native App).از همان ابتدا روش‌های هیبریدی به شدت مورد استقبال قرار گرفتند تا حدی که شرکت Intel نرم افزار Intel XDK را که یک IDE مخصوص تولید اپلیکیشن‌های هیبریدی بود تولید کرد و خیلی کارهای دیگر انجام شد (از فناوری CrossWalk تا سایت‌هایی مثل Cocoon.io و...) که متأسفانه هم‌اکنون تمامی این پروژه‌ها رها شده اند.از همان ابتدا اعتقاد داشتم که با روش‌های هیبریدی می‌شود نرم افزارهای خیلی خوبی تولید کرد، و رها شدن پروژه‌های خوب حوزه‌ی هیبرید خیلی برایم ناراحت‌کننده بود. شاید بتوان گفت یکی از دلایل ضعیف شدن ابزارهای هیبرید و آن شور و شوق اولیه ظهور PWAها و پروژه‌ی فوگو بود، که صد البته فناوری جذابی است و خودم مدت‌هاست از طرفداران پر و پا قرص آن هستم.من، مجتبی قاسم زاده تهرانی، تقریبا از حدود سال ۹۳ وارد حوزه‌ی وب شدم، ولی از چند سال قبلش با ابزارهای هیبریدی آشنا بودم و جالب اینجاست که علت رغبت من به برنامه‌نویسی وب نیز همین بود. از چند سال پیش از ورودم به حوزه‌ی وب که در زمینه‌ی بازی‌سازی کار می‌کردم با ابزارهای NW.js و مشتقاتی از Cordova آشنا بودم و از آن‌ها استفاده می‌کردم. بعدها اپلیکیشن حفظ‌یار و قرآن پروژکتور را با فناوری‌های وب و با استفاده از ابزار Cordova به عنوان پروژه‌ی کناره طراحی کردم.تا اینکه امسال برای یک پروژه‌ی دیگر تصمیم گرفتم به روش هیبریدی اپلیکیشن اندروید بسازم، ولی این بار با آن پروژه‌های کناره فرق می‌کرد! این بار تجربیاتی کسب کردم که دوست داشتم منتشر کنم. من برنامه‌نویس اندروید نیستم و زبان جاوا را نیز فقط در حد درس برنامه‌نویسی در دانشگاه یاد گرفته‌ام، ولی در حوزه‌ی وب تخصصم خوب است، برای همین بهترین روش برای کسی مثل من تولید اپلیکیشن هیبریدی است.برای تولید اپلیکیشن هیبرید اندرویدی سه راهکار اصلی وجود دارد:ابزار Cordovaابزار Capacitorابزار BubbleWrapکوردوا (Cordova)ابزار Cordova را شاید بتوان قدیمی‌ترین ابزار تولید اپ هیبریدی دانست که در سال ۲۰۰۹ تولید شده است.کوردوا از فناوری‌های امروزی جاوااسکریپت خیلی فاصله دارد. پلاگین‌های کوردوا همه به سبک سنتی کار می‌کنند، همه‌ی آن‌ها پس از نصب آبجکت‌هایی را به صورت Global تعریف می‌کنند که بدون نیاز به import می‌توان از آن‌ها استفاده کرد. خیلی از پلاگین‌های کوردوا تایپ‌اسکریپتی نیستند و IDE نمی‌تواند خیلی خوب توابع آن‌ها را پیشنهاد دهد. معمولاً همه‌ی توابع کوردوایی به صورت Callback کار می‌کنند و با Promise کار نمی‌کنند!یکی از مشکلات اصلی کوردوا این است که پکیج‌های اصلی ساخته‌شده روی کورودا اکثرا رها شده اند و سال‌هاست که بروزرسانی نمی‌شوند، و خیلی وقت‌ها با بروزرسانی‌های نسخه‌های اندروید و... ناسازگار و غیر قابل استفاده می‌شوند.البته ناگفته نماند که سازندگان فریم‌ورک Ionic با توسعه‌ی مجموعه پکیجی تحت عنوان awesome cordova plugins تا حد امکان این مشکل را مرتفع کردند، و روی بیشتر پلاگین‌های مهم کوردوا یک wrapper نوشته اند که هم تایپ‌اسکریپتی باشد، هم با import مورد استفاده قرار بگیرد و هم Promise برگرداند. این افراد بعدها به خاطر ساختار سنتی کوردوا و یک سری مسائل دیگر خودشان دست به تولید ابزار دیگری تحت عنوان Capacitor زده‌اند که در حال حاضر رقیب اصلی و امروزی کوردوا به حساب می‌آید.کپسیتور (Capacitor)تیم سازنده‌ی فریم‌ورک Ionic سال‌ها بر پایه‌ی Cordova فریم‌ورک خود را پیش می‌بردند، بعدها به علت کهنه بودن ساختار Cordova مجموعه پکیج‌های Cordova awesome plugins را توسعه دادند، و بعدها به این فکر افتادند که جایگزین امروزی‌تر و مناسب‌تری از آن را خودشان طراحی کنند. این شد که کپسیتور متولد شد.تفکر پشت کپسیتور این بود که ما در اصل یک برنامه‌ی وبی پیشرو (PWA) بنویسیم و سپس از همان برنامه خروجی اپ اندروید و آی‌او‌اس بگیریم و در مارکت‌ها منتشر کنیم. از این رو معمولا پلاگین‌های کپسیتور هم وب را پشتیبانی می‌کنند و هم اندروید و هم iOS را.کپسیتور ساختاری امروزی دارد، یکپارچگی خوبی با ابزارهای Build امروزی دارد. تمام پلاگین‌هایش به صورت importشدنی کار می‌کنند، پلاگین‌ها را مجبور به استفاده از تایپ‌اسکریپت می‌کند و در نتیجه تمام پلاگین‌های رسمی و غیر رسمی‌اش تایپ‌اسکریپتی هستند. علاوه بر این همه‌ی آن‌ها مبتنی بر Promise هستند و از ساختار callback در توابعش خبری نیست.کپسیتور سازگاری بسیار خوبی با کوردوا و پلاگین‌هایش دارد و بسیاری از پلاگین‌های کوردوا را می‌توان به همان صورت در کپسیتور استفاده کرد.مهمترین مشکل کپسیتور از نظر من این بود که طبق ادعای خودش فقط از Webview 60 به بالا را در اندروید پشتیبانی می‌کرد! و این اصلا خوب نبود. چون بسیاری از کاربران اندرویدهای ۵ یا ۶ نمی‌توانند درست با اپلیکیشن ما کار کنند چون معمولا وب‌ویوی قدیمی دارند و وب‌ویو هم چیزی نیست که کاربر خودش همین جوری آپدیتش کند.ابزار BubbleWrapاین ابزاری است که گوگل برای تبدیل یک سایت PWA به اپ اندروید برای انتشار در مارکت‌ها تولید کرده است. این ابزار با استفاده از فناوری Trusted Web Activity که به اختصار TWA نامیده می‌شود درون اپ ما مرورگر کروم را بدون نمایش نوار ابزار مرورگر و... باز می‌کند. امّا محدود به apiهای مرورگر می‌شود و اگر کاری را نشود با یک PWA انجام داد با این اپ هم نمی‌شود انجام داد.برای راحتی کار با BubbleWrap سایت pwabuilder.com ساخته شده است که با استفاده از آن و وارد کردن آدرس سایتتان اگر از نظر امکانات PWA مشکلی نداشته باشید، می‌تونید مستقیما خروجی apk از سایتتون بگیرید که بعدا در مارکت‌ها منتشر کنید.مشکل این ابزار این است که کاربر مقصد ما حتما باید نسخه‌ی بروزی از کروم را روی گوشی خود نصب داشته باشد، وگرنه یا از Webview عادی استفاده می‌کند که خیلی محدود است و یا مستقیم کاربر را به مرورگر گوشی هدایت می‌کند که خیلی ضایع است!کوردوا و چالش‌های پیش روبه علت عدم پشتیبانی کپسیتور و BubbleWrap از وب‌ویوهای قدیمی، Cordova را به عنوان ابزار اصلی تولید اپ هیبریدی انتخاب کردم. امّا این اول ماجرا بود و چالش‌ها تازه یکی یکی آغاز خواهد شد!در این مقاله به چالش‌های مشترک اندروید مثل نصب Android Studio و Android SDK و مسائلی مثل sign کردن خروجی اندروید نمی‌پردازم، چرا که آموزش این‌ها در خود سایت این ابزارها موجود است و در این مقاله بیشتر می‌خواهم انتقال تجربیاتی را که خودم درگیر آن بودم در اختیار شما بگذارم.چالش اول: مرورگرهای قدیمیبا یک تست ساده و نصب شبیه‌ساز اندروید ۵.۱ که حداقل نسخه‌ی اندروید مورد پشتیبانی کوردوا بود متوجه شدم نسخه‌ی وب‌ویوی آن مبتنی بر کروم ۳۷ است. این را در نظر داشته باشید که ES6 در کروم ۵۱ پیاده‌سازی‌اش در مرورگر تکمیل شد و در کروم ۶۲ قابلیت import رسما وارد کروم شد. نسخه ۳۷ خیلی قدیمی بود!تست واقعی برنامه در مرورگر قدیمی:برای این کار یک نسخه‌ی قدیمی از NW.js را دانلود کردم و از آن به عنوان یک مرورگر برای تست کروم ۳۷ استفاده کردم!شما در این لینک می‌توانید تمام نسخه‌های قدیمی NW.js را که قبلا node-webkit نام داشت ببینید و دانلود کنید. هر نسخه هم دقیقا مشخص است که مبتنی بر کدام نسخه‌ی کروم کار می‌کند، مثلا نسخه‌ی v0.10.5 به نظر مناسب می‌رسید:https://github.com/nwjs/nw.js/wiki/Downloads-of-old-versionsابزار بیلد:به شخصه Vite را دوست دارم، ولی هر بار می‌خواهم از آن استفاده کنم معمولا یک نیازمندی باعث می‌شود نتوانم، چون حتی با نصب Vite plugin legacy و با تنظیم درست browserslist خروجی کار در کروم ۳۷ (همان nw.js قدیمی) درست اجرا نمی‌شد. از این رو از Webpack خام استفاده کردم و Babel که انصافا خوب کار می‌کرد. فراموش نکنید که باید تنظیم browserslist را هم درست انجام دهید که این نسخه از کروم را پشتیبانی کند.البته خیلی از پکیج‌ها برای مرورگرهایی که تا این حد قدیمی باشند بیلد نشده اند، برای همین در تنظیمات وب‌پک برای این پکیج‌ها باید استثنا قائل شویم که Babel کد آن‌ها را نیز از داخل node_modules بخواند و با کروم ۳۷ سازگار کند!در کانفیگ وب‌پک فوق دو ماژول vueuse و vue-virtual-scroller که با مرورگرهای قدیمی ناسازگار بوده‌اند استثنا شده اند که توسط Babel قابل بیلد باشند.نکته‌ی مهم دیگر هم اینکه از این به بعد برای استفاده از هر API باید یک چشممان به caniuse.com باشد که مطمئن شویم پشتیبانی خوبی از مرورگرهای قدیمی داریم.فریم‌ورکمن به شخصه با فریم‌ورک Vue.js و Solid.js و تا حدی Svelte کار می‌کنم! فریم‌ورک‌های امروزی همچون Solid.js یا Vue 3 با مرورگرهای قدیمی ناسازگارند. پس اگر بخواهیم مرورگرهای قدیمی را پشتیبانی کنیم باید از فریم‌ورک‌های قدیمی همچون React یا Vue 2 استفاده کنیم.از طرفی Vue 2.7 قابلیت script setup را اضافه کرده است، برای همین می‌توان از این فریم‌ورک استفاده کرد با این دیدگاه که از همین ابتدا تفاوت‌های Vue 2 و Vue 3 را در نظر بگیریم که بعدها در صورت تصمیم به مهاجرت تا حد امکان کد کمتری تغییر کند.سی‌اس‌اسبا ظهور روش‌های اتمیک برای نوشتن سی‌اس‌اس مثل tailwind قصد ندارم از روش‌های سنتی استفاده کنم. ولی متأسفانه tailwind علاقه‌ی زیادی به استفاده از متغیرهای CSS دارد که در مرورگرهای قدیمی قابل استفاده نیست.برای همین از فریم‌ورک Uno.css استفاده کردم که به شدت شبیه به tailwind است، ولی با چند تا Regex ساده می‌شود کانفیگش کرد! برای همین مواردی مثل رنگ و پس‌زمینه و transform را خودم با regexهایی کانفیگ کردم که داخلشان از متغیر css استفاده نشود. مشکل بعدی این بود که uno.css ساخته‌ی یکی از اعضای اصلی تیم Vite است، برای همین خیلی با وب‌پک سازگار نیست و چالش‌هایی با آن دارد، مثل ناسازگاری با کش دائمی وب‌پک و نگذشتن کدهای تولیدی آن از PostCSS. ولی هر طور بود مجبور بودیم با آن کنار بیاییم.چالش دوم: پکیج‌های منسوخپلاگین‌های کوردوا اکثرا خیلی قدیمی هستند، اکثر آن‌ها سال‌هاست که رها شده اند. برخی کلا کار نمی‌کنند و باید forkهای بروزترشان را پیدا کرد و از آن‌ها استفاده کرد. این مسأله خیلی حاد نبود تا اینکه خواستم Target SDK برنامه را آپدیت کنم که طبق استانداردهای اندروید و گوگل‌پلی این کار لازم است.پس از ارتقا به SDK 32 اندروید پروژه از کار افتاد! می‌توانم بگویم نیمی از پلاگین‌های مورد استفاده خراب شد و مجبور شدم حذفشان کنم تا پروژه Build بشود، برخی دیگر هم جلوی بیلد را نگرفتند ولی به هر حال درست کار نمی‌کردند! حل مشکل خیلی سخت بود، مجبور شدیم دنبال forkهایی از پلاگین‌ها بگردیم که مشکل را رفع کرده‌اند، برخی را مستقیما از روی گیتهابشان نصب کردیم و برای برخی جایگزین پیدا نکردیم. این مشکل فقط مربوط به پلاگین‌های غیر رسمی نبود، حتی برخی پلاگین‌های رسمی کوردوا مثل پلاگین StatusBar با اندروید جدید ناسازگار بود و امکان تغییر رنگ متن نوار وضعیت از کار افتاده بود. یا اینکه امکان نمایش SplashScreen در وسط کار که قبلا وجود داشت دیگر کار نمی‌کرد.بعضی پکیج‌ها جلوی بیلد apk را نمی‌گرفتند، ولی در صورت اجرا برنامه کرش می‌کرد و کاربر را به بیرون پرتاب می‌کرد. برای شناسایی اینکه چه پکیجی باعث این جور مشکلات می‌شود از ابزار Flipper استفاده کردم که علت کرش برنامه‌های اندروید را می‌تواند گزارش دهد.وقتی دیدم که کوردوا تا این حد منسوخ شده است و maintain نمی‌شود فهمیدم اشتباه کردم که آن را انتخاب کردم و باید از همان اول سراغ Capacitor می‌رفتیم.پلاگین Local notification، پلاگین StatusBar و NavigationBar و تم حالت روشن و تیره از مواردی بودند که با این بروزرسانی خراب شدند. برای برخی جایگزین پیدا کردم (مثل نوتیفیکیشن و تم روشن و تیره) و برای برخی دیگر نه.مهاجرت به Capacitor و چالش‌های آنابزار کپسیتور با این دیدگاه ساخته شده است که ما در اصل یک PWA داریم و حالا می‌خواهیم یک نسخه اندروید یا iOS هم از آن داشته باشیم. پلاگین‌های آن معمولا سعی می‌کنند که حتی پلتفرم وب را نیز تا حد امکان با APIهای فوگو پوشش دهند. تیمی که پشت فریم‌ورک Ionicهستند آن را توسعه داده و نگهداری می‌کنند که تیم پویا و فعال و خوبی به نظر می‌رسند. پلاگین‌های آن معمولا خیلی قدیمی نیست. یکپارچکی راحت‌تری با لایه‌ی Native دارد و در کل از دور که نگاه می‌کنیم همه چیز گل و بلبل است!از دور که نگاه می‌کنیم تنها مشکل کپسیتور عدم پشتیبانی از مرورگرهای قدیمی است (وب‌ویوی زیر ۶۰) که نهایتا برای این افراد می‌توانیم صفحه‌ای جایگزین نشان دهیم و هدایتشان کنیم به جایی که وب‌ویوی خود را بروز کنند. بعد از آن حتی از دست چالش‌هایی که برای مرورگرهای قدیمی متحمل می‌شدیم نیز خلاص خواهیم شد.قانون پایستگی چالش‌ها می‌گوید چالش‌ها از بین نمی‌روند و از حالتی به حالت دیگر تبدیل می‌شوند ? با مهاجرت به کپسیتور از شر چالش‌های کوردوا خلاص شدم و با چالش‌های کپسیتور آشنا شدم.چالش اول: عدم پشتیبانی از وب‌ویوهای زیر ۶۰کپسیتور در تنظیمات خود آدرس یک صفحه‌ی HTML را می‌گیرد که در صورت وقوع خطا آن صفحه را باز کند. این خطا ممکن است از هر چیزی ناشی شود، ولی مهمترین علت آن می‌تواند قدیمی بودن وب‌ویوی کاربر باشد. از طرفی چون قرار نیست کپسیتور این حالت را پشتیبانی کند در این صفحه بسیار محدود هستیم و نمی‌توانیم پلاگین‌های کپسیتور را استفاده کنیم یا حتی از آنجا به سایر صفحات ارجاع دهیم.صفحه‌ای طراحی کردم مبنی بر اینکه کاربر باید وب‌ویوی خود را بروزرسانی کند تا بتواند از برنامه‌ی ما استفاده کند. ولی طبیعتا اگر منشأ خطا چیز دیگری باشد نباید چنین پیامی نشان بدهیم! پس در این صفحه user agent کاربر را چک کردم که اگر وب‌ویوی او قدیمی نباشد او را به صفحه‌ی خطای دیگری ارجاع دهیم.امّا مشکل این جا بود که کپسیتور طوری طراحی شده است که کلا امکان فرار از این صفحه را نمی‌دهد و پلاگین‌هایش نیز در این صفحه کار نمی‌کند! یعنی سازندگان کپسیتور چنین مسأله‌ی مهمی را در نظر نگرفته بودند، در اینجا مجبور شدم به کدهای جاوای کپسیتور دست ببرم و آن شرط کذایی را پیدا کنم و تغییر دهم (به جای این‌که بررسی کند که آیا در صفحه‌ی ارور هستیم، بررسی شود که آیا وب‌ویو قدیمی است یا نه، چرا که در وب‌ویوهای جدید دلیلی ندارد پلاگین‌ها را غیر فعال کنیم). من برای این‌که نمی‌خواستم کد Native اندروید بزنم به ابزارهای هیبریدی روی آورده بودم، و اینکه چنین موضوع مهمی را در نظر نگرفته بودند اصلا جالب نبود.کد را اصلاح کردم و در گیتهاب برایشان Pull request هم زدم. ولی تا قبل این‌که merge شود و نسخه‌ی بعدی کپسیتور منتشر شود چه کنیم؟برای این کار پکیج‌منیجیرهای pnpm و yarn 2 به بالا قابلیت patch کردن پکیج‌ها را دارند. در npm و yarn classic هم می‌توانیم از پکیجی تحت عنوان patch-package استفاده کنیم. با این ابزار می‌توانیم پکیج‌های داخل node_modules را سیخ بزنیم! و تغییرات انجام شده روی آن پکیج‌ها را در گیت کامیت کنیم که برای همه‌ی اعضای پروژه اعمال شود.چالش دوم: عدم پشتیبانی از Service Workerمشکل بعدی کپسیتور این بود که از سرویس‌ورکر پشتیبانی نمی‌کرد. اگر صفحه‌ی ما از طریق سرویس‌ورکر فرستاده می‌شد کپسیتور پروژه را یک پروژه‌ی وبی معمولی تشخیص می‌داد!بعد از کمی جستجو معلوم شد دلیلش این است که کپسیتور برای اینکه درست کار کند یک مقدار کد جاوااسکریپت را به صفحه تزریق می‌کند، ولی سرویس‌ورکر خودش فایل را می‌فرستد و آن را به کپسیتور نمی‌دهد که بخواهد کد مورد نظر خود را در آن تزریق کند. در کوردوا این مشکل را نداشتیم! چرا که کوردوا اصولش بر این بود که باید یک تگ اسکریپت &lt;script src=cordova.js&gt; را درون فایل HTML خود قرار دهیم. این فایل را کوردوا خود به خود درون apk می‌اندازد و پس از آن کوردوا آماده‌ی استفاده است. ولی در کپسیتور برای اینکه مثلا کار برنامه‌نویس را راحت تر کند کد مورد نظر را در صفحه تزریق می‌کند که این باعث ناسازگاری‌اش با سرویس‌ورکر شده بود!سرویس‌ورکر برایم خیلی مهم بود و نمی‌توانستم به راحتی از کنارش بگذرم! از این رو دوباره دست به تغییر کدهای جاوای کپسیتور شدم و روالی مشابه Cordova در آن پیاده کردم. در کدهای جاوای کپسیتور گشتم و جایی را که کدهای جاوااسکریپت را به صفحه تزریق می‌کرد پیدا و حذف کردم. به جای آن یک آدرس مجازی ساختم که در صورت ریکوئست زدن به آن همان کدهایی که می‌خواست تزریق شود فرستاده شود. بعد مشابه کوردوا یک تگ اسکریپت در صفحه گذاشتم و آن آدرس مجازی را به آن دادم. کار سختی بود برای کسی که به نیتیو اندروید مسلط نیست، ولی به هر حال خدا را شکر مشکل سرویس‌ورکر هم حل شد!@capacitor/android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java اعمال شده روی فایل در پچ فوق چیزی که گفتم را اعمال کرده‌ام. کپسیتور برای سازگاری با کوردوا در ریسپانس فایل cordova.js یک ریسپانس خالی می‌فرستاد که همان را با کدی که باید در صفحه تزریق می‌کرد جایگزین کردم و در صفحه تگ اسکریپت cordova.js را قرار دادم.چالش سوم: مشکل signکردن و لو دادن رمز کلید اندرویدمشکل بعدی کپسیتور در ساین کردن فایل خروجی بود! کپسیتور در صورت استفاده از flavorهای اندروید مسیر فایل خروجی apk را گم می‌کند و نمی‌تواند آن را ساین کند! برای حل این مشکل باز هم مجبور شدم کدهای خود کپسیتور را دستکاری کنم و مسیر خروجی را اصلاح کنم.بعد ساین انجام می‌شد ولی در برخی گوشی‌ها قابل نصب نبود! مقداری جستجو کردم و متوجه شدم که برای ساین apk باید از ابزار apksigner استفاده شود، ولی کپسیتور از jarsigner استفاده می‌کند که آن فقط برای فایل‌های aab است! باز هم کدهای کپسیتور را دست‌کاری کردم که از apksigner استفاده کند.در مرحله‌ی بعدی ساین انجام می‌شد و در همه‌ی گوشی‌ها هم قابل نصب و درست بود، ولی فهمیدم کپسیتور فایل تنظیمات خودش را که اتفاقا شامل رمز کلید ساین برنامه است درون خود apk قرار می‌دهد! برای حل این مشکل نباید رمز کلید ساین برنامه را به کپسیتور بدهیم و باید با استفاده از همان خط فرمان در زمان بیلد مشخصات ساین را به کپسیتور بدهیم که برنامه را ساین کند.چالش چهارم: اجرا نشدن در گوشی‌های هواویبعد از انتشار برنامه، متوجه شدیم که در گوشی‌های هواوی جدید بالا نمی‌آید! بعد از کلی بررسی نهایتا متوجه شدیم هواوی از وب‌ویوی پیش‌فرض اندروید که متعلق به گوگل است استفاده نمی‌کند و وب‌ویوی خودش را دارد. از طرفی سیستم نسخه‌بندی وب‌ویوی هواوی مشابه گوگل نیست. مثلا در حال حاضر آخرین نسخه‌ی وب‌ویوی هواوی ۱۱ است، در حالی که کپسیتور وب‌ویوهای قدیمی (زیر ۶۰) را قرار نیست پشتیبانی کند. ولی وب‌ویوی ۱۱ هواوی اصلا قدیمی نیست و این تفاوت نسخه‌بندی باید در نظر گرفته می‌شد!نهایتا این مشکل هم با دست بردن به کدهای جاوای کپسیتور رفع شد.پچ  سازگار شدن با گوشی‌های هواویحرف پایانینتیجه‌ی اخلاقی اینکه هیچگاه گول تبلیغات را نخورید. من قبل از استفاده از این ابزارها جور دیگری رویشان حساب می‌کردم، اما در این مدتی که به صورت واقعا عملیاتی از آن‌ها استفاده کردم متوجه شدم متأسفانه هنوز خیلی کار دارند. حوزه‌ی تولید اپلیکیشن‌های هیبریدی موبایلی نه تنها در کوردوا و کپسیتور که حتی در ابزارهای Nativeتری همچون ReactNative چالش‌های زیادی دارد، و اگر وارد این حوزه‌ها می‌شوید باید درگیر شدن با کدهای Native را به جان بخرید!من مشکلات و راهکارها را به طور خلاصه اشاره کردم و توضیح دادم، ولی خودم برای تشخیص این‌که اصلا این مشکلات از کجا ناشی می‌شود و یافتن این راهکار خیلی تلاش کردم، و برای پرداخت زکات چیزهایی که یاد گرفتم این‌ها را این‌جا نوشتم. ان‌شاءالله که دعا برای بنده‌ی حقیر را فراموش نکنید.والسلام علی من اتبع الهدی</description>
                <category>مجتبی قاسم زاده تهرانی</category>
                <author>مجتبی قاسم زاده تهرانی</author>
                <pubDate>Wed, 01 Feb 2023 07:59:06 +0330</pubDate>
            </item>
                    <item>
                <title>اشتراک کد بین پروژه‌ها | معرّفی Bit.dev</title>
                <link>https://virgool.io/@sabereen/intro-to-bit-lljzfbuvlbjb</link>
                <description>بسم الله الرّحمن الرّحیمسلام به همه!در مورد راهکارهای مختلف اشتراک کد بین پروژه‌های مختلف مطالعه می‌کردم. به مقاله‌ای برخورد کردم که یکی از سازندگان bit.dev نوشته بود. مقاله‌شون برام جالب بود و می‌خواستم خلاصه‌اش رو نگهداری کنم. با خودم گفتم چه جایی بهتر از ویرگول ? و تصمیم گرفتم اوّلین پست خودم رو در اینجا بنویسم.لینک مقاله‌ی اصلی برای دوستانی که میخوان اصل ماجرا رو بخونن ? https://www.smashingmagazine.com/2018/04/sharing-code-between-projects/ ضمناً دوستانی که این مطلب رو می‌خونن باید آشنایی کلی با فریم‌ورک‌هایی مثل React، Vue.js یا Angular داشته باشند.ایشون در ابتدا به چالش جدی اشتراک کد بین پروژه‌های مختلف اشاره می‌کنه و از اهمّیت موضوع میگه. مثلاً میگه حدود ۳۰٪ کدهای پروژه‌ها، کپی و پیست از روی بقیه پروژه‌هاست! یا اینکه ۵۰٪ کدهای موجود در گیتهاب کپی همدیگه است! مثلاً فقط یک تابع isString در ۱۰۰۰۰ ریپازیتوری توی گیتهاب تکرار شده (هر کس برای خودش پیاده‌سازی یا کپی کردش).حالا چند راهکار به ذهنشون رسیده که مشکل رو حل کنند.ایجاد ریپازیتوری‌های مختلف به ازای هر کامپوننتخوب این روش در ابتدا خیلی خوب به نظر میاد. ولی وقتی در عمل استفاده بشه مشکلاتش فهمیده می‌شه. مثلاً وقتی تعداد کامپوننت‌ها زیاد بشه مدیریت این همه ریپازیتوری وحشتناکه. اینکه ریپازیتوری‌ها جدای از پروژه‌ی اصلی هستند خودش یک معضله! کسی که در تیم می‌خواد کامپوننت رو ویرایش کنه باید بره ریپازیتوری رو جداگانه clone کنه، دسترسی هم داشته باشه به ریپازیتوری! (فرض کنید ۱۰۰ تا ریپازیتوری مختلف داشته باشیم و بخوایم به همه‌ی اعضای تیم هم دسترسی بدیم!!!). این قضیه سرعت توسعه رو خیلی کند میکنه. مشکل بعدی اینه که راحت نیست همه اعضای تیم بفهمن چه کامپوننت‌هایی اصلاً وجود دارن و قبلاً ساختیمشون!استفاده از Lernaابزاری وجود داره به اسم Lerna که هدفش مدیریت چند ریپازیتوری با همدیگه است. حتماً کتابخونه‌هایی مثل Angular رو دیدین که ماژول‌های مختلفش رو در ریپازیتوری‌های مختلف گذاشتن. ولی همه با هم یک چیز رو تشکیل می‌دن. به هرکدوم از این ریپازیتوری‌های مجزّا یک monorepo گفته میشه. lerna هم برای مدیریت همیناست. مثلاً شما می‌تونین چندین ریپازیتوری مختلف رو با هم در یک ساختار پوشه‌بندی به شکل زیر در lerna مدیریت کنین:my-lerna-repo/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.jsonخوب همون طور که مشخّصه خیلی از مشکلاتی که در قسمت قبل گفتیم به قوّت خودش باقیست! ولی خوب در مدیریت کمکمون می‌کنه. البته این هم مشکلات خاص خودش رو داره. مثلاً ما فقط برای اشتراک کد بین پروژه‌هامون مجبوریم کل ساختار پروژه‌مون رو طبق فرمایشات lerna پیش ببریم! البته lerna در جای خودش و برای کاربرد خودش خیلی هم خوبه! ولی اینکه فقط به خاطر اشتراک کامپوننت‌ها بیاییم از این روش استفاده کنیم چندان جالب نیست.کتابخانه‌های مشترکدر این روش میان یک ریپازیتوری مشترک میسازن و همه‌ی کامپوننت‌ها رو می‌ریزن توی همون یکی! و به عنوان یک کتابخونه‌ی مشترک بین پروژه‌ها استفاده می‌کنند.خوب این روش هم چندان جالب نیست به چند دلیل:این کتابخونه به مرور رشد می‌کنه و خیلی بزرگ می‌شه، و توی هر پروژه‌ای که استفاده بشه سربار زیادی ایجاد می‌کنه. مثل این می‌مونه که به خاطر جابجا کردن یک پاکت نامه بریم یک تریلی بیاریم! (به خاطر استفاده از ۲تا کامپوننت مجبوریم کتابخونه‌ای که ۱۰۰تا کامپوننت داره رو اضافه کنیم به پروژه).هر پروژه‌ای که کامپوننت‌ها رو لازم داشته باشه خیلی درگیر این کتابخونه می‌شه. ممکنه حتّی کدهای این کتابخونه با اون پروژه در هم بپیچه و نشه در آینده کلا این کتابخونه رو از پروژه جدا کرد!برای اینکه تک تک کامپوننت‌ها رو اعضای تیم بدونن چیه و چه جوری میشه استفاده کرد باید یه عالمه زحمت بکشیم و درست و حسابی مستندسازی‌شون کنیم.حتّی کتابخونه‌های خیلی معروف جاوااسکریپت مثل lodash آروم آروم دارن به این سمت میرن که تابع‌های مختلفشون به صورت مجزّا از طریق npm قابل استفاده باشه.استفاده از git submoduleیکی از امکانات گیت این است که یک ریپازیتوری می‌تواند زیرپوشه‌ای از یک ریپازیتوری دیگر باشد. بنابراین می‌توان از کدهای یک ریپازیتوری در ریپازیتوری دیگر استفاده کرد.به این قابلیت git submodule می‌گن.این هم آخر قصّه نبود. چرا که submodule در گیت فقط روی برنچ master کار می‌کند، و باز هم سرعت توسعه را کند می‌کند. این شد که Bit متولّد شد!بیت متولّد می‌شودسازندگان بیت چیز زیاد پیچیده‌ای نمی‌خواستند! فقط می‌خواستند کامپوننت‌ها و ماژول‌ها رو از پروژه‌ها مستقل کنند، در فضایی ابری نگه داری کنند و در هر پروژه‌ای که خواستند از اون‌ها استفاده کنند. همین ?دیدگاه سازندگان بیتدر ساخت بیت چند دستورالعمل از همون ابتدا مد نظر بود و خیلی براشون مهم بود ساخت بیت بر این اساس باشه (برای خودم جالب بود):در عین اینکه کامپوننت‌ها باید مستقل از پروژه باشند، نباید لازم باشه به ازای هر کامپوننت ریپازیتوری مجزّایی ساخته بشه یا محیط تست و build اون پیکربندی بشه.توسعه‌ی کامپوننت باید دوطرفه باشه، یعنی در هر پروژه‌ای که بودیم باید بتونیم کامپوننت‌های مختلف را همان‌جا ویرایش کنیم، و بعد باید سایر پروژه‌ها sync بشه.مدیریت و اشتراک‌گذاری کامپوننت‌ها باید ساده باشه. باید همه‌ی اعضای تیم اطّلاعات لازم هر کامپوننت رو خیلی خوشگل و گرافیکی ببینند.بیت چگونه کار می‌کند؟روند کاری بیت در سه مرحله خلاصه می‌شه:اوّل باید به بیت بگیم کدوم قسمت از کد و کامپوننت‌هامون رو می‌خواهیم اشتراک‌گذاری کنیم. بعد بیت این قسمت‌ها رو در پروژه‌های مختلفی که به اشتراک گذاشته شده ردگیری می‌کنه و تغییراتشون رو ثبت می‌کنه.بعد میتونین version این کامپوننت‌ها رو هم مشخّص کنین، بعد بیت به صورت خودکار درخت وابستگی (depenency tree) فایلی و پکیجی رو تشخیص میده و ثبت میکنه. (خیلی پیچیده شد؟ نگران نباشین. منظورشون اینه که بیت نگاه می‌کنه چه فایل‌های دیگه یا پکیج‌هایی رو درون کامپوننت خودتون import کردین و اون‌ها رو ثبت می‌کنه. همین ?)نهایتاً کامپوننت‌ها رو به فضای ابری بیت (یا حتّی روی سرور خودتون) می‌فرستید. این طوری همه‌ی اعضای تیم می‌تونن کامپوننت‌ها رو ببینند، و مثل هر پکیج دیگه‌ای با npm یا yarn نصبشون کنند.بنابراین با استفاده از بیت اصلاً لازم نیست برای اشتراک کامپوننت‌ها ریپازیتوری جدیدی بسازید! یا اینکه کدتون رو تکه تکه کنید و...البته قسمت قشنگش اینجاست که با Bit می‌تونید کامپوننت‌ها رو در پروژه‌های دیگه import کنید. و از اون جایی که بیت این کامپوننت‌ها رو در بین پروژه‌های مختلف ردگیری می‌کنه در هر پروژه‌ای که بودید و این کامپوننت رو تغییر دادین sync میشه و همه‌ی پروژه‌های دیگه‌تون با کامپوننت جدید آپدیت خواهند شد. با روند کاری سریع و توزیع‌شده‌ای که Bit داره دیگه مشکلات اذیت‌کننده‌ی مربوط به دسترسی هم نداریم، و روی هر پروژه‌ای که باشیم می‌تونیم کامپوننت‌ها رو واسه‌ی همه‌ی پروژه‌ها آپدیت کنیم.ممنون از اینکه این پست رو تا اینجا مطالعه کردین، یا اینکه فقط اسکرول کردین و اومدین ببینید آخرش چی می‌شه! امیدوارم به دردتون خورده باشه.</description>
                <category>مجتبی قاسم زاده تهرانی</category>
                <author>مجتبی قاسم زاده تهرانی</author>
                <pubDate>Sun, 03 May 2020 23:48:21 +0430</pubDate>
            </item>
            </channel>
</rss>