4

問題

我有一個使用Angular構建並託管在Amazon S3上的靜態SPA網站。我試圖使抓取工具可以對預渲染的頁面進行訪問,但我無法重定向抓取工具請求,因爲Amazon S3不提供URL Rewrite選項,並且重定向規則有限。如何在使用Amazon S3時將抓取工具請求重定向到預先呈現的頁面?

我有什麼

我已經添加了下列元標記來我的index.html的<head>頁:

<meta name="fragment" content="!"> 

而且,我的SPA採用簡潔的URL(不散列#符號)與HTML5推狀態。

使用此設置,當爬蟲發現我的http://mywebsite.com/about鏈接時,它將發出GET請求http://mywebsite.com/about?_escaped_fragment_=。這是一個pattern defined by Google,其次是其他爬蟲。

我需要的是用about.html文件的預渲染版本來回答此請求。我已經使用Phantom.js完成了此預渲染,但由於Amazon S3沒有重寫規則,因此無法爲抓取工具提供正確的文件。

nginx的服務器,解決辦法是增加一個重寫規則,如:

location/{ 
    if ($args ~ "_escaped_fragment_=") { 
    rewrite ^/(.*)$ /snapshots/$1.html break; 
    } 
} 

但在亞馬遜S3,我被他們的redirect rules基於KeyPrefixes和HttpErrorCodes限制。 ?_escaped_fragment_=不是KeyPrefix,因爲它出現在URL的末尾,並且它不會提供HTTP錯誤,因爲Angular會忽略它。

我已經試過

我已經開始使用帶有ngRoute動態模板嘗試,但後來我意識到,因爲我針對爬蟲能我不能與任何角度的解決方案解決了這個」執行JavaScript。

有了Amazon S3,我必須堅持使用他們的重定向規則。

我設法使用一種醜陋的解決方法來處理它。如果我爲每個頁面的新規則,我做:

<RoutingRules> 

    <!-- each page needs it own rule --> 
    <RoutingRule> 
    <Condition> 
     <KeyPrefixEquals>about?_escaped_fragment_=</KeyPrefixEquals> 
    </Condition> 
    <Redirect> 
     <HostName>mywebsite.com</HostName> 
     <ReplaceKeyPrefixWith>snapshots/about.html</ReplaceKeyPrefixWith> 
    </Redirect> 
    </RoutingRule> 

</RoutingRules> 

正如你可以在此解決方案看,每一頁都需要它自己的規則。由於亞馬遜限制只有50個重定向規則,這不是一個可行的解決方案。

另一種解決方案是忘掉漂亮的URL並使用hashbangs。有了這個,我的鏈接將是http://mywebsite.com/#!about,爬蟲將要求這與http://mywebsite.com/?_escaped_fragment_=about。由於URL將以?_escaped_fragment_=開頭,因此可以使用KeyPrefix捕獲,只需一個重定向規則即可。但是,我不想使用醜陋的URL。

那麼,我該如何在亞馬遜S3中使用靜態SPA並對搜索引擎友好?

+1

剛寫完我的問題後,我已經意識到如何解決這個問題。由於我花了很多時間試圖找出錯誤的路徑,所以我在下面發佈了我的答案,希望能夠幫助其他人。 – Zanon

回答

5

簡答

亞馬遜S3(和Amazon CloudFront的)不提供重寫規則,只有有限的重定向選項。但是,您不需要需要重定向或重寫您的URL請求。只需預渲染全部HTML文件和將其上傳到您的網站路徑

由於瀏覽網頁的用戶啓用了JavaScript,Angular將被觸發並將控制導致重新呈現模板的頁面。有了這個,所有的Angular功能都可以供這個用戶使用。

關於爬蟲,預渲染的頁面就足夠了。


如果你有一個名爲網站www.myblog.com,並鏈接到其他網頁的URL www.myblog.com/posts/my-first-post。很可能,您的Angular應用程序具有以下結構:index.html文件位於您的根目錄中並負責所有內容。 my-first-post是位於/partials/my-first-post.html的部分HTML文件。

這種情況下的解決方案是在部署時使用預渲染工具。您可以使用PhantomJS進行此操作,但您不能使用中間件工具,如Prerender,因爲您在Amazon S3中託管了靜態網站。

您需要使用該預渲染工具來創建兩個文件:的index.html我先交。請注意,my-first-post將是一個不包含.html擴展名的HTML文件,但在上傳到Amazon S3時,您需要將其Content-Type設置爲text/html

你將我先交放置的index.html文件在你的根目錄下,並名爲帖子文件夾內,以配合您的URL路徑/職位/我先交

使用這種方法,爬蟲將能夠檢索您的HTML文件,用戶將很樂意使用所有的Angular功能。


注意:此解決方案要求使用根路徑引用所有文件。如果您訪問鏈接www.myblog.com/posts/my-first-post,相對路徑將不起作用。

通過根路徑,我的意思是:

<script src="/js/myfile.js"></script> 

錯誤的方式,使用相對路徑,將是:

<script src="js/myfile.js"></script> 


編輯:

下面跟隨我使用PhantomJS預渲染頁面的小型JavaScript代碼。在安裝PhantomJS並使用單個頁面測試腳本之後,向您的構建過程添加一個腳本以在部署站點之前預先渲染所有頁面。

var fs = require('fs'); 
var webPage = require('webpage'); 
var page = webPage.create(); 

// since this tool will run before your production deploy, 
// your target URL will be your dev/staging environment (localhost, in this example) 
var path = 'pages/my-page'; 
var url = 'http://localhost/' + path; 

page.open(url, function (status) { 

    if (status != 'success') 
    throw 'Error trying to prerender ' + url; 

    var content = page.content; 
    fs.write(path, content, 'w'); 

    console.log("The file was saved."); 
    phantom.exit(); 
}); 

注:它看起來像Node.js的,但事實並非如此。它必須用Phantom可執行文件執行,而不是Node。

+0

如果有一個可以幫助預渲染的腳本,那將會非常棒。 – jjbskir

+0

@jjbskir,我已經添加了我用來預渲染一個頁面的腳本。 – Zanon

+0

這很酷!我可以看到爲我的一些項目工作,但不是其他項目。我的項目只有靜態的HTML,我沒有太多的互動性,他們會工作,但我的項目,我動態添加在視圖和控制器我會有問題。這個週末我開始研究一種預渲染我的所有角頁面的方法 - https://github.com/jjbskir/angular-prerender - 這樣可以幫助你嗎? – jjbskir

相關問題