本教程是给nodejs和Expressjs的小白们写的。Expressjs是一个基于nodejs的开发框架,现在大热的MEAN站点开发技术栈,的E就是Expressjs。说到Expressjs就不能不说这个在nodejs界影响巨大的框架的作者TJ Holowaychuk。几乎三成以上的nodejs社区代码都是这位仁兄贡献的,甚至有人怀疑他不是一个人在战斗。。。但是,无论如何,要用nodejs写web站点都离不开他的拥有或参与的nodejs库。实在是一位值得膜拜的代码英雄。这位英雄酷爱摄影,这里是他的影展站点。
本来nodejs做站点很多都是用jade作为生成html页面的模板。这里为了简单,并且突出主要内容expressjs,就直接使用html页面了。
最开始莫过于是安装nodejs了。毕竟,expressjs是运行在nodejs之上的,没有nodejs什么都无从谈起。nodejs在这里下载。只需要下载并安装对应于你的系统的版本就可以。之后安装。
开发工具具体用什么,有很大的空间。本人比较喜爱使用Sublime。也有人使用Intellij的WebStorm,这个比较重型一些,但是也在某些地方方便很多。还有其他比较轻量级的Visual Code。都可以使用,看个人的爱好。
在正式开始编写代码以前,需要有一个结构良好的项目目录结构。这非常重要,如果你不知道运行什么功能的代码存放在什么地方,什么时候这个文件的什么方法会被调用到,那么你对项目的理解就非常的欠缺了。那么首先创建一个存放你的应用的文件夹,并跳转到这个目录下。
这里有一个项目的目录结构:
|__node_modules
|__routers
|__main.js
|__views
|__index.html
|__about.html
|__package.json
|__app.js
你可能会问,这些我都要创建吗?也是,也不是。接续往下读你就会清楚了。
在这个文件中会包含你expressjs应用的全部信息。比如,这个应用的名称、版本、描述等内容,项目不同这些也会有些不同。
这些内容中最重要的就是依赖项(dependencies)。这些依赖项是应用运行起来所不可或缺的。但是package.json文件并不用我们去手动创建。打开终端,并跳转到你刚刚为这个应用创建的目录下。运行命令:
$ npm init
命令中会跳出很多的需要你输入的东西。依次输入,或者对于我们的教程来说直接回车也可以。但是,有一点例外,在出现
entry point: (index.js)
的时候把文件名改为app.js,或者随便你喜欢的名字都可以。或者你觉得index.js也可以的话,就直接回车。但是我们在后面用到的这个文件都叫做app.js。
对于我们今天的主角expressjs来说,可以使用nodejs提供的包管理工具来完成安装。只需要一个命令就可以完成,非常的简单。
$ npm install express --save
命令之后打开package.json文件看看:
{
"name": "express-web-app",
"version": "1.0.0",
"description": "Just a blogging platform.",
"author": "uncle charlie",
"dependencies": {
"express": "^4.13.4"
}
}
注意:在填写名称的时候不能包含空白,比如“express web app”。即使是“express-web-app”或者“express_web_app”这样也是可以的。还有一点,在依赖项的版本号前面的那些特殊的符号除了^还有其他。我们来看看这些特殊符号的含义:
* “^” 是指匹配全部4.x.x的版本,一直到5.0.0(不包括)。
* “~” 是指匹配全部2.4.x的版本,一直到2.5.0(不包括)。
更多内容对于版本的指定,可以参考官网。
我们继续使用npm安装其他的依赖项,ejs和mysql。
$npm install mysql --save
和
$npm install ejs --save
最后等待全部的依赖项都安装完成。还有一种完全没有什么必要的安装依赖项的方法,就是在npm init命令生成package.json文件之后,自己编辑这个文件,添加依赖项。最后执行npm install命令。不过这样没有什么必要。npm才是管理依赖包的,我们去手动编辑package.json文件就违背了nodejs使用npm包管理工具的初衷。只有在项目下已经存在package.json文件,而对应的依赖项还没有下载到本地的情况下才直接使用npm install安装。
我们需要的依赖项都已经安装好了,也创建了package.json文件。现在就该正式的进入正题,创建一个Express的server来响应各种用户请求了。前文中在执行npm init命令的时候已经生成了app.js文件。现在打开这个文件。输入如下的代码:
var express = require("express");
var app = express();
var server = app.listen(5566, function(){
console.log("Server is running on http://localhost:5566");
});
在终端中执行命令node app.js。这里node后面跟你使用的文件的名称。在浏览器中输入地址http://localhost:5566并回车,你会发现已经可以访问这个server了,虽然还是一点小小的瑕疵。这个瑕疵主要是因为我们还没有在server里没有提供路由(router)的功能。
我们的server已经准备好了。现在我们就来处理路由(router)的问题。
var express = require("express");
var app = express();
// *
app.get('/', function(req, res){
res.send("Hello World!");
});
var server = app.listen(5566, function(){
console.log("Server is running on http://localhost:5566");
});
加星注释的那句就是我们添加的路由功能的代码。方法get
表明处理的是用户的GET请求。后面的function(req, res){res.send("Hello World!"}
输出响应的内容,这里是一个全世界最著名的计算机字符串“Hello World”。
用户的响应只是一个字符串是远远不够的,按照上文中介绍目录结构的时候提到的,给views目录添加文件index.html和about.html。并分别给这两个文件添加内容:
<html>
<head>
head>
<body>
<header>
<h3>HOMEh3>
header>
body>
html>
<html>
<head>
head>
<body>
<header>
<h3>ABOUTh3>
header>
body>
html>
添加的内容非常简单,只是为了区分是哪个页面被打开了。
如何显示这两个页面呢?这就回到刚刚我们讨论的问题上了,修改路由。
app.get('/', function(req, res){
res.render('index.html');
});
app.get('/about', function(req, res){
res.render('about.html');
});
用上面的代码替换掉最开始使用的示例路由代码,然后重新运行node app.js
命令。额……你会发现会报错。是的,以后这样的事情还会经常发生的。查看报错的内容:
Error: Cannot find module 'html'
at Function.Module._resolveFilename (module.js:337:15)
at Function.Module._load (module.js:287:25)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at new View (/Users/uncle_charlie/Documents/Dev/Test/js_test/js_server/node_modules/express/lib/view.js:78:30)
主要是因为没有对应的处理模块,所以无法正确的render渲染html文件。这时候就需要用到处理视图的模块ejs了。增加ejs的设置代码:
var express = require("express");
// 1
var ejs = require('ejs');
var app = express();
// 2
app.set('view engine', 'ejs');
// 3
app.engine('html', ejs.renderFile);
// 以下代码不动,这里省略……
上面的修改主要有:
1. 引入了ejs模块。
2. 设定应用的视图引擎(view engine)为ejs。
3. 设定在处理HTML文件的时候使用ejs来渲染文件。
在浏览器中输入地址http://localhost:5566/about你看到的就是ABOUT页面了。
看起来是so far so good了。但是这是不够的。对于产品级的Express应用来说会有很多的代码。其中只路由的部分的代码就会非常之多。对于后期添加或者删除功能,修改bug都会造成很大的问题。所以,从现在开始我们就应该养成一个保持代码整洁的好习惯。这样是编程水平的反应。
下面我们就把路由的代码从app.js文件中移出去。在上文提到的目录结构中添加一个mainRouter.js的问题件来存放我们从app.js中移出来的路由部分代码:
var router = function(app){
app.get('/', function(req, res){
res.render('../views/index.html');
});
app.get('/about', function(req, res){
res.render('../views/about.html');
});
};
exports.router = router;
最后的一句是说,这部分的代码是要作为模块给其他部分的代码使用的,所以需要使用系统提供的exports对象来“发布”这里的代码。在app.js中使用require
关键字来引入路由模块的代码。
var routers = require('./routers/mainRouter');
引入一个本地模块只需要知道路径就可以了。使用npm安装到本地的,或者nodejs系统内置的模块只需要require
方法中使用模块本身的名字就可以,不需要路径。完整代码:
var express = require("express");
var ejs = require('ejs');
var routers = require('./routers/mainRouter');
var app = express();
app.set('view engine', 'ejs');
app.engine('html', ejs.renderFile);
// routers
routers.router(app);
// app.get('/', function(req, res){
// res.render('index.html');
// });
// app.get('/about', function(req, res){
// res.render('about.html');
// });
// server
var server = app.listen(5566, function(){
console.log("Server is running on http://localhost:5566");
});
实践是检验真理的唯一标准。运行一下看看吧。