कैसे एक एसपीए एसईओ क्रॉल करने योग्य है?


143

मैं Google के निर्देशों के आधार पर Google द्वारा SPA क्रॉल करने योग्य बनाने के लिए काम कर रहा हूं । हालांकि, कुछ सामान्य स्पष्टीकरण हैं, जिन्हें मैं वास्तविक उदाहरणों के साथ कहीं अधिक संपूर्ण चरण-दर-चरण ट्यूटोरियल नहीं पा सका। इसे समाप्त करने के बाद मैं अपना समाधान साझा करना चाहूंगा ताकि अन्य लोग भी इसका उपयोग कर सकें और संभवत: इसे और बेहतर बना सकें।
मैं नियंत्रकों के MVCसाथ उपयोग कर रहा हूं Webapi, और सर्वर साइड पर Phantomjs , और क्लाइंट साइड पर Durandalpush-state सक्षम के साथ ; मैं क्लाइंट-सर्वर डेटा इंटरैक्शन के लिए ब्रीज़ज का भी उपयोग करता हूं , जो सभी मैं दृढ़ता से सलाह देते हैं, लेकिन मैं एक सामान्य पर्याप्त स्पष्टीकरण देने की कोशिश करूंगा जो अन्य प्लेटफार्मों का उपयोग करने में लोगों की मदद करेगा।


40
"ऑफ़ टॉपिक" के विषय में - एक वेब ऐप प्रोग्रामर को एसईओ के लिए अपने ऐप को क्रॉल करने का तरीका खोजना होगा, यह वेब पर एक बुनियादी आवश्यकता है। ऐसा करना प्रति se प्रोग्रामिंग के बारे में नहीं है, लेकिन यह "व्यावहारिक, जवाबदेह समस्याओं के लिए प्रासंगिक है जो प्रोग्रामिंग पेशे के लिए अद्वितीय है" जैसा कि stackoverflow.com/help/on-topic में वर्णित है । यह कई प्रोग्रामर के लिए एक समस्या है जिसमें संपूर्ण वेब पर कोई स्पष्ट समाधान नहीं है। मैं दूसरों की मदद करने की उम्मीद कर रहा था और यहां वर्णन करने में घंटों का निवेश किया, नकारात्मक अंक प्राप्त करना निश्चित रूप से मुझे फिर से मदद करने के लिए प्रेरित नहीं करता है।
बीमिश

3
यदि प्रोग्रामिंग पर जोर दिया गया है और साँप का तेल / गुप्त सॉस एसईओ वूडू / स्पैम नहीं है, तो यह पूरी तरह से सामयिक हो सकता है। हम स्वयं के उत्तर भी पसंद करते हैं जहां वे भविष्य के पाठकों के लिए दीर्घकालिक रूप से उपयोगी होने की क्षमता रखते हैं। यह प्रश्न और उत्तर जोड़ी उन दोनों परीक्षणों को पास करती है। (पृष्ठभूमि विवरण में से कुछ बाहर सवाल बेहतर नहीं बल्कि जवाब में शुरू किया जा रहा से मांस सकता है, लेकिन है कि काफी मामूली है)
Flexo

6
+1 वोट को कम करने के लिए। भले ही क्यू / ब्लॉग पोस्ट के रूप में बेहतर होगा, सवाल डुरंडल के लिए प्रासंगिक है और जवाब अच्छी तरह से शोध किया गया है।
RainerAtSpirit

2
मैं मानता हूँ कि एसईओ आजकल हर दिन के जीवन में डेवलपर्स का एक महत्वपूर्ण हिस्सा है और निश्चित रूप से स्टैकओवरफ्लो में एक विषय के रूप में माना जाना चाहिए!
किम डी।

स्वयं पूरी प्रक्रिया को लागू करने के अलावा, आप SnapSearch snapsearch.io की कोशिश कर सकते हैं जो मूल रूप से इस समस्या को सेवा के रूप में संबोधित करता है।
CMCDragonkai

जवाबों:


121

शुरू करने से पहले, कृपया सुनिश्चित करें कि आप समझते हैं कि Google को क्या आवश्यकता है , विशेष रूप से सुंदर और बदसूरत का उपयोग URL का उपयोग। अब कार्यान्वयन को देखते हैं:

ग्राहक की ओर

