วิธีการรวบรวมข้อมูล SEO SPA?


143

ผมเคยทำงานเกี่ยวกับวิธีการที่จะทำให้สามารถรวบรวมข้อมูลได้สปาโดย google อยู่บนพื้นฐานของ google คำแนะนำ แม้ว่าจะมีคำอธิบายทั่วไปบางอย่างที่ฉันไม่สามารถหาได้จากทุกที่ที่มีการสอนทีละขั้นตอนอย่างละเอียดยิ่งขึ้นพร้อมตัวอย่างจริง หลังจากเสร็จสิ้นสิ่งนี้ฉันต้องการแบ่งปันวิธีแก้ไขปัญหาของฉันเพื่อให้ผู้อื่นสามารถใช้ประโยชน์ได้และอาจปรับปรุงให้ดียิ่งขึ้น
ฉันใช้MVCกับWebapiคอนโทรลเลอร์และPhantomjsที่ฝั่งเซิร์ฟเวอร์และDurandalที่ฝั่งไคลเอ็นต์พร้อมpush-stateเปิดใช้งาน ฉันยังใช้Breezejsสำหรับการโต้ตอบกับข้อมูลลูกค้า - เซิร์ฟเวอร์ซึ่งทั้งหมดนี้ฉันขอแนะนำอย่างยิ่ง แต่ฉันจะพยายามอธิบายให้มากพอที่จะช่วยผู้ใช้แพลตฟอร์มอื่น ๆ


40
เกี่ยวกับ "หัวข้อปิด" - โปรแกรมเมอร์เว็บแอปต้องค้นหาวิธีทำให้แอปของเขา / เธอสามารถรวบรวมข้อมูลสำหรับ SEO ได้นี่เป็นข้อกำหนดขั้นพื้นฐานบนเว็บ การทำเช่นนี้ไม่ได้เกี่ยวกับการเขียนโปรแกรมต่อ se แต่มันมีความเกี่ยวข้องกับเรื่องของ "การปฏิบัติปัญหาคำตอบที่เป็นเอกลักษณ์ของการเขียนโปรแกรมอาชีพ" ที่อธิบายไว้ในstackoverflow.com/help/on-topic มันเป็นปัญหาสำหรับโปรแกรมเมอร์จำนวนมากที่ไม่มีวิธีแก้ปัญหาที่ชัดเจนในเว็บทั้งหมด ฉันหวังว่าจะช่วยเหลือผู้อื่นและใช้เวลาหลายชั่วโมงในการอธิบายที่นี่การได้รับคะแนนเชิงลบแน่นอนไม่ได้กระตุ้นให้ฉันช่วยอีกครั้ง
beamish

3
หากความสำคัญกับการเขียนโปรแกรมและไม่งูน้ำมัน / ซอสลับ SEO วูดู / สแปมก็สามารถเฉพาะที่สมบูรณ์แบบ เราชอบคำตอบด้วยตนเองที่พวกเขามีศักยภาพที่จะเป็นประโยชน์ต่อผู้อ่านในอนาคตในระยะยาว คู่คำถามและคำตอบนี้ผ่านการทดสอบทั้งคู่แล้ว (รายละเอียดเบื้องหลังบางอย่างอาจทำให้คำถามดีกว่าแทนที่จะได้รับการแนะนำในคำตอบ แต่ค่อนข้างน้อย)
Flexo

6
+1 เพื่อลดคะแนนโหวต ไม่ว่า q / a จะเหมาะกว่าในการโพสต์บล็อกคำถามนี้เกี่ยวข้องกับ Durandal และคำตอบนั้นได้รับการค้นคว้าอย่างดี
RainerAtSpirit

2
ฉันยอมรับว่า SEO เป็นส่วนสำคัญในปัจจุบันของนักพัฒนาในชีวิตประจำวันและแน่นอนควรพิจารณาเป็นหัวข้อใน stackoverflow!
Kim D.

นอกเหนือจากการใช้กระบวนการทั้งหมดด้วยตัวเองคุณสามารถลองใช้ SnapSearch snapsearch.ioซึ่งแก้ไขปัญหานี้เป็นบริการ
CMCDragonkai

คำตอบ:


121

