65.9K
CodeProject 正在变化。 阅读更多。
Home

AngularJS 社交分享和 SEO

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.25/5 (3投票s)

2016年3月14日

CPOL

4分钟阅读

viewsIcon

21001

随着 Web 应用程序开发越来越依赖 JavaScript 技术(AngularJS、React 等),对 JavaScript 渲染的依赖变得比以往任何时候都更加重要。本文将介绍如何在纯 JavaScript 应用程序中处理 SEO 和社交分享。

问题

AngularJS 框架非常棒,双向数据绑定是 AngularJS 的主要特性和强大之处之一。在我开始从事我的 AngularJS 项目的第一天,我就无法回头了。

这种 JavaScript 渲染 HTML 的技术非常棒,与 ASP.Net MVC 等其他框架相比,它更简单、更快速。

但是,一个问题始终在我脑海中盘旋——当我们不需要浏览器就能获取最终渲染的页面(包括所有内容和元标签)时会发生什么?比如说,通过 Web 请求?或者某个爬虫?结果会是什么?

在下面的 POC 示例应用程序中,我创建了一个带有简单服务的 Angular 应用程序,该服务会更新 rootScope 上的 **MetaTitle** 和 **MetaDescription** 值,并将它们绑定到 title 和 description 元标签。

angular.module('MyApp',[]).service('updatemymetaplease',function($rootScope){
    var $rootScope = $rootScope;
    retrun {
           UpdateNow:
               function(title,description) {

                   this.$rootScope.MetaTitle = title;
                   this.$rootScope.MetaDescription = description;
           }
    }})
    
    .controller('MainController',function(updatemymetaplease){
          updatemymetaplease.UpdateNow('My App Title','Awsome Application');
    });



以及 page.html 文件

<html ng-app="MyApp">
   <head>
        <title>{{MetaTitle}}</title>
        <meta name="description" content="{{ MetaDescription }}">
  </head>
  <body ng-controller="MainController">
        <p>Exemple App</p>
   
      <script src="app.js"></script>
  </body>
</html>

 在 Angular 的 digest 周期之后,输出将如下所示

<html>
   <head>
        <title>My App Title</title>
        <meta name="description" content="Awsome Application">
  </head>
  <body></body>
  <script src="app.js"></script>
</html>

是不是很棒?没有静态元标签,我的 HTML 文件完全是动态的、干净且易于阅读,没有任何难以理解的 JS 文件和全局作用域上的 JQuery 操作,尤其是——我不需要任何服务器端框架(asp.net、php、java 等),我可以在客户端动态绑定我的元标签。

让我们来测试一下我们超赞的网站的 Facebook 分享预览框吧!

 - Facebook 预览显示

 

为什么?

嗯,JavaScript 是一种客户端语言(NodeJS 系列除外)。我的意思是 UI 只能由浏览器运行和渲染——那么如果你的客户端不使用浏览器会发生什么?在这种情况下,Facebook 抓取器——爬虫期望获得一个完全渲染的 HTML 页面,实际上调用者似乎进行了 GET 请求,返回了以下 HTML 页面。

<html>
   <head>
        <title>{{MetaTitle}}</title>
        <meta name="description" content="{{ MetaDescription }}">
  </head>
  <body>
        <p>Exemple App</p>
  </body>
</html>

这不是 Bug!

我们都知道 Google 开始渲染重度 JS 应用程序,这为 Google SEO 问题提供了解决方案,但对于 Bing 爬虫呢?Facebook 抓取器?Twitter 和许多其他服务?此时,一个纯 AngularJS 应用将会显示出它作为输出 HTML 的样子,而没有 JS 渲染。

我真的必须用服务器端框架来包装我的应用程序来解决这个问题吗?——**不**

解决方案描述

