Simple App
实验目的
- 学会使用 Node 编写简单的前端应用。
操作步骤
(1)新建一个目录
$ mkdir simple-app-demo
$ cd simple-app-demo
(2)在该目录下,新建一个package.json
文件。
$ npm init -y
package.json
是项目的配置文件。
(3)安装jquery
和webpack
这两个模块。
$ npm install -S jquery
$ npm install -S webpack
打开package.json
文件,会发现jquery
和webpack
都加入了dependencies
字段,并且带有版本号。
(4)在项目根目录下,新建一个网页文件index.html
。
<html>
<body>
<h1>Hello World</h1>
<script src="bundle.js"></script>
</body>
</html>
(5)在项目根目录下,新建一个脚本文件app.js
。
const $ = require("jquery");
$("h1").css({ color: "red"});
上面代码中,require
方法是 Node 特有的模块加载命令。
(6)打开package.json
,在scripts
字段里面,添加一行。
"scripts": {
"build": "webpack app.js bundle.js",
"test": "...."
},
(7) 在项目根目录下,执行下面的命令,将脚本打包。
$ npm run build
执行完成,可以发现项目根目录下,新生成了一个文件bundle.js
。
(8)浏览器打开index.html
,可以发现Hello World
变成了红色。
练习
- 修改样式,将标题变为蓝色,然后重新编译生成打包文件。
REST API
实验目的
- 熟悉 REST API 的基本用法
操作步骤
(1) 命令行进入rest-api-demo
目录,执行下面的命令。
$ npm install -S json-server
(2) 在项目根目录下,新建一个 JSON 文件db.json
。
{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}
(3) 打开package.json
,在scripts
字段添加一行。
"scripts": {
"server": "json-server db.json",
"test": "..."
},
(4) 命令行下执行下面的命令,启动服务。
$ npm run server
(5)打开 Chrome 浏览器的 Postman 应用。依次向http://127.0.0.1:3000/posts
、http://127.0.0.1:3000/posts/1
发出GET
请求,查看结果。
(6)向http://127.0.0.1:3000/comments
发出POST
请求。注意,数据体Body
要选择x-www-form-urlencoded
编码,然后依次添加下面两个字段。
body: "hello world"
postId: 1
发出该请求后,再向http://127.0.0.1:3000/comments
发出GET
请求,查看结果。
(7) 向http://127.0.0.1:3000/comments/2
发出PUT
请求,数据体Body
要选择x-www-form-urlencoded
编码,然后添加下面的字段。
body: "hello react"
发出该请求后,再向http://127.0.0.1:3000/comments
发出GET
请求,查看结果。
(8)向http://127.0.0.1:3000/comments/2
发出delete
请求。
发出该请求后,再向http://127.0.0.1:3000/comments
发出GET
请求,查看结果。
Express
实验目的
- 学会 Express 搭建 Web 应用的基本用法。
操作步骤
(1)进入demos/express-demo
目录,命令行执行下面的命令,安装依赖。
$ cd demos/express-demo
$ npm install
(2)打开app1.js
,尝试看懂这个脚本。
var express = require("express");
var app = express();
上面代码调用express
,生成一个 Web 应用的实例。
var router = express.Router();
router.get("/", function(req, res) {
res.send("<h1>Hello World</h1>");
});
app.use("/home", router);
上面代码新建了一个路由对象,该对象指定访问根路由(/
)时,返回Hello World
。然后,将该路由加载在/home
路径,也就是说,访问/home
会返回Hello World
。
router.get
方法的第二个参数是一个回调函数,当符合指定路由的请求进来,会被这个函数处理。该函数的两个参数,req
和res
都是Express 内置的对象,分别表示用户的请求和 Web 服务器的回应。res.send
方法就表示服务器回应所送出的内容。
var port = process.env.PORT || 8080;
app.listen(port);
console.log("Magic happens on port " + port);
上面代码指定了外部访问的端口,如果环境变量没有指定,则端口默认为8080
。最后两行是启动应用,并输出一行提示文字。
(3)在命令行下,启动这个应用。
$ node app1.js
浏览器访问localhost:8080/home
,看看是否输出Hello World
。
然后,命令行下按 Ctrl + C,退出这个进程。
(4)通过环境变量,自定义启动端口。
假定我们指定必须启动在7070
端口,命令行可以这样操作。
# Linux & Mac
$ PORT=7070 node app1.js
# windows
$ set PORT=7070
$ node app1.js
浏览器就可以访问localhost:7070/home
了。
然后,命令行下按 Ctrl + C,退出这个进程。
思考题:Node 应用能否直接在80
端口启动?
(5)打开app2.js
,查看新增的那个路由。
router.get("/:name", function(req, res) {
res.send("<h1>Hello " + req.params.name + "</h1>");
});
上面代码新增了一个路由,这个路由的路径是一个命名参数:name
,可以从req.params.name
拿到这个传入的参数。
在命令行下,启动这个应用。
$ node app2.js
浏览器访问localhost:8080/home/张三
,看看是否输出Hello 张三
。
然后,命令行下按 Ctrl + C,退出这个进程。
(6)打开app3.js
,先查看页面头部新增的两行代码。
var express = require("express");
var app = express();
// 新增代码...
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
// ...
上面代码中,body-parser
模块的作用,是对POST
、PUT
、DELETE
等 HTTP 方法的数据体进行解析。app.use
用来将这个模块加载到当前应用。有了这两句,就可以处理POST
、PUT
、DELETE
等请求了。
下面查看新增的那个路由。
router.post("/", function (req, res) {
var name = req.body.name;
res.json({message: "Hello " + name});
});
上面代码表示,如果收到了/
路径(实际上是/home
路径)的POST
请求,先从数据体拿到name
字段,然后返回一段 JSON 信息。
在命令行下,启动这个应用。
$ node app3.js
然后,在 Chrome 浏览器的 Postman 插件里面,向http://127.0.0.1:8080/home
发出一个POST
请求。数据体的编码方法设为x-www-form-urlencoded
,里面设置一个name
字段,值可以随便取,假定设为Alice
。也就是说,发出这样一个请求。
POST /home HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
name=Alice
如果一切正常,服务器会返回一段 JSON 信息。
{
"message": "Hello Alice"
}
(7)打开app4.js
,查看在所有路由之前新增的那个函数。
var router = express.Router();
// 新增的代码
router.use(function(req, res, next) {
console.log("Thers is a requesting.");
next();
});
router.get("/", function(req, res) {
// ...
router.use
的作用是加载一个函数。这个函数被称为中间件,作用是在请求被路由匹配之前,先进行一些处理。上面这个中间件起到 logging 的作用,每收到一个请求,就在命令行输出一条记录。请特别注意,这个函数内部的next()
,它代表下一个中间件,表示将处理过的请求传递给下一个中间件。这个例子只有一个中间件,就进入路由匹配处理(实际上,bodyparser
、router
本质都是中间件,整个 Express 的设计哲学就是不断对 HTTP 请求加工,然后返回一个 HTTP 回应)。
练习
请增加一个中间件,服务器每次收到用户请求,会在服务器的控制台打印出收到请求的时间。
URL 的查询字符串,比如
localhost:8080?name=Alice
里面的name
,可以用req.query.name
拿到。请修改一个路由,使之可以收到查询字符串,然后输出"Hello " + req.query.name
。