ก่อนเริ่มต้นโปรดตรวจสอบให้แน่ใจว่าคุณเข้าใจว่า Google ต้องการอะไรโดยเฉพาะการใช้URL ที่น่ารักและน่าเกลียด ตอนนี้ให้ดูการใช้งาน:

ด้านลูกค้า

ในฝั่งไคลเอ็นต์คุณมีหน้า html เดียวซึ่งโต้ตอบกับเซิร์ฟเวอร์แบบไดนามิกผ่านการโทร AJAX นั่นคือสิ่งที่สปาเป็นเรื่องเกี่ยวกับ aแท็กทั้งหมดในฝั่งไคลเอ็นต์นั้นสร้างขึ้นในแอปพลิเคชันของฉันแบบไดนามิกในภายหลังเราจะเห็นวิธีที่จะทำให้ลิงก์เหล่านี้มองเห็นบอทของ Google ในเซิร์ฟเวอร์ แต่ละaแท็กดังกล่าวจะต้องสามารถมีpretty URLในhrefแท็กเพื่อให้บอทของ Google จะรวบรวมข้อมูล คุณไม่ต้องการให้ชิ้นhrefส่วนถูกใช้เมื่อไคลเอนต์คลิกที่มัน (แม้ว่าคุณต้องการให้เซิร์ฟเวอร์แยกวิเคราะห์ได้เราจะเห็นว่าในภายหลัง) เนื่องจากเราอาจไม่ต้องการให้โหลดหน้าใหม่ เพื่อโทร AJAX เพื่อรับข้อมูลบางส่วนที่จะแสดงในส่วนของหน้าและเปลี่ยน URL ผ่านทาง javascript (เช่นใช้ HTML5 pushstateหรือด้วยDurandaljs) ดังนั้นเราจึงมีทั้งhrefคุณลักษณะสำหรับ google เช่นเดียวกับonclickที่ทำงานเมื่อผู้ใช้คลิกที่ลิงค์ ขณะนี้เนื่องจากฉันใช้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 เหล่านี้ในกรณีที่ใช้เป็นลิงก์ภายนอกจากไซต์อื่นไปยังเว็บไซต์ของคุณ เราจะเห็นในภายหลังในส่วนของเซิร์ฟเวอร์) ตอนนี้จัดการได้อย่างน่าอัศจรรย์โดย Durandal ฉันขอแนะนำอย่างยิ่ง แต่คุณสามารถข้ามส่วนนี้ได้หากคุณต้องการเทคโนโลยีอื่น ๆ หากคุณเลือกและคุณใช้ 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 URLเครื่องมือค้นหาของ Google สร้างขึ้น เส้นทาง 'store' จะรับข้อมูลในคุณสมบัติ 'fragment' และทำการโทร AJAX เพื่อรับข้อมูลแสดงและเปลี่ยน URL ในเครื่อง ในแอปพลิเคชันของฉันฉันจะไม่โหลดหน้าอื่นสำหรับการโทรทุกครั้ง ฉันเปลี่ยนเฉพาะส่วนของหน้าที่ข้อมูลนี้มีความเกี่ยวข้องและเปลี่ยน URL ในเครื่อง
  4. ขอให้สังเกตpushState:trueว่าคำสั่งใดที่ Durandal ใช้ URL สถานะการพุช

นี่คือทั้งหมดที่เราต้องการในด้านลูกค้า สามารถนำไปใช้กับ URL ที่แฮช (ใน Durandal คุณสามารถลบได้อย่างง่ายดายpushState:true) ส่วนที่ซับซ้อนมากขึ้น (อย่างน้อยสำหรับฉัน ... ) คือส่วนของเซิร์ฟเวอร์:

ฝั่งเซิร์ฟเวอร์

ฉันกำลังใช้MVC 4.5ฝั่งเซิร์ฟเวอร์กับWebAPIตัวควบคุม เซิร์ฟเวอร์ต้องการจัดการ URL 3 ประเภทจริง ๆ : URL ที่สร้างขึ้นโดย google - ทั้งprettyและuglyURL ที่ 'เรียบง่าย' ที่มีรูปแบบเดียวกับ 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;
        }
    }
}