क्लाइंट की तरफ आपके पास केवल एक ही html पृष्ठ होता है जो AJAX कॉल के माध्यम से गतिशील रूप से सर्वर के साथ इंटरैक्ट करता है। एसपीए जो है। aक्लाइंट साइड में सभी टैग गतिशील रूप से मेरे एप्लिकेशन में बनाए गए हैं, हम बाद में देखेंगे कि सर्वर में Google के बॉट के लिए इन लिंक को कैसे बनाया जाए। ऐसी प्रत्येक aटैग की जरूरत है एक के लिए सक्षम होने के लिए pretty URLमें hrefइतना है कि गूगल के बॉट यह क्रॉल करेगा टैग। hrefजब ग्राहक उस पर क्लिक करता है, तब भी आप उस भाग का उपयोग नहीं करना चाहते (भले ही आप चाहते हैं कि सर्वर उसे पार्स करने में सक्षम हो, हम बाद में देखेंगे), क्योंकि हम लोड करने के लिए एक नया पृष्ठ नहीं चाहते हैं। केवल AJAX कॉल करने के लिए पृष्ठ के भाग में प्रदर्शित होने के लिए कुछ डेटा प्राप्त करना और जावास्क्रिप्ट के माध्यम से URL बदलना (जैसे HTML5 pushstateया साथ का उपयोग करना Durandaljs)। तो, हम दोनों एक हैhrefonclickउपयोगकर्ता के लिए लिंक पर क्लिक करने पर भी कार्य करता है। अब, चूंकि मैं उपयोग करता push-stateहूं मुझे #URL पर कोई भी नहीं चाहिए , इसलिए एक विशिष्ट aटैग इस तरह दिखाई दे सकता है:
<a href="http://www.xyz.com/#!/category/subCategory/product111" onClick="loadProduct('category','subCategory','product111')>see product111...</a>

'श्रेणी' और 'उपश्रेणी' शायद अन्य वाक्यांश होंगे, जैसे 'संचार' और 'फोन' या 'कंप्यूटर'। और एक बिजली के उपकरणों की दुकान के लिए 'लैपटॉप'। जाहिर है कि कई अलग-अलग श्रेणियां और उप श्रेणियां होंगी। जैसा कि आप देख सकते हैं, लिंक सीधे श्रेणी, उप श्रेणी और उत्पाद के लिए है, न कि अतिरिक्त मापदंडों के रूप में एक विशिष्ट 'स्टोर' संस्करण के रूप में http://www.xyz.com/store/category/subCategory/product111। ऐसा इसलिए है क्योंकि मैं छोटे और सरल लिंक पसंद करता हूं। तात्पर्य यह है कि मैं अपने 'पृष्ठ' अर्थात '' के समान नाम वाली श्रेणी नहीं रखूंगा।
मैं AJAX ( onclickभाग) के माध्यम से डेटा को लोड करने के तरीके में नहीं जाऊंगा , इसे Google पर खोजूंगा, कई अच्छे स्पष्टीकरण हैं। यहाँ केवल एक महत्वपूर्ण बात जिसका मैं उल्लेख करना चाहता हूं वह यह है कि जब उपयोगकर्ता इस लिंक पर क्लिक करता है, तो मैं चाहता हूं कि ब्राउज़र में URL इस तरह दिखे:
http://www.xyz.com/category/subCategory/product111। और यह URL सर्वर पर नहीं भेजा जाता है! याद रखें, यह एक एसपीए है जहां ग्राहक और सर्वर के बीच सभी इंटरैक्शन AJAX के माध्यम से किए जाते हैं, कोई लिंक नहीं है! सभी 'पृष्ठ' क्लाइंट साइड पर लागू किए जाते हैं, और अलग-अलग URL सर्वर पर कॉल नहीं करते हैं (सर्वर को यह जानने की आवश्यकता है कि इन URL को कैसे संभालना है, जब वे किसी अन्य साइट से आपकी साइट पर बाहरी लिंक के रूप में उपयोग किए जाते हैं,) हम देखेंगे कि बाद में सर्वर साइड भाग पर)। अब, यह डर्न्डल द्वारा आश्चर्यजनक रूप से संभाला गया है। मैं दृढ़ता से इसकी सिफारिश करता हूं, लेकिन यदि आप अन्य तकनीकों को पसंद करते हैं तो आप इस हिस्से को भी छोड़ सकते हैं। यदि आप इसे चुनते हैं, और आप भी मेरी तरह वेब के लिए MS Visual Studio Express 2012 का उपयोग कर रहे हैं, तो आप Durandal स्टार्टर किट स्थापित कर सकते हैं , और वहाँ, shell.jsइस तरह से कुछ का उपयोग कर सकते हैं:

define(['plugins/router', 'durandal/app'], function (router, app) {
    return {
        router: router,
        activate: function () {
            router.map([
                { route: '', title: 'Store', moduleId: 'viewmodels/store', nav: true },
                { route: 'about', moduleId: 'viewmodels/about', nav: true }
            ])
                .buildNavigationModel()
                .mapUnknownRoutes(function (instruction) {
                    instruction.config.moduleId = 'viewmodels/store';
                    instruction.fragment = instruction.fragment.replace("!/", ""); // for pretty-URLs, '#' already removed because of push-state, only ! remains
                    return instruction;
                });
            return router.activate({ pushState: true });
        }
    };
});

यहाँ ध्यान देने योग्य कुछ महत्वपूर्ण बातें हैं:

  1. पहला मार्ग route:''उस URL के लिए है, जिसमें कोई अतिरिक्त डेटा नहीं है, यानी http://www.xyz.com। इस पृष्ठ में आप AJAX का उपयोग करके सामान्य डेटा लोड करते हैं। aइस पृष्ठ में वास्तव में कोई टैग नहीं हो सकता है । आप निम्नलिखित टैग जोड़ना चाहेंगे ताकि Google के बॉट को पता चले कि उसके साथ क्या करना है
    <meta name="fragment" content="!">:। यह टैग Google के बॉट को URL में बदल www.xyz.com?_escaped_fragment_=देगा, जिसे हम बाद में देखेंगे।
  2. 'के बारे में' मार्ग अन्य उदाहरणों के लिए एक लिंक है, जिसे आप अपने वेब एप्लिकेशन पर चाहते हैं।
  3. अब, मुश्किल हिस्सा यह है कि कोई 'श्रेणी' मार्ग नहीं है, और कई अलग-अलग श्रेणियां हो सकती हैं - जिनमें से कोई भी पूर्वनिर्धारित मार्ग नहीं है। यह वह जगह है जहाँ mapUnknownRoutesयह इन अज्ञात मार्गों को 'स्टोर' मार्ग पर मैप करता है और किसी भी 'को हटाता है!' URL के मामले में यह pretty URLgoogle के seach इंजन द्वारा उत्पन्न होता है। 'स्टोर' मार्ग जानकारी को 'टुकड़े' की संपत्ति में ले जाता है और डेटा प्राप्त करने, उसे प्रदर्शित करने और URL को स्थानीय रूप से बदलने के लिए AJAX कॉल करता है। मेरे आवेदन में, मैं ऐसे हर कॉल के लिए एक अलग पेज लोड नहीं करता हूं; मैं केवल उस पृष्ठ के हिस्से को बदलता हूं जहाँ यह डेटा प्रासंगिक है और स्थानीय रूप से URL भी बदलता है।
  4. ध्यान दें, pushState:trueजो ड्यूरंडल को पुश स्टेट यूआरएल का उपयोग करने का निर्देश देता है।

यह सब हम ग्राहक पक्ष में की जरूरत है। इसे हैशेड URL के साथ भी लागू किया जा सकता है (Durandal में आप इसके लिए सरल निष्कासन करते हैं pushState:true)। अधिक जटिल हिस्सा (कम से कम मेरे लिए ...) सर्वर हिस्सा था:

सर्वर साइड

मैं नियंत्रकों के MVC 4.5साथ सर्वर साइड पर उपयोग कर रहा हूं WebAPI। सर्वर को वास्तव में 3 प्रकार के URL को संभालने की आवश्यकता है: Google द्वारा उत्पन्न - दोनों prettyऔर uglyक्लाइंट के ब्राउज़र में दिखाई देने वाले एक ही प्रारूप के साथ एक 'सरल' URL। ऐसा करने के तरीके पर ध्यान दें:

सुंदर URL और 'सरल' पहले सर्वर द्वारा व्याख्या किए जाते हैं जैसे कि एक गैर-मौजूद नियंत्रक को संदर्भित करने का प्रयास करना। सर्वर कुछ ऐसा देखता है http://www.xyz.com/category/subCategory/product111और 'श्रेणी' नामक नियंत्रक की तलाश करता है। इसलिए web.configमैं निम्नलिखित लाइन को एक विशेष त्रुटि नियंत्रक से पुनर्निर्देशित करने के लिए जोड़ता हूं:

<customErrors mode="On" defaultRedirect="Error">
    <error statusCode="404" redirect="Error" />
</customErrors><br/>

अब, यह URL को कुछ इस तरह से रूपांतरित करता है http://www.xyz.com/Error?aspxerrorpath=/category/subCategory/product111:। मैं चाहता हूं कि URL को क्लाइंट के पास भेजा जाए जो AJAX के माध्यम से डेटा लोड करेगा, इसलिए यहां ट्रिक को डिफ़ॉल्ट 'इंडेक्स' नियंत्रक को कॉल करना है जैसे कि किसी भी नियंत्रक को संदर्भित नहीं करना; मैं सभी 'श्रेणी' और 'उपश्रेणी' मापदंडों से पहले URL में एक हैश जोड़कर ऐसा करता हूं ; हैशेड URL को डिफॉल्ट 'इंडेक्स' कंट्रोलर को छोड़कर किसी विशेष कंट्रोलर की आवश्यकता नहीं होती है और डेटा क्लाइंट को भेजा जाता है जो तब हैश को हटा देता है और हैश के बाद जानकारी को AJAX के माध्यम से डेटा लोड करने के लिए उपयोग करता है। यहाँ त्रुटि हैंडलर नियंत्रक कोड है:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

using System.Web.Routing;

namespace eShop.Controllers
{
    public class ErrorController : ApiController
    {
        [HttpGet, HttpPost, HttpPut, HttpDelete, HttpHead, HttpOptions, AcceptVerbs("PATCH"), AllowAnonymous]
        public HttpResponseMessage Handle404()
        {
            string [] parts = Request.RequestUri.OriginalString.Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries);
            string parameters = parts[ 1 ].Replace("aspxerrorpath=","");
            var response = Request.CreateResponse(HttpStatusCode.Redirect);
            response.Headers.Location = new Uri(parts[0].Replace("Error","") + string.Format("#{0}", parameters));
            return response;
        }
    }
}


लेकिन बदसूरत यूआरएल के बारे में क्या ? ये google के bot द्वारा बनाए गए हैं और उन्हें सादे HTML को वापस करना चाहिए जिसमें उपयोगकर्ता द्वारा देखे गए सभी डेटा शामिल हैं। इसके लिए मैं फैंटमज का इस्तेमाल करता हूं । फैंटम एक सिर रहित ब्राउज़र है जो ब्राउज़र क्लाइंट साइड पर कर रहा है - लेकिन सर्वर साइड पर। दूसरे शब्दों में, प्रेत जानता है (अन्य बातों के अलावा) एक URL के माध्यम से वेब पेज कैसे प्राप्त करें, इसमें सभी जावास्क्रिप्ट कोड चलाने के साथ-साथ (AJAX कॉल के माध्यम से डेटा प्राप्त करने सहित) पार्स करें, और आपको प्रतिबिंबित करने वाले HTML को वापस दें। डोम। यदि आप MS Visual Studio Express का उपयोग कर रहे हैं, तो आप बहुत से इस लिंक के माध्यम से प्रेत स्थापित करना चाहते हैं ।
लेकिन पहले, जब एक बदसूरत URL सर्वर पर भेजा जाता है, तो हमें उसे पकड़ना चाहिए; इसके लिए, मैंने निम्न फ़ाइल 'फ़ोल्डर_स्टार्ट' फ़ोल्डर में जोड़ा:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace eShop.App_Start
{
    public class AjaxCrawlableAttribute : ActionFilterAttribute
    {
        private const string Fragment = "_escaped_fragment_";

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.RequestContext.HttpContext.Request;

            if (request.QueryString[Fragment] != null)
            {

                var url = request.Url.ToString().Replace("?_escaped_fragment_=", "#");

                filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary { { "controller", "HtmlSnapshot" }, { "action", "returnHTML" }, { "url", url } });
            }
            return;
        }
    }
}

इसे 'FilterConfig.cs' से 'App_start' में भी कहा जाता है:

using System.Web.Mvc;
using eShop.App_Start;

namespace eShop
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new AjaxCrawlableAttribute());
        }
    }
}

