هناك الكثير من الأدوات الرائعة لإنشاء مواقع ويب جافا سكريبت قوية ذات الصفحة الواحدة هذه الأيام. في رأيي ، يتم ذلك بشكل صحيح من خلال السماح للخادم بالعمل كواجهة برمجة تطبيقات (وليس أكثر من ذلك) والسماح للعميل بمعالجة جميع مواد إنشاء HTML. المشكلة في هذا "النمط" هي قلة دعم محرك البحث. يمكنني التفكير في حلين:
http://example.com/my_path
مباشرةً ، فسيظهر الخادم نفس الشيء الذي سيظهره العميل إذا انتقلت إلى /my_path
عبر pushState.http://example.com/my_path
، فيجب أن يقدم له الخادم نسخة جافا سكريبت الثقيلة من موقع الويب. ولكن في حالة زيارة برنامج Google bot ، يجب على الخادم تزويده ببعض الحد الأدنى من HTML مع المحتوى الذي أرغب في فهرسة Google له.الحل الأول هو مزيد من المناقشة هنا . لقد كنت أعمل على موقع على شبكة الإنترنت أفعل ذلك ، وهي ليست تجربة رائعة جدًا. إنه ليس DRY وفي حالتي ، كان علي استخدام محركي قوالب مختلفين للعميل والخادم.
أعتقد أنني رأيت الحل الثاني لبعض المواقع الإلكترونية الجيدة لـ ol. تعجبني هذه الطريقة أكثر من الطريقة الأولى ، وباستخدام الأداة المناسبة على الخادم ، يمكن القيام بذلك دون أي ألم.
إذن ما أتساءل حقاً هو ما يلي:
في حين أن # 2 قد يكون "أسهل" بالنسبة لك كمطور ، إلا أنه يوفر الزحف إلى محرك البحث فقط. ونعم ، إذا اكتشفت Google تقديم المحتوى المختلف الخاص بك ، فقد تتم معاقبتك (لست خبيرًا في ذلك ، لكنني سمعت بحدوث ذلك).
تتمتع كل من مُحسنات محركات البحث (SEO) وإمكانية الوصول (ليس فقط للأشخاص ذوي الإعاقة ، ولكن إمكانية الوصول عبر الأجهزة المحمولة وأجهزة الشاشات التي تعمل باللمس وغيرها من الأنظمة الأساسية غير المعتمدة للحوسبة/الإنترنت) بفلسفة أساسية متشابهة: ترميز غني بشكل كبير "يمكن الوصول إليه" (أي يمكن يمكن الوصول إليها أو عرضها أو قراءتها أو معالجتها أو استخدامها بطريقة أخرى) لجميع هذه المتصفحات المختلفة. يجب أن يكون كل من قارئ الشاشة ، أو متتبع ارتباطات محرك بحث أو مستخدمًا به JavaScript ممكناً ، قادرًا على استخدام/فهرسة/فهم الوظائف الأساسية لموقعك دون مشكلة.
pushState
لا يضيف إلى هذا العبء ، في تجربتي. إنه يجلب فقط ما اعتاد أن يكون فكرة لاحقة و "إذا كان لدينا وقت" في طليعة تطوير الويب.
ما تصفه في الخيار رقم 1 هو عادةً أفضل طريقة للذهاب - ولكن ، مثل مشكلات الوصول وكبار المسئولين الاقتصاديين الأخرى ، فإن القيام بذلك باستخدام pushState
في تطبيق جافا سكريبت الثقيل يتطلب تخطيطًا مقدمًا أو سيصبح عبئًا كبيرًا. يجب إدخاله في بنية التطبيق والتطبيق من البداية - التعديل التحديثي مؤلم وسيؤدي إلى تكرار أكثر مما هو ضروري.
لقد كنت أعمل مع pushState
و SEO مؤخرًا على تطبيقين مختلفين ، ووجدت أن ما أعتقد أنه طريقة جيدة. يتبع العنصر رقم 1 الخاص بك بشكل أساسي ، ولكنه لا يكرر html/القوالب.
يمكن العثور على معظم المعلومات في هذين المنشورين بالمدونة:
و
http://lostechies.com/derickbailey/2011/06/22/rendering-a-Rails-partial-as-a-jquery-template/
يتمثل جوهر ذلك في أنني أستخدم قوالب ERB أو HAML (تشغيل Ruby on Rails ، و Sinatra ، وما إلى ذلك) لتقديم جانب الخادم الخاص بي ولإنشاء قوالب جانب العميل التي يمكن لـ Backbone استخدامها ، وكذلك لمواصفات Jasmine JavaScript الخاصة بي. هذا يقلل من الازدواجية في العلامات بين جانب الخادم وجانب العميل.
من هناك ، تحتاج إلى اتخاذ بعض الخطوات الإضافية لجعل جافا سكريبت لديك يعمل مع HTML الذي يتم تقديمه بواسطة الخادم - تحسين تدريجي حقيقي ؛ أخذ العلامات الدلالية التي تم تسليمها وتحسينها باستخدام جافا سكريبت.
على سبيل المثال ، أقوم بإنشاء تطبيق لمعرض الصور باستخدام pushState
. إذا طلبت /images/1
من الخادم ، فستعرض معرض الصور بأكمله على الخادم وترسل كل HTML و CSS و JavaScript إلى متصفحك. إذا تم تعطيل جافا سكريبت ، فسوف يعمل بشكل جيد. سيطلب كل إجراء تقوم به عنوان URL مختلفًا عن الخادم وسيعرض الخادم كل الترميز لمتصفحك. إذا قمت بتمكين جافا سكريبت ، على الرغم من ذلك ، ستقوم JavaScript بالتقاط HTML المقدم بالفعل مع بعض المتغيرات التي تم إنشاؤها بواسطة الخادم وتتولى من هناك.
إليك مثال:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
بعد أن يعرض الخادم هذا ، فإن جافا سكريبت ستلتقطه (باستخدام طريقة عرض Backbone.js في هذا المثال)
FooView = Backbone.View.extend({
events: {
"change #name": "setName",
"click #say": "sayName"
},
setName: function(e){
var name = $(e.currentTarget).val();
this.model.set({name: name});
},
sayName: function(e){
e.preventDefault();
var name = this.model.get("name");
alert("Hello " + name);
},
render: function(){
// do some rendering here, for when this is just running JavaScript
}
});
$(function(){
var model = new MyModel();
var view = new FooView({
model: model,
el: $("#foo")
});
});
هذا مثال بسيط للغاية ، لكنني أعتقد أنه يكتسب أهمية كبيرة.
عندما أقوم بتثبيت العرض بعد تحميل الصفحة ، أقوم بتقديم المحتوى الموجود في النموذج الذي تم تقديمه بواسطة الخادم ، إلى مثيل العرض كـ el
للعرض. أنا لا تقديم الطلب أو وجود طريقة العرض el
، عند تحميل العرض الأول. لدي طريقة تجسيد متوفرة بعد تشغيل العرض والصفحة كلها JavaScript. هذا يتيح لي إعادة تقديم العرض لاحقًا إذا كنت بحاجة إلى ذلك.
يؤدي النقر فوق الزر "قل اسمي" مع تمكين JavaScript إلى ظهور مربع تنبيه. بدون JavaScript ، سيتم إعادة النشر إلى الخادم ويمكن للخادم تقديم الاسم إلى عنصر html في مكان ما.
تحرير
فكر في مثال أكثر تعقيدًا ، حيث لديك قائمة تحتاج إلى إرفاقها (من التعليقات أدناه)
لنفترض أن لديك قائمة بالمستخدمين في علامة <ul>
. تم تقديم هذه القائمة بواسطة الخادم عندما قدم المتصفح طلبًا ، وكانت النتيجة تبدو مثل:
<ul id="user-list">
<li data-id="1">Bob
<li data-id="2">Mary
<li data-id="3">Frank
<li data-id="4">Jane
</ul>
تحتاج الآن إلى تنفيذ هذه القائمة وإرفاق نموذج وطراز العمود الفقري بكل عنصر من عناصر <li>
. باستخدام سمة data-id
، يمكنك العثور على النموذج الذي تأتي منه كل علامة بسهولة. ستحتاج بعد ذلك إلى طريقة عرض مجموعة وعرض عنصر أذكياء بما يكفي لإرفاق نفسه بـ html.
UserListView = Backbone.View.extend({
attach: function(){
this.el = $("#user-list");
this.$("li").each(function(index){
var userEl = $(this);
var id = userEl.attr("data-id");
var user = this.collection.get(id);
new UserView({
model: user,
el: userEl
});
});
}
});
UserView = Backbone.View.extend({
initialize: function(){
this.model.bind("change:name", this.updateName, this);
},
updateName: function(model, val){
this.el.text(val);
}
});
var userData = {...};
var userList = new UserCollection(userData);
var userListView = new UserListView({collection: userList});
userListView.attach();
في هذا المثال ، سيتم تنفيذ UserListView
عبر كافة علامات <li>
وإرفاق كائن عرض مع النموذج الصحيح لكل منها. يقوم بإعداد معالج حدث لحدث تغيير اسم النموذج وتحديث النص المعروض للعنصر عند حدوث تغيير.
هذا النوع من العمليات ، لأخذ أتش تي أم أل الذي قدمه الخادم وتفعيل جافا سكريبت وتشغيله ، هو طريقة رائعة لجعل الأمور تتدفق من أجل تحسين محركات البحث (SEO) وإمكانية الوصول ودعم pushState
.
امل ان يساعد.
أعتقد أنك بحاجة إلى هذا: http://code.google.com/web/ajaxcrawling/
يمكنك أيضًا تثبيت خلفية خاصة "تعرض" صفحتك عن طريق تشغيل javascript على الخادم ، ثم تخدم ذلك في google.
اجمع بين الأمرين ولديك حل دون برمجة الأشياء مرتين. (طالما أن التطبيق الخاص بك يمكن التحكم فيه تمامًا عبر أجزاء التثبيت).
لذلك ، يبدو أن الشاغل الرئيسي هو جفاف
<a href="/someotherpage">mylink</a>
، يعيد الخادم كتابة عنوان url إلى ملف التطبيق الخاص بك ، ويقوم بتحميله في phantom.js ، ويتم إرسال html الناتج إلى bot ، وهكذا ...<a>
. في هذه الحالة ، يكون التعامل مع 404 أسهل نظرًا لأنه يمكنك ببساطة التحقق من وجود الملف الثابت باسم يحتوي على مسار url.فيما يلي بعض الأمثلة التي تستخدم phantom.js لـ seo:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
إذا كنت تستخدم Rails ، فحاول poirot . إنها جوهرة تجعل من السهل إعادة استخدام الشارب أو المقاود العميل والقوالب جانب الخادم.
قم بإنشاء ملف في طرق العرض الخاصة بك مثل _some_thingy.html.mustache
.
تقديم جانب الخادم:
<%= render :partial => 'some_thingy', object: my_model %>
ضع القالب الخاص بك للاستخدام من جانب العميل:
<%= template_include_tag 'some_thingy' %>
جانب العميل Rendre:
html = poirot.someThingy(my_model)
لاتخاذ زاوية مختلفة قليلاً ، سيكون الحل الثاني هو الحل الصحيح من حيث إمكانية الوصول ... ستوفر محتوى بديلاً للمستخدمين الذين لا يمكنهم استخدام javascript (أولئك الذين لديهم قارئات شاشة ، إلخ).
سيؤدي هذا تلقائيًا إلى إضافة فوائد مُحسّنات محرّكات البحث ، وفي رأيي ، لن يُنظر إلى Google على أنها تقنية "غير مطيع".
مثير للإعجاب. لقد كنت أبحث في جميع أنحاء عن حلول قابلة للحياة ولكن يبدو أن مشكلة كبيرة.
كنت أميل فعلاً نحو نهجك الثاني:
اسمح للخادم بتوفير موقع ويب خاص فقط لروبوتات محرك البحث. إذا قام مستخدم عادي بزيارة http://example.com/my_path يجب أن يعطيه الخادم نسخة جافا سكريبت الثقيلة من موقع الويب. ولكن في حالة زيارة برنامج Google bot ، يجب على الخادم تزويده ببعض الحد الأدنى من HTML مع المحتوى الذي أرغب في فهرسة Google له.
إليكم حل المشكلة. على الرغم من عدم تأكيد العمل ، إلا أنه قد يوفر بعض الأفكار أو الأفكار للمطورين الآخرين.
افترض أنك تستخدم إطار عمل JS يدعم وظيفة "حالة الدفع" ، وأن إطار عمل الواجهة الخلفية لديك هو Ruby on Rails. لديك موقع مدونة بسيط وتريد أن تقوم محركات البحث بفهرسة جميع صفحات مقالاتك index
و show
.
دعنا نقول أن لديك طرقك مثل هذا:
resources :articles
match "*path", "main#index"
تأكد من أن كل وحدة تحكم من جانب الخادم تعرض نفس القالب الذي يتطلبه إطار جانب العميل لتشغيله (html/css/javascript/etc). إذا لم تتم مطابقة أي من وحدات التحكم في الطلب (في هذا المثال ، لدينا فقط مجموعة من الإجراءات المناسبة لـ ArticlesController
) ، ثم فقط قم بمطابقة أي شيء آخر وقم فقط بتقديم القالب ودع إطار عمل العميل يتولى التوجيه. الفرق الوحيد بين ضرب وحدة التحكم وضرب أداة مطابقة أحرف البدل هو القدرة على تقديم محتوى بناءً على عنوان URL الذي تم طلبه للأجهزة التي تم تعطيل JavaScript.
مما أفهمه هو فكرة سيئة لتقديم محتوى غير مرئي للمتصفحات. لذلك عندما تقوم Google بفهرستها ، يذهب الأشخاص عبر Google لزيارة صفحة معينة ولا يوجد أي محتوى ، ومن المحتمل أن تتم معاقبتكم. ما يتبادر إلى الذهن هو أنك تقوم بتقديم محتوى في عقدة div
التي display: none
في CSS.
ومع ذلك ، أنا متأكد من أنه لا يهم إذا قمت بذلك ببساطة:
<div id="no-js">
<h1><%= @article.title %></h1>
<p><%= @article.description %></p>
<p><%= @article.content %></p>
</div>
ثم باستخدام JavaScript ، والذي لا يتم تشغيله عندما يفتح جهاز معطل على JavaScript الصفحة:
$("#no-js").remove() # jQuery
وبهذه الطريقة ، بالنسبة إلى Google ، ولأي شخص لديه أجهزة معطل JavaScript ، سيشاهد المحتوى الخام/الثابت. وبالتالي فإن المحتوى {هو موجود فعليًا وهو مرئي لأي شخص لديه أجهزة معطل JavaScript.
ولكن ، عندما يزور المستخدم الصفحة نفسها ويمكّن has جافا سكريبت JavaScript ، ستتم إزالة العقدة #no-js
حتى لا تشوش تطبيقك. بعد ذلك ، سيقوم إطار جانب العميل بمعالجة الطلب من خلال جهاز التوجيه الخاص به ويعرض ما يجب على المستخدم رؤيته عند تمكين JavaScript.
أعتقد أن هذا قد يكون وسيلة صالحة وسهلة الاستخدام إلى حد ما. على الرغم من أن هذا قد يعتمد على تعقيد موقع الويب الخاص بك/التطبيق.
رغم ذلك ، يرجى تصحيح لي إذا لم يكن كذلك. فقط أعتقد أنني سوف أشارك أفكاري.
استخدم NodeJS على جانب الخادم ، وتصفح رمز عميلك وقم بتوجيه uri لكل طلب http (باستثناء موارد http الثابتة) من خلال عميل جانب الخادم لتوفير أول "bootnap" (لقطة من الصفحة التي تظهر حالتها). استخدم شيءًا مثل jsdom للتعامل مع jquery dom-ops على الخادم. بعد إرجاع bootsnap ، قم بإعداد اتصال websocket. ربما يكون من الأفضل التمييز بين عميل websocket والعميل serveride عن طريق إجراء نوع من اتصال مجمّع على clientide (يمكن العميل serveride التواصل مباشرة مع الخادم). كنت أعمل على شيء مثل هذا: https://github.com/jvanveen/rnet/
استخدم قالب إغلاق Google لعرض الصفحات. يتم تجميعها إلى جافا سكريبت أو جافا ، لذلك من السهل تقديم الصفحة إما على العميل أو الخادم. في أول مواجهة مع كل عميل ، قم بتقديم html وإضافة javascript كارتباط في الرأس. سيقوم برنامج الزاحف بقراءة ملف html فقط ، لكن المتصفح سينفذ البرنامج النصي. يمكن إجراء جميع الطلبات اللاحقة من المستعرض مقابل api لتقليل حركة المرور.