แต่แล้วURL ที่น่าเกลียดล่ะ สิ่งเหล่านี้สร้างขึ้นโดยบอทของ google และควรส่งคืน HTML ธรรมดาที่มีข้อมูลทั้งหมดที่ผู้ใช้เห็นในเบราว์เซอร์ สำหรับเรื่องนี้ผมใช้phantomjs Phantom เป็นเบราว์เซอร์ที่ไม่มีส่วนหัวทำสิ่งที่เบราว์เซอร์กำลังทำอยู่ในฝั่งไคลเอ็นต์ - แต่อยู่ฝั่งเซิร์ฟเวอร์ กล่าวอีกนัยหนึ่ง phantom รู้ (เหนือสิ่งอื่นใด) วิธีรับหน้าเว็บผ่าน URL แยกวิเคราะห์รวมถึงการเรียกใช้รหัสจาวาสคริปต์ทั้งหมดในนั้น (รวมถึงการรับข้อมูลผ่านการโทร AJAX) และให้ HTML ที่สะท้อนกลับมาให้คุณ DOM หากคุณใช้ MS Visual Studio Express คุณหลายคนต้องการติดตั้ง phantom ผ่านลิงค์นี้
แต่ก่อนอื่นเมื่อ URL ที่น่าเกลียดถูกส่งไปยังเซิร์ฟเวอร์เราต้องจับมัน สำหรับเรื่องนี้ฉันเพิ่มลงในโฟลเดอร์ 'App_start' ไฟล์ต่อไปนี้:

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);

ฉันต้องการขอบคุณโทมัสเดวิสสำหรับหน้าที่ฉันได้รับรหัสพื้นฐานจาก :-)
คุณจะสังเกตเห็นสิ่งผิดปกติที่นี่: phantom โหลดซ้ำหน้าจนกว่าcheckLoaded()ฟังก์ชันจะคืนค่าจริง ทำไมถึงเป็นอย่างนั้น? นี่เป็นเพราะ SPA เฉพาะของฉันทำการโทร AJAX หลายครั้งเพื่อรับข้อมูลทั้งหมดและวางไว้ใน DOM บนหน้าของฉันและ phantom ไม่ทราบว่าเมื่อการโทรทั้งหมดเสร็จสิ้นก่อนที่จะคืนค่าเงาสะท้อน HTML ของ DOM ให้ฉัน สิ่งที่ฉันทำที่นี่คือหลังจากการโทร AJAX สุดท้ายที่ฉันเพิ่ม<span id='compositionComplete'></span>เพื่อว่าถ้าแท็กนี้มีอยู่ฉันรู้ว่า DOM เสร็จสมบูรณ์ ฉันทำสิ่งนี้เพื่อตอบสนองต่อcompositionCompleteเหตุการณ์ของ Durandal ดูที่นี่มากขึ้น หากสิ่งนี้ไม่เกิดขึ้นภายใน 10 วินาทีฉันก็ยอมแพ้ (มันน่าจะใช้เวลาเพียงเสี้ยววินาทีเท่านั้น) HTML ที่ส่งคืนมีลิงก์ทั้งหมดที่ผู้ใช้เห็นในเบราว์เซอร์ สคริปต์จะทำงานไม่ถูกต้องเนื่องจาก<script>แท็กที่มีอยู่ในสแน็ปช็อต HTML ไม่ได้อ้างอิง URL ที่ถูกต้อง สิ่งนี้สามารถเปลี่ยนแปลงได้เช่นกันในไฟล์ phantom javascript แต่ฉันไม่คิดว่านี่เป็นสิ่งจำเป็นเพราะ google snapshort ถูกใช้โดย Google เพื่อรับaลิงก์และไม่ให้เรียกใช้ javascript เท่านั้น เชื่อมโยงเหล่านี้ทำอ้างอิง URL ที่สวยและถ้าเป็นจริงถ้าคุณลองไปดูภาพรวม HTML ในเบราว์เซอร์ที่คุณจะได้รับความผิดพลาด javascript แต่การเชื่อมโยงทั้งหมดจะทำงานได้อย่างถูกต้องและนำคุณไปยังเซิร์ฟเวอร์อีกครั้งกับ URL ที่สวยในครั้งนี้ รับหน้าทำงานอย่างเต็มที่
นี่ไง. ตอนนี้เซิร์ฟเวอร์รู้วิธีจัดการ URL ทั้งสวยและน่าเกลียดโดยเปิดใช้งานสถานะพุชบนทั้งเซิร์ฟเวอร์และไคลเอนต์ URL ที่น่าเกลียดทั้งหมดได้รับการปฏิบัติเช่นเดียวกันโดยใช้ phantom ดังนั้นจึงไม่จำเป็นต้องสร้างตัวควบคุมแยกต่างหากสำหรับการโทรแต่ละประเภท
สิ่งหนึ่งที่คุณอาจต้องการที่จะมีการเปลี่ยนแปลงไม่ได้ที่จะให้เป็นนายพล '/ หมวดหมู่หมวดหมู่รอง / ผลิตภัณฑ์' โทร แต่จะเพิ่มเก็บ http://www.xyz.com/store/category/subCategory/product111'เพื่อให้การเชื่อมโยงจะมีลักษณะดังนี้: นี้จะหลีกเลี่ยงปัญหาที่เกิดขึ้นในการแก้ปัญหาของฉันว่า URL ที่ไม่ถูกต้องได้รับการปฏิบัติราวกับว่าพวกเขาเป็นจริงเรียกไป 'ดัชนี' ควบคุมและฉันคิดว่าสิ่งเหล่านี้สามารถจัดการได้แล้วภายในเก็บ 'ควบคุมโดยไม่ต้องไปweb.configฉันพบดังกล่าวข้างต้น .