जैसा कि आप देख सकते हैं, 'AjaxCrawlableAttribute' मार्ग बदसूरत URL को 'HtmlSnapshot' नामक कंट्रोलर में रूट करता है, और यहाँ यह कंट्रोलर है:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace eShop.Controllers
{
    public class HtmlSnapshotController : Controller
    {
        public ActionResult returnHTML(string url)
        {
            string appRoot = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);

            var startInfo = new ProcessStartInfo
            {
                Arguments = String.Format("{0} {1}", Path.Combine(appRoot, "seo\\createSnapshot.js"), url),
                FileName = Path.Combine(appRoot, "bin\\phantomjs.exe"),
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                RedirectStandardInput = true,
                StandardOutputEncoding = System.Text.Encoding.UTF8
            };
            var p = new Process();
            p.StartInfo = startInfo;
            p.Start();
            string output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            ViewData["result"] = output;
            return View();
        }

    }
}

संबंधित viewबहुत सरल है, कोड की सिर्फ एक पंक्ति:
@Html.Raw( ViewBag.result )
जैसा कि आप नियंत्रक में देख सकते हैं, प्रेत createSnapshot.jsमेरे द्वारा बनाए गए फ़ोल्डर के तहत एक जावास्क्रिप्ट फ़ाइल को लोड करता है जिसका नाम है seo। यहाँ यह जावास्क्रिप्ट फ़ाइल है:

var page = require('webpage').create();
var system = require('system');

var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();

page.onResourceReceived = function (response) {
    if (requestIds.indexOf(response.id) !== -1) {
        lastReceived = new Date().getTime();
        responseCount++;
        requestIds[requestIds.indexOf(response.id)] = null;
    }
};
page.onResourceRequested = function (request) {
    if (requestIds.indexOf(request.id) === -1) {
        requestIds.push(request.id);
        requestCount++;
    }
};

function checkLoaded() {
    return page.evaluate(function () {
        return document.all["compositionComplete"];
    }) != null;
}
// Open the page
page.open(system.args[1], function () { });

var checkComplete = function () {
    // We don't allow it to take longer than 5 seconds but
    // don't return until all requests are finished
    if ((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 10000 || checkLoaded()) {
        clearInterval(checkCompleteInterval);
        var result = page.content;
        //result = result.substring(0, 10000);
        console.log(result);
        //console.log(results);
        phantom.exit();
    }
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 300);

मैं पहले पेज के लिए थॉमस डेविस को धन्यवाद देना चाहता हूं जहां मुझे मूल कोड मिला :-)।
आपको यहाँ कुछ अजीब लगेगा: checkLoaded()फंक्शन पेज को तब तक फिर से लोड करता रहता है, जब तक कि फ़ंक्शन सही न हो जाए। ऐसा क्यों है? इसका कारण यह है कि मेरा विशिष्ट एसपीए सभी डेटा प्राप्त करने के लिए कई AJAX कॉल करता है और इसे अपने पेज पर DOM में रखता है, और फ़ैंटम को यह पता नहीं चल सकता है कि DOM के HTML प्रतिबिंब को वापस करने से पहले सभी कॉल कब पूरी हो चुकी हैं। एजेएएक्स कॉल के फाइनल होने के बाद मैंने यहां क्या किया <span id='compositionComplete'></span>, मैं एक जोड़ देता हूं , ताकि यदि यह टैग मौजूद हो तो मुझे पता है कि डोम पूरा हो गया है। मैं ड्यूरंडल की compositionCompleteघटना के जवाब में ऐसा करता हूं , यहां देखेंअधिक जानकारी के लिए। अगर यह 10 सेकंड के साथ नहीं होता है तो मैं हार जाता हूं (यह केवल एक सेकंड में सबसे अधिक समय लेना चाहिए)। HTML में लौटे सभी लिंक हैं जो उपयोगकर्ता ब्राउज़र में देखता है। स्क्रिप्ट ठीक से काम नहीं करेगी क्योंकि <script>HTML स्नैपशॉट में मौजूद टैग सही URL का संदर्भ नहीं देते हैं। इसे जावास्क्रिप्ट फ़ैंटम फ़ाइल में भी बदला जा सकता है, लेकिन मुझे नहीं लगता कि यह necassary है क्योंकि HTML स्नैपशॉट का उपयोग केवल aलिंक प्राप्त करने के लिए Google द्वारा किया जाता है न कि जावास्क्रिप्ट को चलाने के लिए; इन कड़ियों करना संदर्भ एक सुंदर यूआरएल, और तथ्य यह है कि अगर, यदि आप एक ब्राउज़र में एचटीएमएल स्नैपशॉट देखने की कोशिश, आप जावास्क्रिप्ट त्रुटियां मिलेंगी लेकिन सभी लिंक ठीक से काम करते हैं और एक बहुत URL इस समय के साथ एक बार फिर से सर्वर को निर्देशित करेंगे पूरी तरह से काम कर रहे पृष्ठ।
यह बात है। अब सर्वर को पता है कि कैसे सुंदर और बदसूरत दोनों यूआरएल को संभालना है, जिसमें सर्वर और क्लाइंट दोनों पर पुश-स्टेट सक्षम है। सभी बदसूरत यूआरएल को प्रेत का उपयोग करके उसी तरह से व्यवहार किया जाता है, इसलिए प्रत्येक प्रकार के कॉल के लिए एक अलग नियंत्रक बनाने की आवश्यकता नहीं है।
एक बात आप परिवर्तन करना पसंद कर सकते एक सामान्य 'श्रेणी / उपश्रेणी / उत्पाद' कॉल करने के लिए नहीं है, लेकिन एक 'दुकान' जिससे वे सभी तरह दिखाई देगा जोड़ने के लिए है: http://www.xyz.com/store/category/subCategory/product111। यह मेरे समाधान में समस्या से बचना होगा कि सभी अमान्य URL को ऐसे माना जाता है जैसे कि वे वास्तव में 'अनुक्रमणिका' नियंत्रक को कॉल करते हैं, और मुझे लगता है कि इन्हें तब संभाला जा सकता है, जबकि 'स्टोर' नियंत्रक के भीतर जो web.configमैंने दिखाया उसके अतिरिक्त नहीं ।


