শুরু করার আগে, দয়া করে নিশ্চিত হয়ে নিন যে গুগল কী প্রয়োজন , বিশেষত সুন্দর এবং কুরুচিপূর্ণ URL এর ব্যবহার । এখন এর বাস্তবায়নটি দেখতে দিন:
মক্কেলের পক্ষে
ক্লায়েন্টের পক্ষে আপনার কেবলমাত্র একটি একক এইচটিএমএল পৃষ্ঠা রয়েছে যা এজেএক্স কলগুলির মাধ্যমে সার্ভারের সাথে গতিশীলভাবে যোগাযোগ করে। এটিই এসপিএ সম্পর্কে। a
ক্লায়েন্ট পক্ষের সমস্ত ট্যাগগুলি আমার অ্যাপ্লিকেশনটিতে গতিশীলভাবে তৈরি করা হয়েছে, আমরা পরে দেখব কীভাবে এই লিঙ্কগুলি সার্ভারে গুগলের বটে দৃশ্যমান করা যায়। প্রতিটি যেমন a
ট্যাগ চাহিদা একটি আছে পাবে pretty URL
মধ্যে href
যাতে Google এর বট এটা ক্রল করবে ট্যাগ। তুমি কি চাও না href
অংশ যখন এটি মধ্যে ক্লায়েন্ট ক্লিক ব্যবহার করা হবে, কারণ আমরা করতে পারে লোড একটি নতুন পৃষ্ঠা চাই (যদিও আপনি সার্ভারে এটা বিশ্লেষণ করতে সক্ষম হতে চাও আমরা যা পরে দেখতে পাবেন,) কেবলমাত্র একটি এজেএক্স কল করার জন্য পৃষ্ঠার অংশে কিছু তথ্য প্রদর্শিত হবে এবং জাভাস্ক্রিপ্টের মাধ্যমে ইউআরএল পরিবর্তন করতে হবে (যেমন HTML5 ব্যবহার করে pushstate
বা এর সাথে Durandaljs
) using সুতরাং, আমরা উভয় একটি আছেhref
গুগলের জন্য যেমন বৈশিষ্ট্য onclick
সেই সাথে কাজ করে যখন ব্যবহারকারী লিঙ্কে ক্লিক করে। এখন, যেহেতু আমি ব্যবহার push-state
করি আমি #
ইউআরএলটিতে কোনও চাই না , তাই একটি সাধারণ 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
। এর কারণ আমি সংক্ষিপ্ত এবং সহজ লিঙ্কগুলিকে পছন্দ করি। এটি সূচিত করে যে আমি আমার 'পৃষ্ঠাগুলি' এর একটির মতো একই নামের কোনও বিভাগ থাকবে না, অর্থাৎ '
আমি এজেএক্স ( onclick
অংশ) এর মাধ্যমে ডেটা লোড করব কীভাবে যাব না , এটি গুগলে অনুসন্ধান করুন, অনেকগুলি ভাল ব্যাখ্যা রয়েছে। আমি এখানে উল্লেখ করতে চাই শুধুমাত্র গুরুত্বপূর্ণ জিনিসটি যখন ব্যবহারকারী এই লিঙ্কটি ক্লিক করেন, আমি ব্রাউজারে URL টি দেখতে চাই যাতে:
http://www.xyz.com/category/subCategory/product111
। এবং এটি সার্ভারে ইউআরএল প্রেরণ করা হয় না! মনে রাখবেন, এটি একটি এসপিএ যেখানে ক্লায়েন্ট এবং সার্ভারের মধ্যে সমস্ত মিথস্ক্রিয়া এজেএক্সের মাধ্যমে করা হয়, কোনও লিঙ্ক নেই! সমস্ত 'পৃষ্ঠাগুলি' ক্লায়েন্টের পাশেই প্রয়োগ করা হয়েছে, এবং বিভিন্ন ইউআরএল সার্ভারে কল দেয় না (অন্য সাইট থেকে অন্য কোনও সাইট থেকে আপনার সাইটে বহিরাগত লিঙ্ক হিসাবে ব্যবহৃত হয় সে ক্ষেত্রে এই URL গুলি কীভাবে পরিচালনা করতে হবে তা সার্ভারকে জানতে হবে, আমরা এটি পরে সার্ভারের অংশে দেখতে পাব)। এখন, এটি দুরণ্ডাল আশ্চর্যজনকভাবে পরিচালনা করেছেন। আমি দৃ strongly়ভাবে এটির প্রস্তাব দিচ্ছি, তবে আপনি অন্যান্য প্রযুক্তি পছন্দ করলে আপনি এই অংশটি এড়িয়ে যেতে পারেন। যদি আপনি এটি চয়ন করেন এবং আপনি আমার মতো ওয়েবের জন্য এমএস ভিজ্যুয়াল স্টুডিও এক্সপ্রেস 2012 ব্যবহার করছেন তবে আপনি ডুরান্ডাল স্টার্টার কিটটি ইনস্টল করতে পারেন এবং সেখানেও 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 });
}
};
});
এখানে কয়েকটি গুরুত্বপূর্ণ বিষয় লক্ষ্য করা যায়:
- (প্রথম রুট
route:''
) URL টি যার মধ্যে কোন অতিরিক্ত তথ্য আছে, অর্থাত জন্য http://www.xyz.com
। এই পৃষ্ঠাতে আপনি এজেএক্স ব্যবহার করে সাধারণ ডেটা লোড করুন। a
এই পৃষ্ঠায় আসলে কোনও ট্যাগ নেই । আপনি নিম্নলিখিত ট্যাগ যুক্ত করতে যাতে Google এর বট কি এটা দিয়ে কি জানবে চান:
<meta name="fragment" content="!">
। এই ট্যাগটি গুগলের বটকে ইউআরএল রূপান্তর করবে www.xyz.com?_escaped_fragment_=
যা আমরা পরে দেখব।
- আপনার ওয়েব অ্যাপ্লিকেশনটিতে আপনি চাইলে অন্যান্য 'পৃষ্ঠাগুলি'র লিঙ্কের' প্রায় 'রুট কেবলমাত্র একটি উদাহরণ।
- এখন, জটিল অংশটি হ'ল কোনও 'বিভাগ' রুট নেই এবং এখানে অনেকগুলি বিভিন্ন বিভাগ থাকতে পারে - যার কোনওটিরই পূর্বনির্ধারিত রুট নেই। এটি এখানেই
mapUnknownRoutes
আসে It এটি 'স্টোর' রুটে এই অজানা রুটের মানচিত্র তৈরি করে এবং কোনও 'সরান'! URL থেকে যদি এটি pretty URL
গুগলের সিচ ইঞ্জিন দ্বারা উত্পাদিত হয়। 'স্টোর' রুটটি 'টুকরো টুকরো' সম্পত্তিতে তথ্য নেয় এবং ডেটা পেতে, এটি প্রদর্শনের জন্য এবং স্থানীয়ভাবে ইউআরএল পরিবর্তন করতে AJAX কল করে। আমার অ্যাপ্লিকেশনটিতে, আমি এই জাতীয় প্রতিটি কলের জন্য আলাদা পৃষ্ঠা লোড করি না; আমি কেবলমাত্র পৃষ্ঠার অংশটি পরিবর্তন করেছি যেখানে এই ডেটা প্রাসঙ্গিক এবং স্থানীয়ভাবে ইউআরএলও পরিবর্তন করেছি।
- লক্ষ্য করুন
pushState:true
যে ডুরান্ডালকে পুশ স্টেটের ইউআরএল ব্যবহার করতে নির্দেশ দেয়।
ক্লায়েন্টের পক্ষে আমাদের এটির প্রয়োজন। এটি হ্যাশ ইউআরএলগুলির সাহায্যেও প্রয়োগ করা যেতে পারে (ডুরান্ডালে আপনি তার pushState:true
জন্য সরল সরল )। আরও জটিল অংশ (কমপক্ষে আমার জন্য ...) হ'ল সার্ভার অংশ:
সার্ভার সাইড
আমি নিয়ন্ত্রণকারীদের MVC 4.5
সাথে সার্ভার সাইডে ব্যবহার করছি WebAPI
। সার্ভারকে আসলে 3 ধরণের ইউআরএল হ্যান্ডেল করা দরকার: গুগল দ্বারা উত্পাদিত এগুলি - pretty
এবং ugly
ক্লায়েন্টের ব্রাউজারে প্রদর্শিত একইরকম ফর্ম্যাট সহ একটি 'সাধারণ' ইউআরএল। এটি কীভাবে করা যায় তা দেখুন:
সুন্দর ইউআরএল এবং 'সরল' গুলি প্রথমে সার্ভার দ্বারা ব্যাখ্যা করা হয় যেন কোনও অস্তিত্বহীন নিয়ামককে উল্লেখ করার চেষ্টা করা হয়। সার্ভারটি এর মতো কিছু দেখে 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
। আমি চাইছি যে ক্লায়েন্টের কাছে ইউআরএল প্রেরণ করা হবে যা এজেএক্সের মাধ্যমে ডেটা লোড করবে, সুতরাং এখানে কৌশলটি ডিফল্ট 'সূচক' নিয়ামককে কল করা যেন কোনও নিয়ামককে উল্লেখ না করে; আমি সমস্ত 'বিভাগ' এবং 'উপশ্রেণী' পরামিতির আগে ইউআরএলটিতে একটি হ্যাশ যুক্ত করে তা করি ; হ্যাশ ইউআরএলটিকে ডিফল্ট 'সূচক' নিয়ন্ত্রক ব্যতীত কোনও বিশেষ নিয়ামকের প্রয়োজন হয় না এবং ক্লায়েন্টের কাছে ডেটা প্রেরণ করা হয় যা হ্যাশ সরিয়ে দেয় এবং হ্যাশের পরে তথ্যটি এজেএক্সের মাধ্যমে ডেটা লোড করতে ব্যবহার করে। এখানে ত্রুটি হ্যান্ডলার নিয়ামক কোড:
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 টি সার্ভারে প্রেরণ করা হয় তখন আমাদের অবশ্যই এটি ধরতে হবে; এর জন্য, আমি নিম্নলিখিত ফাইলটি 'অ্যাপ_স্টার্ট' ফোল্ডারে যুক্ত করেছি:
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;
}
}
}
এটি 'ফিল্টারকনফিগ.সি.সি' থেকে 'অ্যাপ_স্টার্ট'-তেও ডাকা হয়:
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());
}
}
}
আপনি দেখতে পাচ্ছেন, 'আজাক্সক্র্যাবলএ্যাট্রিবিউট' কুটিল URL গুলি 'এইচটিএমএলস্ন্যাপশট' নামে একটি নিয়ামকের দিকে যাত্রা করে এবং এই নিয়ামকটি এখানে:
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()
ফাংশনটি সত্য না হওয়া পর্যন্ত পৃষ্ঠাটি পুনরায় লোড করতে থাকে । কেন এমন? এটি কারণ আমার নির্দিষ্ট এসপিএ সমস্ত ডেটা পেতে এবং এটি আমার পৃষ্ঠায় ডিওমে রাখার জন্য বেশ কয়েকটি এজেএক্স কল করে এবং ড্যামের এইচটিএমএল প্রতিবিম্বটি ফেরত দেওয়ার আগে যখন সমস্ত কল শেষ হয়ে যায় তখন ফ্যান্টম জানতে পারে না। আমি এখানে যা করেছি তা চূড়ান্ত এজ্যাক্স কল করার পরে আমি একটি যুক্ত করব <span id='compositionComplete'></span>
, যাতে এই ট্যাগটি উপস্থিত থাকলে আমি জানতে পারি যে ডমটি সম্পন্ন হয়েছে। আমি এটি ডুরান্ডালের compositionComplete
ঘটনার প্রতিক্রিয়াতে করি , এখানে দেখুনআরো বেশী. যদি এটি 10 সেকেন্ডের সাথে না ঘটে তবে আমি ছেড়ে দেব (এটি সবচেয়ে বেশি মাত্র এক সেকেন্ড সময় নেয়)। ফিরিয়ে দেওয়া এইচটিএমএলটিতে ব্রাউজারটিতে ব্যবহারকারীরা যে সমস্ত লিঙ্ক দেখেন সেগুলি রয়েছে। স্ক্রিপ্টটি সঠিকভাবে কাজ করবে না কারণ <script>
এইচটিএমএল স্ন্যাপশটে যে ট্যাগগুলি রয়েছে সেগুলি সঠিক URL টি উল্লেখ করে না। এটি জাভাস্ক্রিপ্ট ফ্যান্টম ফাইলেও পরিবর্তন করা যেতে পারে, তবে আমি মনে করি না এটি নেসেসারি বলে কারণ এইচটিএমএল স্ন্যাপশটটি কেবল গুগল a
লিঙ্কগুলি পেতে এবং জাভাস্ক্রিপ্ট চালানোর জন্য ব্যবহার করে না; এই লিঙ্ক কি রেফারেন্স একটি প্রশংসনীয় URL টি, এবং সত্য যদি, যদি আপনি একটি ব্রাউজারে এইচটিএমএল স্ন্যাপশট দেখতে চেষ্টা, আপনি জাভাস্ক্রিপ্ট ত্রুটি পাবেন কিন্তু সমস্ত লিঙ্কের ঠিকমত কাজ এবং একটি সুন্দর URL টি এই সময়ের সাথে সাথে আবার সার্ভারে আপনি নির্দেশ করবে পুরোপুরি কাজ করার পৃষ্ঠাটি পেয়েছি।
এই হল. এখন সার্ভার জানে যে কীভাবে উভয় সুন্দর এবং কুরুচিপূর্ণ URL টি পরিচালনা করতে হবে, সার্ভার এবং ক্লায়েন্ট উভয়েই পুশ-স্টেট সক্ষম রয়েছে। সমস্ত কুরুচিপূর্ণ URL গুলি ভুত ব্যবহার করে একইরকম আচরণ করা হয় যাতে প্রতিটি ধরণের কলের জন্য আলাদা কন্ট্রোলার তৈরি করার দরকার নেই।
একটা জিনিষ আপনি পরিবর্তন করতে পছন্দ হতে পারে একটি সাধারণ 'বিভাগ / উপবিষয়শ্রেণীটি / পণ্য' কল করতে কিন্তু একটি 'দোকান' যাতে লিংক মত দেখাবে যোগ করার জন্য হল: http://www.xyz.com/store/category/subCategory/product111
। এটি আমার সমাধানের সমস্যাটি এড়াবে যে সমস্ত অবৈধ ইউআরএলগুলি এমন আচরণ করা হয় যেন তারা প্রকৃতপক্ষে 'সূচক' নিয়ন্ত্রকের কাছে কল হয় এবং আমি মনে করি যে এগুলি 'স্টোর' নিয়ন্ত্রকের মধ্যে web.config
উপরোক্ত প্রদর্শিত সংযোজন ব্যতিরেকে পরিচালনা করা যেতে পারে above ।