ฉันมีคำถามอย่างรวดเร็วฉันคิดว่า ive ทำให้สิ่งนี้ทำงานได้ แต่เมื่อฉันส่งไซต์ของฉันไปที่ google และให้ลิงก์ไปยัง google, แผนผังเว็บไซต์และอื่น ๆ ฉันต้องให้ google mysite.com/# ! หรือเพียงแค่mysite.comและ google จะเพิ่มในescaped_fragmentเพราะฉันมีมันในเมตาแท็ก?
ccorrin

ccorrin - เพื่อความรู้ที่ดีที่สุดของฉันคุณไม่จำเป็นต้องให้ google อะไรเลย บอทของ google จะค้นหาไซต์ของคุณและค้นหา URL ที่น่ารัก (อย่าลืมในหน้าแรกเพื่อเพิ่มเมตาแท็กด้วยเนื่องจากอาจไม่มี URL ใด ๆ ) URL ที่น่าเกลียดซึ่งมี escaped_fragment จะถูกเพิ่มโดย google เท่านั้นคุณไม่ควรใส่มันเข้าไปใน HTML ของคุณ และขอบคุณสำหรับการสนับสนุน :-)
beamish

ขอบคุณ Bjorn & Sandra :-) ฉันกำลังทำงานกับเอกสารนี้ในเวอร์ชันที่ดีขึ้นซึ่งจะรวมถึงข้อมูลเกี่ยวกับวิธีการแคชหน้าเพื่อให้กระบวนการเร็วขึ้นและใช้งานได้บ่อยขึ้นเมื่อ url ประกอบด้วย ชื่อผู้ควบคุม ฉันจะโพสต์ได้เร็วที่สุดเท่าที่มันพร้อม
Beamish

นี่เป็นคำอธิบายที่ดีมาก !! ฉันใช้มันและใช้งานได้อย่างมีเสน่ห์ใน devbox ในพื้นที่ของฉัน ปัญหาคือเมื่อปรับใช้กับเว็บไซต์ Azure เนื่องจากเว็บไซต์ค้างและหลังจากเวลาฉันได้รับข้อผิดพลาด 502 คุณมีความคิดเกี่ยวกับวิธีการปรับใช้ phantomjs กับ Azure หรือไม่ ... ขอบคุณ ( testypv.azurewebsites.net/?_escaped_fragment_=home/about )
yagopv

ฉันไม่มีประสบการณ์กับเว็บไซต์ Azure แต่สิ่งที่อยู่ในใจของฉันคือบางทีขั้นตอนการตรวจสอบสำหรับการโหลดหน้าเว็บจะไม่สำเร็จดังนั้นเซิร์ฟเวอร์จะพยายามโหลดหน้าซ้ำอีกครั้งและอีกครั้งโดยไม่ประสบความสำเร็จ บางทีนั่นอาจเป็นปัญหา (แม้ว่าจะมีเวลา จำกัด ในการตรวจสอบเหล่านี้ดังนั้นจึงอาจไม่มี) ลองใส่ 'return true;' เป็นบรรทัดแรกใน 'checkLoaded ()' และดูว่ามันสร้างความแตกต่างหรือไม่
beamish


