第一章 初识opa
本章,你将初识opa。你将学习如何安装Opa,编写opa程序以及熟悉Opa开发周期中的各个步骤。
安装opa
需要你预先从opa网站(http://opalang.org/)下载适合你的系统架构的安装包。本书编写之际,各种主流平台的安装包都已准备好,包括:Mac OS X, Windows, Linux (generic, Ubuntu, and Fedora), and FreeBSD。这些安装包大都需要64位系统,也有一些针对32位系统的安装包。
在苹果操作系统上,需要同时安装苹果的X-code命令行工具。
作为一种选择,也可以使用opa的源代码进行编译从而安装Opa,但强烈建议使用已经编译好的安装包。
一旦Opa安装完毕,可以通过打开终端输入如下命令来校验Opa安装的正确性:
Tokyo:~ henri$ opa --version
Opa compiler (c) MLstate -- version 1.0.7 -- build 4040
命令会显示出Opa的版本号及构建号,接着会检查Opa的运行依赖库是否完整,如有必要(依赖库不完整)会给出提示信息并引导你去完善那些缺失部分的安装。
安装Nodejs
Opa使用Node.js来执行服务器端的Javascript代码。可通过Node.js网站(http://nodejs.org/)下载安装。然后在你的终端输入如下命令:
Tokyo:~ henri$ npm install -g ursa formidable
-g参数代表global(全局),意思是将node模块安装在node程序易于发现的场所。
自动安装MongoDB
当你在服务器端运行Opa程序时MongoDB会被自动安装。
你可以在https:// github.com/MLstate/opalang/wiki/Getting-started 找到最新的在线安装指令。
我们的第一个程序
在本小节你将编写并运行你的第一个Opa程序。你将学习代码的实际含义,如何构筑你的应用以及理解应用底层是如何运作的。
编写和运行代码
你可以使用文本编辑器来编写Opa代码,任何文本编辑器都行。不过建议使用Opa推荐的编辑器,包括:
•Sublime Text2
•Emacs
•Vim
•Eclipse
请查看Opa的官方最新文档(https://github.com/MLstate/opalang/wiki/Getting-started#wiki-ide)以明了解如何设置你的首选编辑器。
现在,打开你的编辑器创建一个名称为hello.opa的文件,其内容如下:
Server.start(Server.http,
{ title: "Hello, world",
page: function() { <h1>Hello, world</h1> }
}
)
这是个非常简单的应用程序,仅仅显示静态的Hello, world文字信息,通过在终端输入如下命令来编译它:
Tokyo:~ henri$ opa hello.opa --
Http serving on http://localhost:8080
稍后我们会回来讨论代码是如何运作的,现在,请打开浏览器,输入地址http://localhost:8080,你会看到类似下图的网页显示:
localhost:8080是啥意思
通常,你打开浏览器输入类似facebook.com这样的文字,这样的文字称之为URL(统一资源定位符),该URL允许你的浏览器查找网络资源,类似于通过街道名称来查找某栋建筑。前面的localhost是访问本地机器(本地电脑)的标准方式。换成相应IP地址127.0.0.1或机器名称也可达到同等效果。
地址中冒号后边的8080是端口号。域名用来定位站点,端口则用来辨别站点中不同的服务。如果我们把URL看做街道地址,那么域名则好比国家,城市及街道(译者注:完整街道地址应包括国家名城市名及街道名),而端口则好比房屋/公寓门牌号。web服务的默认端口号是80。不过,应用程序若想使用1024以下的端口号通常需要系统管理员权限,因此Opa选择了8080来作为默认端口。在执行应用程序时可通过--port参数修改端口号,如下例:
Tokyo:~ henri$ ./hello.js --port 2012
最后,URL中可以包含路径,比如在http://example.com/this/andthat.html中的/this/andthat.html就是路径。域名和路径是被分别处理的。域名被用来定位运行服务的盒子(译者注:意指服务器硬件),为了成功定位,浏览器需要向DNS服务器发起请求而后者会将名称转换成服务IP。DNS是分发众多客户端请求到众多服务器的第一种被运用的技术。路径被用来定位具体服务资源。在(互联网)最开始的起步阶段,路径被用来定位服务器上的文件-可能是图片或者脚本之类的静态资源。但是,在诸如Opa这样的现代框架中,绝大部分资源是虚拟的。
代码啥意思
让我们解密一下这四行(译者注:原文有误,应为5行或干货3行)代码:
Server.start(Server.http,
{ title: "Hello, world",
page: function() { <h1>Hello, world</h1> }
}
)
Server.start是Opa程序的入口点,就像Java或C的main一样用来启动web应用服务。它需要两个参数:服务器配置和决定服务器如何处理输入请求的定义。第二个参数可以以多种形式存在,在第三章我们会详细讨论。
此处我们使用了一个包含单一页面的变量来创建一个简单的应用程序(译者注:这种在Opa中直接写页面内容的方式类似于Java中的匿名类,在后续章节中会陆续介绍其它方式,比如可以单独写成一个函数,甚至单独写在一个文件中)。该变量被定义成一个包含两个字字段的档案对象:title和page,分别表示页面标题和页面内容。如果你熟悉Javascript,你会注意到Opa借用了同样的{ field1: val1, ... fieldN: valN } 语法来描述档案。在“档案”一节中你会学习关于档案的更多只知识。
title字段是字符串类型,page则是一个(匿名内部)函数,该函数没有参数直接返回(X)HTML 内容。
HTML语言是Opa世界的一等原住民,它在Opa中被预先定义好了,并且支持通过常用语法使其被使用。Opa支持所有的HTML版本(包括HTML5)。在第五章你将学习更多的HTML5特性。
程序运行时究竟发生了什么
当你通过调用opa hello.opa -- 来运行你的应用程序是究竟发生了什么事?实际上,你执行了两步操作:
-
将你所写的代码转换(或编译)成了一个可运行的应用程序。
-
调用运行期环境并执行该应用程序。
让我们近距离仔细观察一下步骤1,Opa是一个由2部分组成的JavaScript框架:一个库和一个编译器。 库是你在程序中使用的预先实现好的各种功能的集合,编译器则是一个怪异和复杂的怪兽,它会执行好几步:
-
编译器读入你所写的代码(那称之为语法解析)并检查代码语法是否正确,比如,如果你忘记关闭一个圆括号这一步会给出解析错误提示信息。
-
一旦语法解析成功,编译器会进行更深层次的检查,检查整个程序的一致性看你的代码是否存在一些幼稚的错误,这一步称之为类型检查,在第二章你会进行详细的学习。
-
一旦类型检查成功,编译器会标志出哪些代码在服务器端运行,哪些代码在数据库端运行,哪些代码在客户端运行。这一步称之为切片处理而这一处理过程也是Opa所提供的众多独一无二特性之一。
-
编译器计算数据模型并生成所有的数据库请求。
-
编译器将所有标志为客户端运行的代码翻译成Javascript。
-
最后,通过Node.js后台将所有标志为服务器端运行的代码翻译成Javascript代码并且嵌入到客户端资源中以便服务器可以把它们发送到任意的客户端或网络链接。
当然,仅仅开发应用程序并不需要精确通晓Opa编译器是如何工作的。好些个开发环境(或集成开发环境)已经集成项目构建能力,编译只需在键盘上轻轻一按,分分钟搞定。
本书中我们将向你展示如何使用命令行来进行Opa操作,原因也简单,命令行可以工作在所有的平台上,而集成开发环境底层也还是用这些个命令行,只不过在中间加了个图形接口(人机交互界面),仅此而已。
编译过程中发生任何问题编译器都会以适当的错误信息或警告信息提示你,若没有任何问题则生成一个可执行的Javascript文件,本例中将会生成hello.js文件。
关于Opa运行期的细节
Opa编译器使用2种技术来生成一个标准的Javascript应用程序:
-
Node.js框架
-
MongoDB数据库
Opa编译时时会检查其自身运行所需运行环境,即Opa的系统环境,因此, 现阶段这两项(Node.js和MongoDB)需要先准备好,如果还没准备好,请参见“安装Opa”。也可以仅编译而不运行,如下方式:
Tokyo:~ henri$ opa file.opa
把两个减号去掉即可。看看当前目录结构你会发现Opa在编译过程中创建了一个文件和一个文件夹(译者注:根据Opa版本不同此处会有细微差异)。
Tokyo:~ henri$ ls
_build program.js program.opa
program.js文件就是前述所说的可执行的Javascript文件,可用如下方式运行起来
Tokyo:~ henri$ ./program.js
Http serving on http://localhost:8080
_build文件夹包含应用程序运行期间所需资源。生成的应用程序是标准的Node.js/MongoDB应用,因此完全可以在发布到云端。如果某些Node.js包缺失,Opa会在运行时提醒并指引你如何安装它们。
Tokyo:~ henri$ opa file.opa--
> some node modules are missing, please run: npm install mongodb formidable nodemailer imap
真实编码场景
在我们简短的“Hello, World” 应用程序中,所有的代码都在一个hello.opa文件中。而在真实的编码场景中,你会想要将不同代码分别组织到不同文件中。
比如,流行的MVC (模型-视图-控制器) 方法是将一个应用程序分成3部分:模型用来处理数据;视图用来将数据呈现给最终用户;控制器用来同步(连接)模型和视图。
幸运的是Opa提供了一种成为“脚手架”的机制,通过它我们可以很方便的创建一个空的MVC应用。
Tokyo:~ henri$ opa create myapp
OpaCreate: Generating myapp/Makefile...
OpaCreate: Generating myapp/Makefile.common...
OpaCreate: Generating myapp/opa.conf...
OpaCreate: Generating myapp/resources/css/style.css...
OpaCreate: Generating myapp/src/controller/main.opa...
OpaCreate: Generating myapp/src/model/data.opa...
OpaCreate: Generating myapp/src/view/page.opa...
现在你可以输入下面命令来编译并运行一个名为“myapp” 的应用。
$ cd myapp
$ make run
也可查看生成的相应代码(译者注:根据Opa版本不同此处会有细微差异)
Tokyo:~ henri$ ls -R src
controller model view
src/controller:
main.opa
src/model:
data.opa
src/view:
page.opa
详细的MVC代码我们会在第二章讨论,到目前为止,重要的是知道下面几点:
-
控制器main.opa文件是应用的主要核心文件,类似于hello.opa
-
模型data.opa文件基本是个空文件(注释不算)
-
视图view.opa文件里面是静态HTML内容
对本文任何意见,建议请直接与译者联系。
译者微信号:liu_matureshadow