为AngularJS + Spring MVC网站生成静态SEO页面

9
我有一个项目使用Spring MVC + AngularJS。所有数据都是动态的。此应用程序中有一些大型位置数据库。
为了SEO目的,需要为每个位置生成静态页面,并将它们放在SEO友好的网址上(例如/localhost/path1/path2/here-is-very-friendly-name)。
最好的方法是什么?
我是否只需单独生成页面并将它们放入主应用程序的某个单独文件夹中(如果是,则最佳方法是什么?),还是可以使用Spring / Angular进行操作?
(额外信息)
每个位置对象包含id、name、latitude、longtitude、地址、区域、城市、国家。

2
你应该在这个问题上设置赏金。这很有趣。 - Demeter Dimitri
4个回答

8

实际上这是我的Angular/SEO经验。
你需要做很多改变!!


1) 从URL中移除#

app.config(['$locationProvider', function ($locationProvider) {

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });

}]);

2) 检查MVC路由

到目前为止,您可能有一个HomeController用于返回index.cshtml并启动您的Angular App。
在从Angular路由中删除#后,您需要为所有路由设置MapRoute
因为在这种情况下,当您第一次尝试访问诸如www.site.com/any_route之类的路由时,Angular应用程序尚未加载,因此它会尝试从MVC Routing获取页面。但是之后$routeProvider会执行其职责。


3) 使用MVC变量设置元标记

为了更好地进行索引并与爬虫和机器人友好,我们必须使用MVC变量来初始化网站元标记。
如果您通过Angular绑定设置页面标题,例如:<title>{{title}}</title>,那么每当您想通过社交网络共享页面时,您将看到{{title}},因为社交网络无法呈现网站。

<title>@ViewBag.title</title>
<meta name="Description" content="@ViewBag.description">
<meta name="Keywords" content="@ViewBag.keywords">
<meta property="og:title" content="@ViewBag.title" />
<meta property="og:description" content="@ViewBag.description" />

4)替换 Angular 绑定的元标签

我们的应用是单页应用程序(SPA),因此在加载 Angular 后,我们已经离开了 MVC 的领域。 我们需要用 MVC 变量替换 Angular 变量。

angular.element('title').remove();
angular.element('meta[name="Description"]').remove();
angular.element('meta[name="Keywords"]').remove();
angular.element('meta[property="og:title"]').remove();
angular.element('meta[property="og:description"]').remove();

var description = angular.element('<meta name="Description" content="{{meta.description}}">');
angular.element('head').prepend(description);    

var keyword = angular.element('<meta name="Keywords" content="{{meta.keywords}}">');
angular.element('head').prepend(keyword);    

var titleOg = angular.element('<meta property="og:title" content="{{meta.title}}" />');
angular.element('head').prepend(titleOg);    

var descriptionOg = angular.element('<meta property="og:description" content="{{meta.description}}" />');
angular.element('head').prepend(descriptionOg);

var title = angular.element('<title ng-bind="meta.title"></title>');
angular.element('head').prepend(title);  

$rootScope.$applyAsync(function () {
    $compile(title)($rootScope);
    $compile(description)($rootScope);
    $compile(keyword)($rootScope);
    $compile(titleOg)($rootScope);
    $compile(descriptionOg)($rootScope);
});

5) 使用JSON-LD处理动态内容

如果您熟悉SCHEMA.org,最好使用JSON-LD而不是其他格式,因为搜索引擎机器人可以捕捉和分析在页面加载后动态插入的<script type="application/ld+json"></script>
您需要查看Schema字典以找到与数据结构最相近的类型。
例如,以下是我公司的json-ld:

<script type="application/ld+json">
    {
        "@context" : "http://schema.org",
        "@type" : "Organization",
        "name" : "داده کاوان امیرکبیر",
        "alternateName" : "ADM | Amirkabir Data Miners",
        "description": "شرکت داده کاوان امیرکبیر | تولید کننده نرم افزارهای تحت وب، از قبیل حسابداری آنلاین 'کاج سیستم' ، سیستم مدیریت پروژه 'تسک من' و ...",
        "url" : "https://adm-co.net",
        "email": "info@adm-co.net",
        "logo": {
            "@type": "ImageObject",
            "url": "http://khoonamon.com/images/ADM_Logo.png",
            "caption": "لوگو داده کاوان امیرکبیر",
            "width": "2480px",
            "height": "1459px"
        },
        "telephone": "+98-21-44002963",
        "address": "تهران، خیابان آیت ا... کاشانی، نبش خیابان عقیل، پلاک 380، طبقه دوم",
        "contactPoint" : [{
            "@type" : "ContactPoint",
            "telephone" : "+98-21-44002963",
            "contactType" : "customer service",
            "contactOption" : "TollFree",
            "areaServed" : "IR",
            "availableLanguage" : "Persian"
        }],
        "sameAs" : [
            "https://google.com/+ADMcoNet-GPlus",
            "https://www.linkedin.com/company/adm-amirkabir-data-miners-?trk=biz-companies-cym",
            "https://instagram.com/AmirkabirDataMiners/",
            "https://www.facebook.com/AmirkabirDataMiners",
            "http://www.pinterest.com/AmirkabirDM/",
            "https://twitter.com/AmirkabirDM",
            "https://www.youtube.com/channel/UCQxP0vZA05Pl9GlyXXQt14A/about"
        ]
    }
</script>

你好,感谢您的回复。对于这种应用程序的SEO来说,它是有用和信息丰富的。但是,这并不是原始问题的答案。 - user1935987
@user1935987 你确定吗? - MeTe-30

1

是的,我知道那些工具,但它们只是绕过页面本身的存在,根本没有回答问题。 - user1935987

1
我自己没有尝试过,但PhantomJs可能是能够做到这一点的最佳选择。
您需要一个字典,其中包含您要呈现的端点及其相应的静态文件路径名。然后,您将遍历每个端点,使用PhantomJS呈现给定路径,然后将输出保存到静态文件中。
从您的问题中所了解到的情况来看,您似乎还没有在Angular应用程序的前端上使用这些路径?如果是这种情况,那么我会说另一种选项是通过Spring仅在服务器端呈现它们。
问题在于,angular并没有考虑到等同性(客户端和服务器端渲染)。如果您想在尚未构建的服务器端进行任何适当的呈现,则最好的选择是使用Spring进行呈现。
另一种选择是升级到具有isomorphic功能的Angular2,并借助angular universal实现。如果Spring不用于呈现,而只作为您的应用程序的API,则此选项将很好地发挥作用。

0

我没有用Java做过这个,但是用C#做了,请通知我如果你在Java中实现了它:

我找到了关于phantomJs的代码片段,然后:

正如我们的朋友所说,我们启用了html5模式,我们使用写引擎在C#中重写了所有的URL,这是IIS中的新功能,我为谷歌请求保留了一个特定的规则,该请求带有特定的查询参数(在网络上找不到它,而且时间也不多)。所以我将它们重定向到这个特定的页面,读取重定向的URL,传递并在phantomJS上运行它,并等待结果返回(需要了解如何运行进程并获取控制台结果),然后,我们从应用程序中删除了ng-app属性,并将原始页面传递给谷歌爬虫(我们有两种重定向代码,只有其中一种起作用,最后直到那个时候,一种是永久的,另一种是临时的)。对于自己来说,这个页面看起来很粗糙,但是谷歌只关注您的架构和结构,所以一切都很好。

我已经很久没有接触Java了,所以我无法实现它,我只恢复了一点关于Spring的知识,所以如果您有任何更新,请通知我,我将不胜感激。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接