读 《node.js实战2.0》,进行学习记录总结。
Node Web 程序是什么
了解 Node Web 程序的结构
典型的Node Web 程序是由下面几部分组成的:
- package.json : 一个包含依赖项列表和运行这个程序的命令的文件;
- public:静态资源文件
- node_modules:项目的依赖项
- 程序代码:
- app.js 或 index.js :设置程序的代码
- models:数据库模型
- views:渲染页面的模板
- controllers或 routes :HTTP 请求处理器
- middleware: 中间件组件
开始一个新的 Web 程序
创建一个新目录,然后运行:
1 | mkdir later |
安装 express
1 | npm i express -S |
可以在 package.json,看到express 已经被安装上去了
1 | "dependencies": { |
如果要卸载可以使用下面的命令:
1 | npm rm express -S |
创建一个简单的服务器
1 | // index.js |
新增 package.json 文件的 npm 脚本
1 | "scripts": { |
运行程序:
1 | npm start |
可以看到:
跟其他平台比较
如果在 PHP 实现上面的程序,代码如下:
1 | echo '<p>Hello World</p>'; |
只有一行,并且一看就明白,那么这个更加复杂的 Node示例有什么优点呢?二者是编程范
式上的区别:用 PHP,程序是页面;Node:程序是服务器,这个Node 示例可以完全控制请求和响应,不用配置服务器就可以做所有事情,如果要用 HTTP 压缩或 URL 转发,可以将这些功能作为程序的逻辑来实现。不需要把 HTTP 程序和逻辑分开,它们是程序的一部分。
搭建一个 RESTful Web 服务
RESTful 服务可以方便创建和保存文件,将杂乱的 Web 页面变得整洁。
设计 RESTful 服务要想好操作,映射到 Express 路由上面。此例子,需要保存文章、获取文章、获取包含所有文章的列表和删除不再需要的文章这几个功能。分别对应下面的路由:
- POST /articles:创建新文章
- GET /articles/:id :获取指定文章
- GET /articles:获取所有文章
- DELETE /articles/:id :删除指定文章
简单的 Express 程序实现了这些路由,现在使用 JavaScript 来存储文章
1 | // index.js |
Express 能自动将数组转换成 JSON 响应。
创建文章,处理 POST 请求需要消息体解析。安装解析器
1 | npm i -S body-parser |
添加消息解析器:
1 | // 消息解析器 |
添加数据库
就往 Node程序中添加数据库而言,并没有一定之规,但一般会涉及下面几个步骤。
(1) 决定想要用的数据库系统。
(2) 在 npm上看看那些实现了数据库驱动或对象-关系映射(ORM)的热门模块。
(3) 用 npm –save 将模块添加到项目中。
(4) 创建模型,封装数据库访问 API。
(5) 把这些模型添加到 Express路由中。
创建数据库之前,添加路由处理代码,程序汇中的 HTTP 路由处理会向模型发起一个简单的调用
1 | app.get('/articles', (req, res, next) => { |
这个 HTTP 路由是用来获取所有文章的,所以对应的模型方法应该类似于 Article.all 。这要取决于数据库 API,一般来说应该是 Article.find({}, cb) 和 Article.fetchAll().then(cb) ,其中的 cb 是回调(callback)的缩写.
上例子中选择了 SQLite数据库,还有热门的 sqlite3 模块。SQLite 是进程内数据库,
所以很方便:你不需要在系统上安装一个后台运行的数据库。你添加的所有数据都会写到一个文件里,也就是说程序停掉后再起来时数据还在,所以非常适合入门学习时用。
制作自己的模型 API
文章应该能被创建、获取、删除,所以模型 Articles 应该提供一下的方法:
- Article.all(cb):返回文章
- Article.find(id,cd):给定ID,找到对应的文章
- Article.create({title,content},cb):创建一篇有标题和内容的文章
- Article.delete(id,cb):根据ID删除文章
这些都可以用sqlite3模块实现。有了这个模块,我们可以用 db.all 获取多行数据,用db.get获取一行数据。不过先要有数据库连接。
安装 sqlite3:
1 | npm i -S sqlite3 |
接着在 ds.js 中实现代码完成上述功能。
1 | const sqlite3 = require('sqlite3'); |
上面例子中创建了一个 名为 Article 的对象,它可以用标准的 SQL 和 sqlite3 创建、获取和删除数据。首先用 sqlite3.Database 打开一个数据库文件,然后创建表的 articles 。这里用到了 SQL 语法 IF NOT EXISTS ,以防一不小心重新运行了代码删除了前面的表重新创建一个。
数据库和表准备好了之后,就可以进行查询。用 sqlite3 的 all 方法可以获取的所有文章。用带问号的查询语法提供具体值的方法可以获取指定文章,sqlite3 会把 ID 插入到查询语句中,最后用 run 方法插入和删除数据。
基本的数据库功能已经实现了,接着我们把它添加到 HTTP 路由中。下面这段代码添加了所有方法,除了 POST 。(因为需要用到 readability模块,但你还没有装好,所以要单独处理。)
1 | const express = require('express'); |
db.js 文件放在同个目录,Node 会加载那个模块,然后用它获取所有文章,查找特定文章和删除一篇文章。
最后一件事情是实现创建文章的功能。还要用 readability 算法处理它们。
让文章可读并存起来
RSETful API 已经搭建好了,数据也可以持续化到数据库中,接下来该写代码把网页转换成简化版的 “阅读视图”。不过我们不用自己实现, npm 中有这样的模块。
在 npm上搜索 readability 会找到很多模块。我们试一下 node-readability:
1 | npm i node-readability -S |
这个模块提供了一个异步函数,可以下载指定 URL 页面并将 HTML 转换成简版。
1 | const read = require('node-readability'); |
还可以和数据库类结合起来,用 Article.create 方法保存文章:
1 | read(url,(err,result)=>{ |
打开 index.js 添加新的 app.post 路由处理器,用上面的方法方法实现下载和保存文章的功能。
1 | const read = require('node-readability'); |
上面代码中,先从 POST 消息体中得到 URL ,然后用 node-readability 模块获取这个URL 指向的页面,用模型类 Article 保存文章,如果有错误,将处理权交给 express 的中间件栈;否则,将 JSON 格式的文章发送给客户端。
添加用户界面
给 Express 项目添加界面需要做的几件事情,首先是使用模块引擎。
支持多种格式
基本做法是用 Express 的 res.format 方法,它可以根据请求发送响应格式的响应。它的用法如下,提供一个包含格式已经对应的响应函数的列表:
1 | res.format({ |
这段代码中, res.render 会渲染 view 文件夹下的 articles.ejs。但这需要安装模板引擎并创建相应的模板。
渲染引擎
模板引擎有很多,EJS属于简单易学的那种。安装:
1 | npm i ejs -S |
res.render 可以渲染 EJS 格式 的 HTML 文件。在 view 文件夹中创建 articles.ejs
1 | <% include head %> |
页眉和页脚模块
1 | <!-- 页眉 --> |
用npm管理客户端依赖项
模块搞定之后,就是样式了。安装 bootstrap
1 | npm install bootstrap --save |
然后在 node_modules/boostrap 里面会看到源码,在 dist/css 里面有css文件,要让服务器响应静态文件请求才可以使用这些文件。
Express 自带了 一个名为 express.static 中间件,可以给浏览器发送客户端 JavaScript、图片和CSS 文件。只要将它指向包含这些文件的目录,浏览器就可以访问到这些文件了。
1 | // 加载 css文件 |
接着在头模块中引入
1 | <link rel="stylesheet" href="/css/bootstrap.css"> |
这只是 Bootstrap的 CSS。它还有很多文件,包括图标、字体以及 jQuery插件。你可以往项目里添加更多文件,或者用工具把它们打包成一个文件,让浏览器更容易加载。
总结
- 用 npm init 和 Express 可以快速搭建出一个 Node Web 应用程序
- npm install 是安装依赖项的命令
- 可以用 Express 制作带有 RESTful API 的 Web 程序
- 选择适合的数据库系统和数据库模板根据个人需求
- 对于小项目来说,SQLite 很好用
- 在 Express 中用EJS渲染模板很容易
- Express 支持很多模块引擎,包括Pug和Mustache