Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境 ( Runtime Environment ), 近年很是流行.

它同样可以用来搭建 Web 应用程序服务器端, 关于 Node.js 相较于其它技术的优劣, 本文不安利. 此处我们只讨论如何安装 Node.js 环境, 同时做个小例子以演示如何使用 Node.js 开发 Web 应用程序.

1. 安装 Node.js

参见 Node.js 环境安装

2. 创建项目

所谓项目, 其实就是一个文件夹, 里面装了相关的文件而已.

所以, 你可以在你喜欢的任意位置, 新建一个文件夹 ( 本文创建的文件夹名为 node_example ).

建议不要使用带中文路径的文件夹, 虽然我不确定会不会出问题, 但经验告诉我, No Zuo Zo Die ~

2.1 初始化项目

在控制台中进入刚建好的文件夹 ( node_example )

执行 npm init 初始化项目, 一路回车, 直到再次回到命令提示符, 如下图:

npm-init

OK, 项目初始化完成后, 将生成一个名为 package.json 的文件, 里面记录了关于项目的信息, 它对 Node.js 项目来说很重要! 未来对项目的一些配置均会记录在这个文件里.

上述过程其实是 npm 在初始化过程中问了一些关于你项目信息的问题, 一路回车就是告诉 npm 使用默认值就行, 别废话! 初始化完成后, 你可以直接打开 package.json 去修改就行.

2.2 创建程序入口文件

在 node_example 文件夹中新建一个名为 index.js 的文件, 敲入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
// 引入 Node.js 的 http 模块
const http = require('http');

// 创建Web服务
http.createServer( function(req, res) {
// 在回应头中写入200状态码, 告诉浏览器一切正常
// Content-Type ... 告诉浏览器给你的东西是"普通文本", 使用的是 uft-8 字符集
res.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});

// 在回应流中写入"你好呀!", 同时结束响应流程
res.end('你好呀!');
}).listen(9000); // 监听9000端口

注释都写满了, 就不过多解释了…

2.3 启动项目

在控制台中进入项目文件夹 ( node_example ), 输入命令 node index.js, 回车即可启动程序, 如下图.

控制台执行 node index.js 后若一切正常则不会有什么反应, 只有个光标忽闪忽闪的…

可以按 Ctrl + C 停止程序. ( 现在暂时别瞎按, 下面还要测试呢… )

打开浏览器, 在地址栏输入 http://localhost:9000

怎么样, 是不是看到如下图所示的页面了?

这回开心了吧~

如果你打开页面看到的是乱码, 别慌!

看下 2.2 节 index.js 代码的第 8 行, 这里告诉了浏览器我们使用的是 utf-8 字符集, 但有可能你使用的编辑器在保存你的代码时使用的是非 utf-8 字符集编码, 这样浏览器显示时就会出现乱码!

怎么办呢? 你可以用 Windows 系统自带的 “记事本” 程序打开 index.js, 打开菜单: 文件 → 另存为… , 在弹出的 “另存为” 窗口中选择编码为 “UFT-8”, 同样以 index.js 文件名替换保存即可.

其实, 到此为此, 我们并没有使用到除 Node.js 提供的 API 之外的别的东东, 所以… 2.1 节的初始化过程是可以省去的, 哈哈~

在实际的项目中, 如果仅使用 Node.js, 不依赖其它第 3 方框架来开发一个网站是比较麻烦的.

下面我们使用一个较常用的框架: Express, 开始吧~

3. 使用 Express

3.1 安装 Express

在控制台中执行 npm install express --save

1
D:\node_example> npm install express --save

安装过程会自动到国外的网站下载资源, 所以… 你懂的… 相当漫长的等待… 还有可能会失败 Orz~

如果实在忍受不了, 或直接安装失败, 可以考虑使用淘宝 npm 镜像站点. 控制台依次执行如下两行命令后再次尝试 npm install …

1
2
npm config set registry http://registry.npm.taobao.org/
yarn config set registry http://registry.npm.taobao.org/

安装完成后, 项目文件夹下会多出一个 node_modules 文件夹, 里面放了 Express 的东东.

另外, package.json 文件中还会多出点东西, 自己找找看吧!

项目文件夹下还会多出一个名为 package-lock.json 的文件, 它主要用来 “锁住” 依赖库的版本.

3.2 创建程序入口文件

在 node_example 文件夹中新建一个名为 index2.js 的文件, 敲入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express');       // 引入 express 框架
const app = express(); // 初始化 express
const port = 9001; // 使用9001端口, 避免和第2节的程序冲突

// 注册程序入口
// '/' 表示浏览器地址栏应输入 http://localhost:9001/
app.get('/', function(req, resp) {
resp.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});
resp.end("你好呀!");
});

// 启动程序, 监听9000端口
app.listen(port, function() { // 启动成功的回调函数
console.log('启动成功! 快试试吧~ http://localhost:' + port + '/');
});

是不是和 2.2 节代码也差不多? 自己琢磨一下呗~

