“单页"JS 网站和 SEO [英] "Single-page" JS websites and SEO

查看:17
本文介绍了“单页"JS 网站和 SEO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在有很多很酷的工具可以制作强大的单页"JavaScript 网站.在我看来,这是通过让服务器充当 API(仅此而已)并让客户端处理所有 HTML 生成内容来完成的.这种模式"的问题在于缺乏搜索引擎支持.我能想到两个解决方案:

There are a lot of cool tools for making powerful "single-page" JavaScript websites nowadays. In my opinion, this is done right by letting the server act as an API (and nothing more) and letting the client handle all of the HTML generation stuff. The problem with this "pattern" is the lack of search engine support. I can think of two solutions:

  1. 当用户进入网站时,让服务器完全按照客户端在导航时的方式呈现页面.因此,如果我直接转到 http://example.com/my_path,服务器将呈现与客户端在我通过 pushState 转到 /my_path 相同的内容.
  2. 让服务器只为搜索引擎机器人提供一个特殊的网站.如果普通用户访问 http://example.com/my_path,服务器应该给他一个网站的 JavaScript 重度版本.但是,如果 Google bot 访问,服务器应该给它一些最小的 HTML,其中包含我希望 Google 索引的内容.
  1. When the user enters the website, let the server render the page exactly as the client would upon navigation. So if I go to http://example.com/my_path directly the server would render the same thing as the client would if I go to /my_path through pushState.
  2. Let the server provide a special website only for the search engine bots. If a normal user visits http://example.com/my_path the server should give him a JavaScript heavy version of the website. But if the Google bot visits, the server should give it some minimal HTML with the content I want Google to index.

此处进一步讨论了第一个解决方案.我一直在一个网站上做这件事,这不是一个很好的体验.这不是 DRY,在我的情况下,我不得不为客户端和服务器使用两个不同的模板引擎.

The first solution is discussed further here. I have been working on a website doing this and it's not a very nice experience. It's not DRY and in my case I had to use two different template engines for the client and the server.

我想我已经看到了一些不错的 Flash 网站的第二种解决方案.我比第一种方法更喜欢这种方法,并且在服务器上使用正确的工具可以轻松完成.

I think I have seen the second solution for some good ol' Flash websites. I like this approach much more than the first one and with the right tool on the server it could be done quite painlessly.

所以我真正想知道的是以下内容:

So what I'm really wondering is the following:

  • 你能想到更好的解决方案吗?
  • 第二种解决方案的缺点是什么?如果 Google 以某种方式发现我没有像普通用户那样为 Google bot 提供完全相同的内容,那么我会在搜索结果中受到惩罚吗?

推荐答案

虽然#2 对开发人员来说可能更容易",但它只提供搜索引擎抓取.是的,如果 Google 发现您提供不同的内容,您可能会受到处罚(我不是这方面的专家,但我听说过这种情况).

While #2 might be "easier" for you as a developer, it only provides search engine crawling. And yes, if Google finds out your serving different content, you might be penalized (I'm not an expert on that, but I have heard of it happening).

SEO 和可访问性(不仅适用于残疾人,还可以通过移动设备、触摸屏设备和其他非标准计算/互联网平台进行访问)都具有相似的基本理念:语义丰富的标记是可访问的"(即可以被访问、查看、阅读、处理或以其他方式使用)到所有这些不同的浏览器.屏幕阅读器、搜索引擎爬虫或启用了 JavaScript 的用户都应该能够毫无问题地使用/索引/理解您网站的核心功能.

Both SEO and accessibility (not just for disabled person, but accessibility via mobile devices, touch screen devices, and other non-standard computing / internet enabled platforms) both have a similar underlying philosophy: semantically rich markup that is "accessible" (i.e. can be accessed, viewed, read, processed, or otherwise used) to all these different browsers. A screen reader, a search engine crawler or a user with JavaScript enabled, should all be able to use/index/understand your site's core functionality without issue.

pushState 不会增加这种负担.它只会将过去的事后想法和如果我们有时间"带到 Web 开发的最前沿.

pushState does not add to this burden, in my experience. It only brings what used to be an afterthought and "if we have time" to the forefront of web development.

您在选项 #1 中描述的通常是最好的方法 - 但是,与其他可访问性和 SEO 问题一样,在 JavaScript 密集型应用程序中使用 pushState 执行此操作需要预先计划或这将成为一个重大的负担.它应该从一开始就融入到页面和应用程序架构中 - 改造是痛苦的,并且会导致不必要的重复.

What your describe in option #1 is usually the best way to go - but, like other accessibility and SEO issues, doing this with pushState in a JavaScript-heavy app requires up-front planning or it will become a significant burden. It should be baked in to the page and application architecture from the start - retrofitting is painful and will cause more duplication than is necessary.

我最近一直在使用 pushState 和 SEO 来开发几个不同的应用程序,我发现我认为这是一个很好的方法.它基本上遵循您的第 1 项,但不会重复 html/模板.

I've been working with pushState and SEO recently for a couple of different application, and I found what I think is a good approach. It basically follows your item #1, but accounts for not duplicating html / templates.

大部分信息都可以在这两篇博文中找到:

Most of the info can be found in these two blog posts:

http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/

http:///lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/

它的要点是我使用 ERB 或 HAML 模板(运行 Ruby on Rails、Sinatra 等)进行服务器端渲染并创建 Backbone 可以使用的客户端模板,以及我的 Jasmine JavaScript 规范.这消除了服务器端和客户端之间的标记重复.

The gist of it is that I use ERB or HAML templates (running Ruby on Rails, Sinatra, etc) for my server side render and to create the client side templates that Backbone can use, as well as for my Jasmine JavaScript specs. This cuts out the duplication of markup between the server side and the client side.

