1.3 开发一个简单的微件
在本章前两小节中我们探讨了一些第三方JavaScript的流行用法。你已经了解了在开发微件、数据收集、作为客户端Web服务的API封装等方面是如何运用到它的。希望这能够给你一些启发,当你设计自己的第三方应用程序时候能够了解哪些功能是能够实现的。
现在,你已经看过了一些现实中的实例,是时候开发一些自己的东西了。让我们先从相对简单的入手:一个极其简单的嵌入式微件。
假设你在运行一个提供当地最新天气信息的网站。一般而言,用户直接访问你的网站是为了获得最新的天气消息。但是为了使用户更广,你决定更进一步,让用户可以在你的网站之外访问你的数据。你可以通过提供一个可嵌入的微件服务做到这一点,如图1.7所示。你需要向那些有兴趣通过引入第三方脚本即可为自己的用户提供本地天气信息的网站发布者推广这个微件。
幸运的是,你已经找到了一个对此兴致盎然的网站发布者,而且他们已经开始试着使用你的微件了。为了让他们能够使用,你需要给他们提供HTML代码片段,从而在他们的Web页面上加载天气微件。网站发布者需要将代码片段粘贴到他们的HTML源代码中想要展现微件的位置。代码片段本身很简单:即一个标签指明weathernearby.com所在服务器上第三方JavaScript的路径:
你会注意到脚本的URL中包含了一个zip参数。通过这个参数你就可以识别需要渲染什么位置的天气信息。
此时,当浏览器加载发布者的Web页面时,遇到这个标签就会向weathernearby.com的服务器请求widget.js脚本文件。当widget.js下载完毕并且执行后,就会在发布者的页面上渲染出天气微件。不管怎么说,这就是我们想要达到的效果。
要做到这些,widget.js需要有权限访问公司的天气数据。这些数据可以直接发布到脚本文件中,但是考虑到美国大约有43 000个邮政编码,这样一来,一个请求中会有太多的数据。除非用户从瑞典或者韩国访问,因为这两个国家100Mbit/s的传输速度是常态。在通常情况下,微件需要请求天气数据可以通过使用AJAX来完成。为了简单起见,我们使用另一种不同的方式:服务端生成脚本。
1.3.1 服务端生成脚本
与提供一个包含微件代码的静态JavaScript文件不同,你需要写一个服务端应用为每个请求生成一个JavaScript文件,如图1.8所示。因为服务器能够访问天气信息的数据库,它可以将所请求的天气数据插入到输出的JavaScript文件中。这就意味着,在发布者页面上渲染天气微件的所有代码和需要的数据都包含在JavaScript中,而无需发起任何额外的请求。
这个服务端应用可以用任何编程语言或者能够在服务器环境运行的平台,像Ruby、PHP、Java、ASP.NET——甚至服务端JavaScript,这些都是很不错的选择。本例中,我们选用很受欢迎的脚本语言Python来进行演示。本例用到了Flask,一个基于Python的小型框架,用于构建小型Web应用。如果你并不熟悉Python,也不用担心——代码很容易理解。如果你想自己尝试程序清单1.5中的例子,可以参照配套的程序源码,程序源码中同时也包含了安装Python(2.x)和Flask的介绍。
为什么选用Python
本书中一小部分服务端的例子都是使用Python语言。我们选用这种编程语言完全是因为偏爱:它是我们在Disqus每天都在使用的语言,并且我们对它最熟悉。倘若你不知道如何使用Python也没关系。本书首先是一本关于JavaScript的书,服务端的例子可以很容易的使用其他语言代替。
当这个服务端脚本启动后,一个请求的标签将返回如下JavaScript代码。从而渲染出你在本节开头看到的示例微件,如图1.7所示。同时,注意这些代码是Python应用产生并且对于浏览器请求而言是完全透明的。
现在看来,这是一个极其简单的例子,并不是开玩笑。这个毫无样式输出的天气微件几乎没有为用户提供交互界面。看似非常糟糕,而且可能会将你刚起步的公司陷入困境。但是它能够工作,而且展示了发布者网站同第三方代码之间的交互。
这里提及的一些技术,像使用document.write和服务端的Python,都不是唯一生成微件的方式。不要皱眉,我们稍后会解释原因。在后边的章节中,我们将探讨更好的替代方案,并介绍更为复杂的功能,如样式表,通过AJAX进行服务端通信以及用户间会话。
1.3.2 通过iframe分发微件
如果你对于Web开发相当有经验,可能会有这样的想法,“是不是通过iframe分发这个微件更容易?”乍一看似乎如此,但是有一些潜在的差异使得第三方脚本成为了更好的实现选择。为了知其所以然,首先我们看一下如何通过iframe重新创建之前的微件示例。
iframe是块级HTML元素,用来从URL嵌入外部内容。如果你对它并不熟悉也能够完全通过一个iframe元素很容易的重新实现天气微件示例,如下。
你会注意到src属性改变了:不再指向一个JavaScript文件,而是指向一个HTML文档。这一次你的服务器将返回一个完整的HTML文档,包含了微件的标记,完全避免了使用JavaScript。你也会注意到微件的尺寸作为iframe的style属性的一部分。iframe元素并不会扩大以适应其内容,因此需要为iframe设定明确的尺寸。
像这样使用iframe将产生同JavaScript示例相同的输出。那为什么要使用JavaScript代替iframe呢?有很多的原因,其中大部分原因都围绕iframe的特性:通过iframe加载的外部内容不能被父页面访问(发布者的页面),反之亦然。
灵活性:如果你希望改变微件的尺寸,就没有那么幸运了。因为iframe的尺寸是在父页面中iframe标签中指定的,而且这些属性不能被iframe加载的内容更改,因此没有办法动态的改变微件的尺寸。
美学:微件的外观需要完全独立于父页面的样式。微件将不能继承基础的样式,例如字体种类、字体大小或颜色等。
交互:微件需要访问或者修改发布者页面的DOM吗?发布者是否需要在微件的内容上附加一些交互?是否会有多个微件实例存在并且相互通信的情况呢?这些通过静态iframe都不可能做到。
报表:浏览器用户是否真能看到微件?在看到它之前,他们在页面上耗费了多长时间?收集这些和其他有价值的数据都需要在发布者页面上运行JavaScript。
这些只是一些简单的例子,但是你或许能看到一种趋势。iframe或许是天气微件示例最简单的分发方式,但是这么做你将失去第三方JavaScript提供的众多引人注目的能力。但是,不要让它改变了你对iframe的看法。它们是第三方JavaScript开发者工具集中一个宝贵的资产,在本书不同的任务中,我们都会频繁地用到它们。