मुझे एक त्वरित प्रश्न है, मुझे लगता है कि ive को अब यह काम मिल गया है, लेकिन जब मैं अपनी साइट को Google को सबमिट करता हूं, और Google, साइट मैप्स आदि के लिए लिंक देता हूं, तो क्या मुझे google mysite.com/# देने की आवश्यकता है ! या सिर्फ mysite.com और google escaped_fragment में जोड़ देगा क्योंकि मेरे पास यह मेटा टैग में है?
कॉर्किन

ccorrin - मेरे ज्ञान का सबसे अच्छा करने के लिए आपको Google को कुछ भी देने की आवश्यकता नहीं है; google का बॉट आपकी साइट को ढूंढेगा और उसे सुंदर URL के लिए देखेगा (होम पेज में मेटा टैग जोड़ने के लिए मत भूलना, क्योंकि इसमें कोई URL नहीं हो सकता है)। बदसूरत URL जिसमें escaped_fragment हमेशा Google द्वारा ही जोड़ा जाता है - आपको इसे कभी भी अपने HTML के अंदर नहीं रखना चाहिए। और समर्थन के लिए धन्यवाद :-)
किरण

धन्यवाद ब्योर्न और सैंड्रा :-) मैं इस दस्तावेज़ के एक बेहतर संस्करण पर काम कर रहा हूं, जिसमें इस बात की जानकारी भी होगी कि कैसे पृष्ठों को कैश करना है ताकि प्रक्रिया को तेज किया जा सके और इसे अधिक सामान्य उपयोग में किया जा सके जहां url शामिल नहीं है नियंत्रक का नाम; जैसे ही यह तैयार होगा मैं इसे पोस्ट कर
दूंगा

यह एक महान व्याख्या है !! मैंने इसे लागू किया और अपने लोकलहोस्ट देवबॉक्स में एक आकर्षण की तरह काम करता है। समस्या तब होती है जब एज़्योर वेबसाइट्स पर तैनात किया जाता है क्योंकि साइट जम जाती है और एक समय के बाद मुझे 502 त्रुटि मिलती है। क्या आपको अज़ुरे को फ़ैंटमज को तैनात करने के बारे में कोई विचार है ?? ... धन्यवाद ( testypv.azurewebsites.net/?_escaped_fragment_=home/about )
yagopv