从那里开始,您需要采取一些额外的步骤来让您的 JavaScript 与服务器呈现的 HTML 一起工作——真正的渐进式增强;采用已交付的语义标记并使用 JavaScript 对其进行增强.

From there, you need to take a few additional steps to have your JavaScript work with the HTML that is rendered by the server - true progressive enhancement; taking the semantic markup that got delivered and enhancing it with JavaScript.

例如,我正在使用 pushState 构建一个图片库应用程序.如果您从服务器请求 /images/1,它将在服务器上呈现整个图片库,并将所有 HTML、CSS 和 JavaScript 发送到您的浏览器.如果您禁用了 JavaScript,它就可以正常工作.您采取的每项操作都会从服务器请求不同的 URL,服务器将为您的浏览器呈现所有标记.但是,如果您启用了 JavaScript,JavaScript 将选择已经呈现的 HTML 以及服务器生成的一些变量,并从那里接管.

For example, i'm building an image gallery application with pushState. If you request /images/1 from the server, it will render the entire image gallery on the server and send all of the HTML, CSS and JavaScript down to your browser. If you have JavaScript disabled, it will work perfectly fine. Every action you take will request a different URL from the server and the server will render all of the markup for your browser. If you have JavaScript enabled, though, the JavaScript will pick up the already rendered HTML along with a few variables generated by the server and take over from there.

这是一个例子:

<form id="foo">
  Name: <input id="name"><button id="say">Say My Name!</button>
</form>

在服务器呈现这个之后,JavaScript 会选择它(在这个例子中使用 Backbone.js 视图)

After the server renders this, the JavaScript would pick it up (using a Backbone.js view in this example)

FooView = Backbone.View.extend({
  events: {
    "change #name": "setName",
    "click #say": "sayName"
  },

  setName: function(e){
    var name = $(e.currentTarget).val();
    this.model.set({name: name});
  },

  sayName: function(e){
    e.preventDefault();
    var name = this.model.get("name");
    alert("Hello " + name);
  },

  render: function(){
    // do some rendering here, for when this is just running JavaScript
  }
});

$(function(){
  var model = new MyModel();
  var view = new FooView({
    model: model,
    el: $("#foo")
  });
});

这是一个非常简单的例子,但我认为它可以说明问题.

This is a very simple example, but I think it gets the point across.

当我在页面加载后实例化视图时,我将服务器呈现的表单的现有内容作为视图的 el 提供给视图实例.在加载第一个视图时,我调用渲染或让视图为我生成一个 el.在视图启动并运行并且页面都是 JavaScript 之后,我有一个可用的渲染方法.这让我可以在需要时重新渲染视图.

When I instante the view after the page loads, I'm providing the existing content of the form that was rendered by the server, to the view instance as the el for the view. I am not calling render or having the view generate an el for me, when the first view is loaded. I have a render method available for after the view is up and running and the page is all JavaScript. This lets me re-render the view later if I need to.

在启用 JavaScript 的情况下单击说出我的名字"按钮将导致出现警告框.如果没有 JavaScript,它会回发到服务器,服务器可以将名称渲染到某处的 html 元素.

Clicking the "Say My Name" button with JavaScript enabled will cause an alert box. Without JavaScript, it would post back to the server and the server could render the name to an html element somewhere.

编辑

考虑一个更复杂的例子,你有一个需要附加的列表(来自下面的评论)

Consider a more complex example, where you have a list that needs to be attached (from the comments below this)

假设您在

    标签中有一个用户列表.这个列表是在浏览器发出请求时由服务器呈现的,结果类似于:

    Say you have a list of users in a <ul> tag. This list was rendered by the server when the browser made a request, and the result looks something like:

    <ul id="user-list">
      <li data-id="1">Bob
      <li data-id="2">Mary
      <li data-id="3">Frank
      <li data-id="4">Jane
    </ul>
    

    现在您需要遍历此列表并将 Backbone 视图和模型附加到每个

  • 项目.通过使用 data-id 属性,您可以轻松找到每个标签来自的模型.然后你需要一个足够智能的集合视图和项目视图来将自己附加到这个 html.

    Now you need to loop through this list and attach a Backbone view and model to each of the <li> items. With the use of the data-id attribute, you can find the model that each tag comes from easily. You'll then need a collection view and item view that is smart enough to attach itself to this html.

    UserListView = Backbone.View.extend({
      attach: function(){
        this.el = $("#user-list");
        this.$("li").each(function(index){
          var userEl = $(this);
          var id = userEl.attr("data-id");
          var user = this.collection.get(id);
          new UserView({
            model: user,
            el: userEl
          });
        });
      }
    });
    
    UserView = Backbone.View.extend({
      initialize: function(){
        this.model.bind("change:name", this.updateName, this);
      },
    
      updateName: function(model, val){
        this.el.text(val);
      }
    });
    
    var userData = {...};
    var userList = new UserCollection(userData);
    var userListView = new UserListView({collection: userList});
    userListView.attach();
    

    在这个例子中,UserListView 将遍历所有的

  • 标签,并为每个标签附加一个具有正确模型的视图对象.它为模型的名称更改事件设置一个事件处理程序,并在发生更改时更新元素的显示文本.

    In this example, the UserListView will loop through all of the <li> tags and attach a view object with the correct model for each one. it sets up an event handler for the model's name change event and updates the displayed text of the element when a change occurs.

    这种获取服务器呈现的 html 并让我的 JavaScript 接管并运行它的过程是一种很好的方式来推动 SEO、辅助功能和 pushState 支持.

    This kind of process, to take the html that the server rendered and have my JavaScript take over and run it, is a great way to get things rolling for SEO, Accessibility, and pushState support.

    希望有所帮助.

    这篇关于“单页"JS 网站和 SEO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