ديون ألماير وباميلا فوكس، Google
يونيو 2007
ملاحظة من المحرّر: لم تعُد واجهة Google Gears API متوفرة.
- مقدمة
- التعرّف على التطبيق
- استخدام خلاصات Google Base Data API
- إضافة Google Gears إلى التطبيق
- تصحيح أخطاء تطبيق بلا إنترنت
- الخاتمة
مقدمة
من خلال الجمع بين Google Base وGoogle Gears، نوضّح كيفية إنشاء تطبيق يمكن استخدامه بلا إنترنت. بعد قراءة هذه المقالة، ستتعرّف أكثر على Google Base API، كما ستفهم كيفية استخدام Google Gears لتخزين إعدادات المستخدم المفضّلة وبياناته والوصول إليها.
التعرّف على التطبيق
لفهم هذا التطبيق، يجب أولاً أن تكون على دراية بـ Google Base، وهو عبارة عن قاعدة بيانات كبيرة للعناصر التي تغطي فئات مختلفة مثل المنتجات والمراجعات والوصفات والأحداث وغير ذلك.
يتمّ إرفاق كل عنصر بعنوان ووصف ورابط يؤدي إلى المصدر الأصلي للبيانات (في حال توفّره)، بالإضافة إلى سمات إضافية تختلف حسب نوع الفئة. تستفيد Google Base من حقيقة أنّ السلع في الفئة نفسها تتشارك مجموعة مشتركة من السمات، فمثلاً، تحتوي جميع وصفات الطعام على مكوّنات. حتى أنّ عناصر Google Base تظهر أحيانًا في نتائج البحث من بحث Google على الويب أو بحث منتجات Google.
يتيح لك تطبيقنا التجريبي، Base with Gears، تخزين وعرض عمليات البحث الشائعة التي قد تجريها على Google Base، مثل البحث عن وصفات تتضمّن "الشوكولاتة" (لذيذ) أو إعلانات شخصية تتضمّن "نزهات على الشاطئ" (رومانسي). يمكنك اعتبارها "قارئ Google Base" يتيح لك الاشتراك في عمليات البحث والاطّلاع على النتائج المعدَّلة عند إعادة فتح التطبيق، أو عندما يبحث التطبيق عن الخلاصات المعدَّلة كل 15 دقيقة.
يمكن للمطوّرين الذين يتطلّعون إلى توسيع نطاق التطبيق إضافة المزيد من الميزات، مثل تنبيه المستخدم بشكل مرئي عندما تحتوي نتائج البحث على نتائج جديدة، والسماح للمستخدم بوضع إشارة مرجعية (نجمة) على العناصر المفضّلة (بلا إنترنت أو على الإنترنت)، والسماح للمستخدم بإجراء عمليات بحث عن سمات خاصة بفئات معيّنة، مثل Google Base.
استخدام خلاصات Google Base data API
يمكن الاستعلام عن Google Base آليًا باستخدام Google Base Data API، المتوافقة مع إطار عمل Google Data API. يوفر بروتوكول Google Data API بروتوكولاً بسيطًا للقراءة والكتابة على الويب، ويتم استخدامه من قِبل العديد من منتجات Google: بيكاسا، وجداول البيانات، وBlogger، و"تقويم Google"، وNotebook، وغير ذلك.
يستند تنسيق Google Data API إلى XML وAtom Publishing Protocol، لذا فإنّ معظم تفاعلات القراءة/الكتابة تكون بتنسيق XML.
في ما يلي مثال على خلاصة Google Base استنادًا إلى Google Data API:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera
يمنحنا نوع الخلاصة snippets
الخلاصة المتاحة للجميع للعناصر. تتيح لنا السمة -/products
حصر الخلاصة بفئة المنتجات. تتيح لنا المَعلمة bq=
حصر الخلاصة بشكل أكبر، بحيث لا تعرض سوى النتائج التي تحتوي على الكلمة الرئيسية "كاميرا رقمية". إذا عرضت هذا الموجز في المتصفّح، سيظهر لك ملف XML يحتوي على عقد <entry>
مع نتائج مطابقة. يحتوي كل إدخال على عناصر المؤلف والعنوان والمحتوى والرابط النموذجية، ولكنّه يتضمّن أيضًا سمات إضافية خاصة بالفئة (مثل "السعر" للعناصر في فئة المنتجات).
بسبب القيود المفروضة على XMLHttpRequest في المتصفّح على مستوى النطاقات المختلفة، لا يُسمح لنا بقراءة خلاصة XML مباشرةً من www.google.com في رمز JavaScript البرمجي. يمكننا إعداد وكيل من جهة الخادم لقراءة ملف XML وإعادة إخراجه في موقع على النطاق نفسه الذي يستخدمه تطبيقنا، ولكننا نريد تجنُّب البرمجة من جهة الخادم تمامًا. لحسن الحظ، هناك بديل.
مثل واجهات Google Data APIs الأخرى، تتضمّن واجهة Google Base data API خيارًا لإخراج البيانات بتنسيق JSON، بالإضافة إلى تنسيق XML العادي. سيكون الناتج الخاص بالخلاصة التي رأيناها سابقًا بتنسيق JSON متاحًا على عنوان URL هذا:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera&alt=json
JSON هو تنسيق بسيط لتبادل البيانات يتيح التضمين الهرمي بالإضافة إلى أنواع البيانات المختلفة. والأهم من ذلك أنّ ناتج JSON هو رمز JavaScript أصلي، وبالتالي يمكن تحميله في صفحة الويب من خلال الإشارة إليه في علامة نص برمجي، ما يؤدي إلى تجاوز القيود المفروضة على النطاقات المتعددة.
تتيح لك واجهات Google Data APIs أيضًا تحديد إخراج "json-in-script" مع دالة رد اتصال يتم تنفيذها عند تحميل JSON. ويسهّل ذلك استخدام ناتج JSON، إذ يمكننا إضافة علامات النصوص البرمجية بشكل ديناميكي إلى الصفحة وتحديد دوال ردّ اتصال مختلفة لكل علامة.
لتحميل خلاصة JSON من Base API بشكل ديناميكي إلى الصفحة، يمكننا استخدام الدالة التالية التي تنشئ علامة نص برمجي مع عنوان URL الخاص بالخلاصة (يتم إلحاقها بقيم alt
callback
) وإلحاقها بالصفحة.
function getJSON() { var script = document.createElement('script'); var url = "http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera"; script.setAttribute('src', url + "&alt=json-in-script&callback=listResults"); script.setAttribute('type', 'text/JavaScript'); document.documentElement.firstChild.appendChild(script); }
وبالتالي، يمكن لدالة رد الاتصال listResults
الآن تكرار JSON الذي تم تمريره كالمَعلمة الوحيدة وعرض معلومات عن كل إدخال تم العثور عليه في قائمة نقطية.
function listTasks(root) { var feed = root.feed; var html = ['']; html.push('<ul>'); for (var i = 0; i < feed.entry.length; ++i) { var entry = feed.entry[i]; var title = entry.title.$t; var content = entry.content.$t; html.push('<li>', title, ' (', content, ')</li>'); } html.push('</ul>'); document.getElementById("agenda").innerHTML = html.join(""); }
إضافة Google Gears
بعد أن أصبح لدينا تطبيق يمكنه التواصل مع Google Base من خلال Google Data API، نريد أن نتيح لهذا التطبيق إمكانية العمل بلا إنترنت. وهنا يأتي دور Google Gears.
تتوفّر خيارات مختلفة للبنية عند كتابة تطبيق يمكن استخدامه بلا إنترنت. ستطرح على نفسك أسئلة حول كيفية عمل التطبيق على الإنترنت مقارنةً بحالة عدم الاتصال بالإنترنت (مثلاً، هل يعمل بالطريقة نفسها تمامًا؟ هل تم إيقاف بعض الميزات، مثل البحث؟ كيف ستتعامل مع المزامنة؟)
في حالتنا، أردنا التأكّد من أنّ المستخدمين الذين لا يتوفّر لديهم Gears على المتصفحات يمكنهم الاستمرار في استخدام التطبيق، مع منح المستخدمين الذين لديهم المكوّن الإضافي مزايا الاستخدام بلا إنترنت وواجهة مستخدم أكثر استجابة.
تبدو بنية نظامنا على النحو التالي:
- لدينا عنصر JavaScript مسؤول عن تخزين طلبات البحث وعرض النتائج المرتبطة بها.
- إذا كان لديك Google Gears مثبّتًا، ستحصل على إصدار Gears يخزّن كل شيء في قاعدة البيانات المحلية.
- إذا لم تكن مثبّتًا Google Gears، ستحصل على إصدار يخزّن طلبات البحث في ملف تعريف ارتباط ولا يخزّن النتائج الكاملة على الإطلاق (وبالتالي تكون الاستجابة أبطأ قليلاً)، لأنّ النتائج أكبر من أن يتم تخزينها في ملف تعريف ارتباط.
if (online) {}
في كل مكان. بدلاً من ذلك، يحتوي التطبيق على عملية تحقّق واحدة من Gears، ثم يتم استخدام المحوّل الصحيح.
استخدام قاعدة بيانات محلية في Gears
أحد مكونات Gears هو قاعدة بيانات SQLite المحلية المضمّنة والجاهزة للاستخدام. تتوفّر واجهة برمجة تطبيقات بسيطة لقاعدة البيانات ستكون مألوفة لك إذا كنت قد استخدمت سابقًا واجهات برمجة تطبيقات لقواعد بيانات من جهة الخادم، مثل MySQL أو Oracle.
خطوات استخدام قاعدة بيانات محلية بسيطة جدًا:
- تهيئة عناصر Google Gears
- الحصول على عنصر مصنع قاعدة بيانات وفتح قاعدة بيانات
- بدء تنفيذ طلبات SQL
لنستعرض هذه الخطوات سريعًا.
تهيئة عناصر Google Gears
يجب أن يقرأ تطبيقك محتوى /gears/samples/gears_init.js
إما مباشرةً أو عن طريق لصق الرمز في ملف JavaScript الخاص بك. بعد إعداد <script src="..../gears_init.js" type="text/JavaScript"></script>
، يمكنك الوصول إلى مساحة الاسم google.gears.
الحصول على عنصر Database Factory وفتح قاعدة بيانات
var db = google.gears.factory.create('beta.database', '1.0'); db.open('testdb');
سيمنحك هذا الاستدعاء عنصر قاعدة بيانات يتيح لك فتح مخطط قاعدة بيانات. عند فتح قواعد البيانات، يتم تحديد نطاقها من خلال قواعد سياسة المصدر نفسه، وبالتالي لن يتعارض "testdb" الخاص بك مع "testdb" الخاص بي.
بدء تنفيذ طلبات SQL
أصبحنا الآن جاهزين لإرسال طلبات SQL إلى قاعدة البيانات. عندما نرسل طلبات "اختيار"، نحصل على مجموعة نتائج يمكننا تكرارها للحصول على البيانات المطلوبة:
var rs = db.execute('select * from foo where name = ?', [ name ]);
يمكنك إجراء عمليات على مجموعة النتائج التي تم إرجاعها باستخدام الطرق التالية:
boolean | isValidRow() |
void | next() |
void | close() |
int | fieldCount() |
string | fieldName(int fieldIndex) |
variant | field(int fieldIndex) |
variant | fieldByName(string fieldname) |
لمزيد من التفاصيل، يُرجى الاطّلاع على مستندات واجهة برمجة التطبيقات الخاصة بوحدة قاعدة البيانات. (ملاحظة المحرّر: لم تعُد واجهة Google Gears API متوفرة).
استخدام GearsDB لتغليف واجهة برمجة التطبيقات المنخفضة المستوى
أردنا تلخيص بعض مهام قاعدة البيانات الشائعة وتسهيل تنفيذها. على سبيل المثال:
- أردنا أن تتوفّر طريقة جيدة لتسجيل عبارات SQL التي تم إنشاؤها أثناء تصحيح أخطاء التطبيق.
- أردنا التعامل مع الاستثناءات في مكان واحد بدلاً من الاضطرار إلى
try{}catch(){}
في كل مكان. - أردنا التعامل مع عناصر JavaScript بدلاً من مجموعات النتائج عند قراءة البيانات أو كتابتها.
للتعامل مع هذه المشاكل بطريقة عامة، أنشأنا GearsDB، وهي مكتبة مفتوحة المصدر تتضمّن عنصر Database. سنوضّح الآن كيفية استخدام GearsDB.
عملية الإعداد الأوّلية
في رمز window.onload، علينا التأكّد من أنّ جداول قاعدة البيانات التي نعتمد عليها متوفّرة. إذا كان المستخدم قد ثبّت Gears عند تنفيذ الرمز التالي، سيتم إنشاء عنصر GearsBaseContent
:
content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();
بعد ذلك، نفتح قاعدة البيانات وننشئ جداول إذا لم تكن موجودة:
db = new GearsDB('gears-base'); // db is defined as a global for reuse later! if (db) { db.run('create table if not exists BaseQueries' + ' (Phrase varchar(255), Itemtype varchar(100))'); db.run('create table if not exists BaseFeeds' + ' (id varchar(255), JSON text)'); }
في هذه المرحلة، نتأكّد من توفّر جدول لتخزين الاستعلامات والخلاصات. سيعمل الرمز new GearsDB(name)
على تضمين فتح قاعدة بيانات بالاسم المحدّد. تتضمّن الطريقة run
الطريقة execute
ذات المستوى الأدنى، ولكنها تتعامل أيضًا مع إخراج تصحيح الأخطاء إلى وحدة تحكّم واعتراض الاستثناءات.
إضافة عبارة بحث
عند تشغيل التطبيق لأول مرة، لن يكون لديك أي عمليات بحث. إذا حاولت البحث عن Nintendo Wii في المنتجات، سنحفظ عبارة البحث هذه في جدول BaseQueries.
تنفّذ نسخة Gears من الطريقة addQuery
ذلك من خلال أخذ الإدخال وحفظه باستخدام insertRow
:
var searchterm = { Phrase: phrase, Itemtype: itemtype }; db.insertRow('BaseQueries', searchterm);
تأخذ insertRow
كائن JavaScript (searchterm
) وتتولّى إدراجه في الجدول نيابةً عنك. يسمح لك أيضًا بتحديد قيود (على سبيل المثال، إدراج كتلة فريدة من نوعها لأكثر من "بوب" واحد). ومع ذلك، ستتعامل في معظم الأحيان مع هذه القيود في قاعدة البيانات نفسها.
الحصول على جميع عبارات البحث
لملء قائمة عمليات البحث السابقة، نستخدم أداة اختيار لطيفة باسم selectAll
:
GearsBaseContent.prototype.getQueries = function() { return this.db.selectAll('select * from BaseQueries'); }
سيؤدي ذلك إلى عرض مصفوفة من عناصر JavaScript التي تتطابق مع الصفوف في قاعدة البيانات (مثل [ { Phrase: 'Nintendo Wii', Itemtype: 'product' }, { ... }, ...]
).
في هذه الحالة، لا بأس من عرض القائمة الكاملة. ولكن إذا كان لديك الكثير من البيانات، من المحتمل أنّك تريد استخدام دالة ردّ الاتصال في استدعاء التحديد حتى تتمكّن من تنفيذ كل صف تم إرجاعه عند وصوله:
db.selectAll('select * from BaseQueries where Itemtype = ?', ['product'], function(row) { ... do something with this row ... });
في ما يلي بعض طرق الاختيار المفيدة الأخرى في GearsDB:
selectOne(sql, args) | إرجاع أول/أحد عناصر JavaScript المطابقة |
selectRow(table, where, args, select) | تُستخدم عادةً في الحالات البسيطة لتجاهل SQL |
selectRows(table, where, args, callback, select) | تعمل هذه الدالة مثل selectRow، ولكنها مخصّصة لنتائج متعدّدة. |
تحميل خلاصة
عندما نتلقّى خلاصة النتائج من Google Base، علينا حفظها في قاعدة البيانات:
content.setFeed({ id: id, JSON: json.toJSONString() }); ... which calls ... GearsBaseContent.prototype.setFeed = function(feed) { this.db.forceRow('BaseFeeds', feed); }
نحصل أولاً على خلاصة JSON ونعرضها كسلسلة باستخدام الطريقة toJSONString
. بعد ذلك، ننشئ الكائن feed
ونمرّره إلى الطريقة forceRow
. سيؤدي forceRow
إلى إدراج إدخال إذا لم يكن هناك إدخال حالي، أو تعديل إدخال حالي.
عرض نتائج البحث
يعرض تطبيقنا نتائج بحث معيّن في اللوحة اليمنى من الصفحة. في ما يلي كيفية استرداد الخلاصة المرتبطة بعبارة البحث:
GearsBaseContent.prototype.getFeed = function(url) { var row = this.db.selectRow('BaseFeeds', 'id = ?', [ url ]); return row.JSON; }
بعد أن أصبح لدينا JSON لصف، يمكننا eval()
للحصول على الكائنات مرة أخرى:
eval("var json = " + jsonString + ";");
يمكننا الآن البدء في إدراج محتوى من JSON في صفحتنا باستخدام innerHTML.
استخدام "متجر موارد" للوصول بلا إنترنت
بما أنّنا نحصل على المحتوى من قاعدة بيانات محلية، من المفترض أن يعمل هذا التطبيق أيضًا بلا اتصال بالإنترنت، أليس كذلك؟
حسنًا، لا. المشكلة هي أنّه لتشغيل هذا التطبيق، عليك تحميل موارد الويب الخاصة به، مثل JavaScript وCSS وHTML والصور. في الوضع الحالي، إذا اتّبع المستخدم الخطوات التالية، قد يظل التطبيق يعمل: بدء الاتصال بالإنترنت، وإجراء بعض عمليات البحث، وعدم إغلاق المتصفح، ثم الانتقال إلى وضع عدم الاتصال بالإنترنت. قد ينجح ذلك لأنّ العناصر ستظل في ذاكرة التخزين المؤقت للمتصفّح. ولكن ماذا لو لم يكن الأمر كذلك؟ نريد أن يتمكّن المستخدمون من الوصول إلى التطبيق من البداية، بعد إعادة التشغيل، وما إلى ذلك.
لإجراء ذلك، نستخدم مكوّن LocalServer ونلتقط مواردنا. عندما تحصل على مورد (مثل HTML وJavaScript المطلوبَين لتشغيل التطبيق)، سيحفظ Gears هذه العناصر وسيتلقّى أيضًا الطلبات من المتصفح لإرجاعها. سيعمل الخادم المحلي كشرطي مرور ويعرض المحتوى المحفوظ من المتجر.
نستخدم أيضًا مكوّن ResourceStore الذي يتطلّب منك إخبار النظام يدويًا بالملفات التي تريد تسجيلها. في العديد من السيناريوهات، تريد إنشاء إصدار من تطبيقك والسماح بالترقيات بطريقة معاملات. تحدّد مجموعة من الموارد معًا إصدارًا، وعند إصدار مجموعة جديدة من الموارد، ستحتاج إلى أن يحصل المستخدمون على ترقية سلسة للملفات. إذا كان هذا هو النموذج الذي تستخدمه، ستستعين بواجهة برمجة التطبيقات ManagedResourceStore.
لالتقاط مواردنا، سيفعل عنصر GearsBaseContent ما يلي:
- إعداد مجموعة من الملفات التي يجب تسجيلها
- إنشاء LocalServer
- فتح أو إنشاء ResourceStore جديد
- إرسال طلب لالتقاط الصفحات في المتجر
// Step 1 this.storeName = 'gears-base'; this.pageFiles = [ location.pathname, 'gears_base.js', '../scripts/gears_db.js', '../scripts/firebug/firebug.js', '../scripts/firebug/firebug.html', '../scripts/firebug/firebug.css', '../scripts/json_util.js', 'style.css', 'capture.gif' ]; // Step 2 try { this.localServer = google.gears.factory.create('beta.localserver', '1.0'); } catch (e) { alert('Could not create local server: ' + e.message); return; } // Step 3 this.store = this.localServer.openStore(this.storeName) || this.localServer.createStore(this.storeName); // Step 4 this.capturePageFiles(); ... which calls ... GearsBaseContent.prototype.capturePageFiles = function() { this.store.capture(this.pageFiles, function(url, success, captureId) { console.log(url + ' capture ' + (success ? 'succeeded' : 'failed')); }); }
من المهم ملاحظة أنّه يمكنك تسجيل الموارد على نطاقك فقط. واجهنا هذا القيد عندما حاولنا الوصول إلى ملف JavaScript الخاص بـ GearsDB مباشرةً من ملف "gears_db.js" الأصلي في جذع SVN. الحل بسيط بالطبع: عليك تنزيل أي موارد خارجية ووضعها ضمن نطاقك. يُرجى العِلم أنّ عمليات إعادة التوجيه 302 أو 301 لن تعمل، لأنّ LocalServer لا يقبل سوى رموز الخادم 200 (نجاح) أو 304 (لم يتم التعديل).
ولذلك آثار. إذا وضعت صورك على images.yourdomain.com، لن تتمكّن من التقاطها، لأنّ www1 وwww2 لا يمكنهما رؤية بعضهما البعض. يمكنك إعداد خوادم وكيل من جهة الخادم، ولكنّ ذلك سيؤدي إلى إبطال الغرض من تقسيم تطبيقك إلى نطاقات متعددة.
تصحيح أخطاء التطبيق الذي يعمل بلا إنترنت
يُعدّ تصحيح الأخطاء في تطبيق غير متصل بالإنترنت أكثر تعقيدًا. تتوفّر الآن سيناريوهات إضافية للاختبار:
- أنا متصل بالإنترنت والتطبيق يعمل بالكامل في ذاكرة التخزين المؤقت
- أنا متصل بالإنترنت ولكن لم أفتح التطبيق، ولا يوجد أي بيانات في ذاكرة التخزين المؤقت
- أنا غير متصل بالإنترنت ولكن يمكنني الوصول إلى التطبيق
- أنا غير متصل بالإنترنت ولم أستخدم التطبيق من قبل (هذا ليس مكانًا جيدًا!)
لتسهيل الأمر، استخدمنا النمط التالي:
- نوقف ذاكرة التخزين المؤقت في Firefox (أو المتصفح الذي تختاره) عندما نحتاج إلى التأكّد من أنّ المتصفح لا يستردّ البيانات من ذاكرة التخزين المؤقت فقط.
- نصحّح الأخطاء باستخدام Firebug (وFirebug Lite للاختبار على متصفحات أخرى)؛ ونستخدم
console.log()
في كل مكان، ونبحث عن وحدة التحكّم في حال الحاجة. - نضيف رمز JavaScript مساعدًا إلى:
- تسمح لنا بمحو قاعدة البيانات والبدء من جديد
- إزالة الملفات التي تم التقاطها، وبالتالي عندما تعيد التحميل، سيتم استرجاعها من الإنترنت مرة أخرى (مفيد عند تكرار عملية التطوير ;)
لا تظهر أداة تصحيح الأخطاء على الجانب الأيسر من الصفحة إلا إذا كان لديك Gears مثبّت. يتضمّن وسيلة شرح لتنظيف الرمز البرمجي:
GearsBaseContent.prototype.clearServer = function() { if (this.localServer.openStore(this.storeName)) { this.localServer.removeStore(this.storeName); this.store = null; } } GearsBaseContent.prototype.clearTables = function() { if (this.db) { this.db.run('delete from BaseQueries'); this.db.run('delete from BaseFeeds'); } displayQueries(); }
الخاتمة
يمكنك ملاحظة أنّ استخدام Google Gears بسيط جدًا. استخدمنا GearsDB لتسهيل استخدام مكوّن قاعدة البيانات، واستخدمنا ResourceStore اليدوي الذي كان مناسبًا تمامًا للمثال الذي قدّمناه.
إنّ الجزء الذي تقضي فيه معظم الوقت هو تحديد استراتيجية الوقت المناسب للحصول على البيانات على الإنترنت وكيفية تخزينها بلا إنترنت. من المهم تخصيص وقت لتحديد مخطط قاعدة البيانات. إذا كنت بحاجة إلى تغيير المخطط في المستقبل، عليك إدارة هذا التغيير لأنّ المستخدمين الحاليين سيستخدمون نسخة من قاعدة البيانات. وهذا يعني أنّه عليك إرسال رمز البرنامج النصي مع أي ترقية لقاعدة البيانات. من الواضح أنّ تقليل هذا الإجراء يساعدك، ويمكنك تجربة GearShift، وهي مكتبة صغيرة قد تساعدك في إدارة المراجعات.
كان بإمكاننا أيضًا استخدام ManagedResourceStore لتتبُّع ملفاتنا، مع مراعاة النتائج التالية:
- نودّ أن نكون مواطنين صالحين ونحتفظ بإصدارات ملفاتنا لنتمكّن من إجراء ترقيات نظيفة في المستقبل.
- تتوفّر ميزة في ManagedResourceStore تتيح لك ربط عنوان URL باسم مستعار بمحتوى آخر. يمكن أن يكون خيار البنية الصالح هو أن يكون gears_base.js إصدارًا غير متوافق مع Gears، وأن يتم إنشاء اسم مستعار له حتى يتمكّن Gears نفسه من تنزيل gears_base_withgears.js الذي يتضمّن جميع ميزات إتاحة المحتوى بلا إنترنت.
نأمل أن تكون قد استمتعت بتجربة تطبيق Gearing up. يُرجى الانضمام إلينا في منتدى Google Gears إذا كانت لديك أسئلة أو تطبيق تريد مشاركته.