मुझे एज़्योर वेबसाइटों के साथ कोई अनुभव नहीं है, लेकिन मेरे दिमाग में जो बात आती है वह यह है कि पेज को पूरी तरह से लोड करने के लिए शायद जाँच प्रक्रिया कभी पूरी नहीं होती है इसलिए सर्वर बार-बार बिना किसी सफलता के पेज को फिर से लोड करने की कोशिश करता रहता है। शायद यही वह समस्या है जहाँ (भले ही इन जाँचों की कोई समय सीमा हो लेकिन ऐसा नहीं हो सकता है)? 'सच लौटा दो?' 'checkLoaded ()' में पहली पंक्ति के रूप में और देखें कि क्या इससे कोई फर्क पड़ता है।
बीमिश


4

यहाँ 14 अगस्त को लंदन में आयोजित मेरे एम्बर.जेएस प्रशिक्षण वर्ग से एक स्क्रैंकेस्ट-रिकॉर्डिंग की एक कड़ी है। यह आपके क्लाइंट-साइड एप्लिकेशन और आपके लिए सर्वर-साइड एप्लिकेशन, दोनों के लिए एक रणनीति की रूपरेखा तैयार करता है, साथ ही इन सुविधाओं को लागू करने का एक लाइव प्रदर्शन भी देता है, जो जावास्क्रिप्ट को बंद करने वाले उपयोगकर्ताओं के लिए भी आपके जावास्क्रिप्ट सिंगल-पेज-ऐप को सुंदर गिरावट प्रदान करेगा। ।

यह आपकी वेबसाइट को क्रॉल करने में सहायता के लिए PhantomJS का उपयोग करता है।

संक्षेप में, आवश्यक कदम हैं:

  • आपके द्वारा क्रॉल किए जाने वाले वेब एप्लिकेशन का एक होस्ट किया गया संस्करण है, इस साइट को आपके पास उत्पादन में मौजूद सभी डेटा की आवश्यकता है
  • अपनी वेबसाइट को लोड करने के लिए एक जावास्क्रिप्ट एप्लिकेशन (फैंटमज स्क्रिप्ट) लिखें
  • क्रॉल करने के लिए URL की सूची में index.html (या "/") जोड़ें
    • क्रॉल-सूची में जोड़ा गया पहला URL पॉप करें
    • पृष्ठ लोड करें और उसका DOM रेंडर करें
    • लोड किए गए पृष्ठ पर कोई लिंक ढूंढें जो आपकी अपनी साइट से लिंक करता हो (URL फ़िल्टरिंग)
    • इस लिंक को "क्रॉल करने योग्य" URLS की सूची में जोड़ें, अगर यह पहले से क्रॉल नहीं हुआ है
    • फ़ाइल सिस्टम पर फ़ाइल के लिए प्रदान किए गए DOM को संग्रहीत करें, लेकिन पहले सभी स्क्रिप्ट-टैग को हटा दें
    • अंत में, क्रॉल किए गए URL के साथ Sitemap.xml फ़ाइल बनाएं

एक बार जब यह कदम पूरा हो जाता है, तो यह आपके उस पृष्ठ के noscript-tag के भाग के रूप में आपके HTML के स्थैतिक-संस्करण की सेवा करने के लिए आपके बैकएंड तक होता है। यह Google और अन्य खोज इंजनों को आपकी वेबसाइट पर हर एक पृष्ठ को क्रॉल करने की अनुमति देगा, भले ही आपका ऐप मूल रूप से एकल-पृष्ठ-ऐप हो।

पूर्ण विवरण के साथ स्क्रीनकास्ट से लिंक करें:

http://www.devcasts.io/p/spas-phantomjs-and-seo/#


0

आप अपने एसपीए के लिए प्रीरेन्डर नामक सेवा के साथ अपनी स्वयं की सेवा का उपयोग या निर्माण कर सकते हैं। आप इसे उसकी वेबसाइट prerender.io और उसके github प्रोजेक्ट पर देख सकते हैं (यह PhantomJS का उपयोग करता है और यह आपके लिए आपकी वेबसाइट को प्रस्तुत करता है)।

इसके साथ शुरू करना बहुत आसान है। आपको केवल सेवा के लिए क्रॉलर को पुनर्निर्देशित करना होगा और वे प्रदान किए गए HTML प्राप्त करेंगे।


2
हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
टाइमजैब

2
तुम सही हो। मैंने अपनी टिप्पणी अपडेट कर दी है ... मुझे उम्मीद है कि अब यह अधिक सटीक होगी।
गैब्रिएलपेरलस

0

आप http://sparender.com/ का उपयोग कर सकते हैं जो सिंगल पेज एप्लिकेशन को सही तरीके से क्रॉल करने में सक्षम बनाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.