我们将使用超棒的 PhantomJS (http://phantomjs.org/) 在发送响应之前渲染 AngularJS 脚本,这样我们就可以确保元标签和内容对搜索引擎可用,并且 HTML 页面的输出将是完全渲染的 HTML 页面。您还可以设置一个快照创建器——这样您可以比以往更快地响应。

这将是应用程序的最终生命周期

一旦 IIS 收到一个传入的请求,Rewrite 模块就会决定

    - 如果是 Facebook、Twitter、Bing 或您定义的任何内容——那么请求将被传输到 PhantomJS Windows 服务——并且完全渲染的 HTML 将是输出。

    - 否则,将执行常规的网站行为。

确保您按照预期定义重写规则,不要将所有 HTTP 调用重定向到 PhantomJS,只重定向您需要的。

 

下载代码:https://github.com/benmizrahi/AngularJS-Social-Sharing-And-SEO

设置与配置

测试环境:Windows Server 2012 R2,IIS 8.5

步骤 1 - 安装

1) 下载并安装 URL-Rewrite 模块

    http://www.iis.net/downloads/microsoft/url-rewrite

2) 下载并安装 Application-Request-Routing

http://www.iis.net/learn/extensions/installing-application-request-routing-arr/install-application-request-routing

步骤 2 - Phantom Windows 服务

1) 下载 git 项目。

2) 打开 PhantomService.exe.config 文件,用记事本打开,配置以下内容:

      a) PathToPhantom - phantom.exe 的本地路径(来自 zip)。

      b) PhantomScript - phantom 脚本的本地路径(Components\phantomWS.js)。

      c) PhantomLogLocation - phantom 日志记录位置

      d) PhantomPort - 监听的本地端口

      e) LocalHost - 你的本地应用主机(通常是 http://yourdnsname)。

      f) CreateSnapshots - 启用快照(1/0)。

      g) SanpshootLocation - 保存快照的位置。

3) 打开 cmd 并导航到 "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319"

4) 运行以下命令:InstallUtil.exe "\path\to\phantom\service\PhantomService.exe" - 以管理员用户身份进行安装。

5)  在启动 Windows 服务之前,请转到 "%systemroot%\system32\drivers\etc\"

       打开 hosts 文件并将 yourdnsname 添加为 127.0.0.1  - 在服务器内部测试,您应该可以访问:

      http://yourdnsname.

6) 转到“运行”并打开 services.msc, 启动 PhantomJSWS 服务,然后您可以通过浏览 https://:selectedport/ 来测试 phantom 是否正在运行 - 您应该会看到 IIS 欢迎屏幕。

 

步骤 3 - IIS 设置

Application Request Routing 配置

1) 打开 inetmgr,转到顶级(服务器级别)并选择 Features View。

2) 选择 Application Request Routing Catch (应该是第一个)。

3) 在右侧选择 Server Proxy Settings。

4) 勾选复选框 - Enable proxy。

5) 保存设置。

URL-Rewrite 配置

1) 打开 inetmgr,并选择您的站点或应用程序。

2) 在 Features View 中 - 选择 Url Rewrite

3) 添加以下设置

 { HTTP_USER_AGENT }

 

 

重写模型

URL:https://:selectedphantomport/{URL}

此设置会将请求重写到 phantom Windows 服务。

测试: 在 URL 中添加:?escaped_fragment_= 您应该会获得您请求的页面

示例: http://yourdnsname/?escaped_fragment_=

 

步骤 4 - AngularJS 端

1) 将 RenderFinishedDirective.js 指令添加到您的站点并将其包含到您的 AngularApp 中。

2) 在您的 index.html 文件中 -> 在 body 元素的底部添加指令: 

   <render-finished-directive></render-finished-directive>

注意: 您可以通过在应用程序完成渲染时(所有 Promise 完成工作后)添加此代码来避免添加此指令。

 if (typeof window.callPhantom == 'function') {
      window.callPhantom();
  }

 

就是这样——您完成了。

如果您需要任何帮助,请随时联系。

Ben Mizrahi

benm@item-soft.com

 

 

© . All rights reserved.