4

นี่คือลิงค์ไปสู่ ​​screencast-recording จากคลาสฝึกอบรม Ember.js ของฉันที่ฉันโฮสต์ในลอนดอนเมื่อวันที่ 14 สิงหาคม มันสรุปกลยุทธ์สำหรับทั้งแอปพลิเคชันฝั่งไคลเอ็นต์ของคุณและสำหรับแอปพลิเคชันฝั่งเซิร์ฟเวอร์ของคุณรวมถึงการสาธิตสดของวิธีการใช้คุณสมบัติเหล่านี้จะให้ JavaScript Single-Page-App ของคุณเสื่อมโทรมอย่างสง่างามแม้สำหรับผู้ใช้ที่ปิด JavaScript .

มันใช้ PhantomJS เพื่อช่วยในการรวบรวมข้อมูลเว็บไซต์ของคุณ

กล่าวโดยย่อขั้นตอนที่จำเป็นคือ:

  • มีเวอร์ชันของแอปพลิเคชันเว็บที่คุณต้องการรวบรวมข้อมูลเว็บไซต์นี้ต้องมีข้อมูลทั้งหมดที่คุณมีในการผลิต
  • เขียนแอปพลิเคชัน JavaScript (PhantomJS Script) เพื่อโหลดเว็บไซต์ของคุณ
  • เพิ่ม index.html (หรือ“ /“) ไปยังรายการ URL ที่จะรวบรวมข้อมูล
    • เปิด URL แรกที่เพิ่มเข้าไปในรายการรวบรวมข้อมูล
    • โหลดหน้าและแสดงผล DOM
    • ค้นหาลิงก์ใด ๆ ในหน้าเว็บโหลดที่เชื่อมโยงไปยังเว็บไซต์ของคุณเอง (การกรอง URL)
    • เพิ่มลิงค์นี้ไปยังรายการ URL ที่“ รวบรวมข้อมูลได้” หากยังไม่ได้รวบรวมข้อมูล
    • เก็บ DOM ที่เรนเดอร์ไว้ในไฟล์บนระบบไฟล์ แต่ตัดส่วนของแท็กสคริปต์ทั้งหมดออกก่อน
    • ในตอนท้ายให้สร้างไฟล์ Sitemap.xml ด้วย URL ที่รวบรวมข้อมูล

เมื่อทำขั้นตอนนี้เสร็จแล้วก็ขึ้นอยู่กับแบ็กเอนด์ของคุณเพื่อให้บริการเวอร์ชันคงที่ของ HTML ของคุณเป็นส่วนหนึ่งของแท็ก noscript ในหน้านั้น วิธีนี้จะช่วยให้ Google และเครื่องมือค้นหาอื่น ๆ สามารถรวบรวมข้อมูลได้ทุกหน้าในเว็บไซต์ของคุณแม้ว่าแอปของคุณจะเป็นหน้าจอเดียว

เชื่อมโยงไปยังหน้าจอพร้อมรายละเอียดทั้งหมด:

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


0

คุณสามารถใช้หรือสร้างบริการของคุณเองเพื่อแสดงผลสปาของคุณด้วยบริการที่เรียกว่า prerender คุณสามารถตรวจสอบมันบนเว็บไซต์ของเขาprerender.ioและในโครงการ GitHubของเขา(มันใช้ PhantomJS และมันทำให้เว็บไซต์ของคุณสำหรับคุณ)

มันง่ายมากที่จะเริ่มต้นด้วย คุณต้องเปลี่ยนเส้นทางโปรแกรมรวบรวมข้อมูลไปยังบริการและพวกเขาจะได้รับ html ที่แสดงผล


2
แม้ว่าลิงก์นี้อาจตอบคำถามได้ดีกว่าหากรวมส่วนสำคัญของคำตอบไว้ที่นี่และให้ลิงก์สำหรับการอ้างอิง คำตอบสำหรับลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าเว็บที่เชื่อมโยงมีการเปลี่ยนแปลง - จากรีวิว
timgeb

2
คุณพูดถูก ฉันได้อัปเดตความคิดเห็นของฉัน ... ฉันหวังว่าตอนนี้จะแม่นยำยิ่งขึ้น
gabrielperales

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.