3.3 托管静态文件

项目文件夹 ( node_example ) 下新建一个文件, 名为 public, 在 public 文件夹中新建一个名为 hehe.html 的文件, 敲入如下代码:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HeHe</title>
</head>
<body>
呵呵, 我是一个静态页面!
</body>
</html>

重新打开 3.2 节的 index2.js 文件, 在第 4 行的位置插入如下代码, 保存:

1
2
// 告诉 express, public 文件夹下有静态文件哦
app.use(express.static('public'));

3.4 启动项目

在控制台中进入项目文件夹 ( node_example ), 输入命令 node index2.js, 回车即可启动程序. ( 注意是 index2.js 哦 ~ )

打开浏览器

http://localhost:9001/ 是不是已经看到效果了?

http://localhost:9001/hehe.html 可以看到3.3节那个静态页面.

懒, 就不截图了!

3.5 获取前端传来的数据

如果你已经被我忽悠了开始尝试使用 Node.js + Express 做 Web 应用程序开发了, 那么本节内容是送给你的小礼物 ~

使用 Express 框架时, 有 3 种传递参数的方式: query (get), body (post), params (named route parameter)

直接给个图吧, 慢慢看 ~

Express传参

参考文献

https://www.expressjs.com.cn/4x/api.html#req.query

https://www.expressjs.com.cn/4x/api.html#req.body

https://www.expressjs.com.cn/4x/api.html#req.params

4 综合示例

还是不放心, 再附赠一个综合示例吧, 完整演示一遍… 本例中使用 Express + Axios. 演示了以不同的方式在前后端之间如何传递参数.

让我们从零开始~

  1. 新建文件夹 node-web-example

  2. 打开控制台, 进入 node-web-example 文件夹

  3. 初始化项目npm init -y

  4. 安装express npm i express --save

  5. 项目根目录下, 创建 public 文件夹 (前端程序放这里面), 并在 public 下新建 index.html

  6. 项目根目录下, 创建 index.js 文件 (服务端入口)

  7. 分别将如下代码放入上述两个文件. 最后, 控制台中执行 node index.js启动程序… 试一下啦~

/public/index.html (客户端页面)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Express + Axios</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function ajaxRequest() {
// 服务端以 req.body.user 方式接收参数
// axios.post 默认使用JSON, 服务端需要 app.use(express.json())
axios.post('/hello', {
user: 'chen'
}).then(function(res){
console.log(res.data)
})
}

function comboRequest() {
axios.post('/comboRequest/张三?age=18', {
info: {
name: 'zhang',
height: '178cm'
}
}).then(function(res) {
console.log(res.data)
})
}
</script>
</head>
<body>
<a href="/hello?user=wang">GET (req.query.user)</a>
<br/>
<a href="/hello/zhang">GET (req.param.user)</a>
<br/>
<!-- 表单以POST方式提交 -->
<form action="/hello" method="post">
user: <input type="text" name="user" value="wang"/>
<button type="submit">Submit</button>
</form>
<br/>
<button onclick="ajaxRequest()">AjaxRequest</button>
<button onclick="comboRequest()">ComboRequest</button>
</body>
</html>
/index.js (服务端)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const express = require('express');       // 引入 express 框架
const app = express(); // 初始化 express
const port = 9000; // 使用9000端口

app.use(express.static('public'))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())

// GET, 通过query传递参数
app.get('/hello', function(req, res) {
console.log('req.query.user =>', req.query.user)
res.end('Hello ' + req.query.user)
})

// GET, 通过params (named route parameter)传递参数
app.get('/hello/:user', function(req, res) {
console.log('req.params.user =>', req.params.user)
res.end('Hello ' + req.params.user)
})

// POST, 通过body传递参数
app.post('/hello', function(req, res) {
console.log('req.body.user =>', req.body.user)
res.end('Hello ' + req.body.user)
})


// POST, 3 种传递参数的方式组合演示: query (get), body (post), params (named route parameter)
app.post('/comboRequest/:name', function(req, res) {
console.log('req.params.name =>', req.params.name)
console.log('req.query.age =>', req.query.age)
console.log('req.body.info =>', req.body.info)
res.json({
params: req.params.name,
query: req.query.name,
info: req.body.info
})
})

// 启动程序
app.listen(port, function (){
// 启动成功的回调
console.log('启动成功! 快试试吧~ http://localhost:' + port + '/');
});

使用 Node.js + Express 进行小型 Web 项目的开发确实是一个不错的选择, Node.js 世界丰富的第 3 方库, 不失灵活性的同时也带来也不少便利.

本文的介绍仅是抛砖引玉, 如果感兴趣, 或想在自己的项目中实践, 那么官方文档可以通读一下.

除 Express 之外, 还有其它的 Node.js 环境下的 Web 开发框架, 例如: KOA, Egg …

Egg 是阿里在 KOA 基础上搞出来的框架, 用下来感觉不错, 可以学习学习: https://eggjs.org/zh-cn/tutorials/index.html