原文: http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/

原文的源代码在此

太多的教程教你些一个Hello, World!了, 但是仅凭Hello, World! 是找不到工作的, 因此有了这篇教程.

PART I – 安装开发环境

作者是在Windows 8上开发的.

STEP 1 – 安装NODE.JS

打开 Node.js website 点击绿色的安装按钮. 运行安装程序就安装好了, 就是这么简单. 现在你已经安装好Node.js了, 同样NPM(Node Package Manager)也安装好了

  • 打开命令终端 cmd
  • cd到你想要建立应用的目录
    (本教程是 C:\node).

STEP 2 – 安装EXPRESS

现在我们安装Express, Express是一个框架他能让我们更简单的建立一个web应用. 在命令终端运行:

  1. C:\node>npm install -g express

(-g代表安装到全局, 我感觉express不应该安装到全局)

好消息: 你可以安装一个express的"generator". 他能帮我们生成一个网站基本的框架, 让我们少些了好多的代码(如果你想了解更多可以去Yeoman 看看). 安装generator也很容易, 在命令终端运行:

  1. C:\node>npm install -g express-generator

好了是时候生成一个网站的基本框架了

STEP 3 – CREATE AN EXPRESS PROJECT

我们使用Express 和 Jade, 在命令终端输入:

  1. C:\node>express nodetest1

点击回车,  你可以看到下面的东西

  1. C:\node>express nodetest1
  2. create : nodetest1
  3. create : nodetest1/package.json
  4. create : nodetest1/app.js
  5. create : nodetest1/public
  6. create : nodetest1/public/javascripts
  7. create : nodetest1/public/images
  8. create : nodetest1/routes
  9. create : nodetest1/routes/index.js
  10. create : nodetest1/routes/users.js
  11. create : nodetest1/public/stylesheets
  12. create : nodetest1/public/stylesheets/style.css
  13. create : nodetest1/views
  14. create : nodetest1/views/index.jade
  15. create : nodetest1/views/layout.jade
  16. create : nodetest1/views/error.jade
  17. create : nodetest1/bin
  18. create : nodetest1/bin/www
  19.  
  20. install dependencies:
  21. $ cd nodetest1 && npm install
  22.  
  23. run the app:
  24. $ DEBUG=my-application ./bin/www

STEP 4 – 编辑依赖

现在我们的网站已经有一个基本的结构了, 但是我们现在还有一些事没做. 你能注意到nodetest1目录有一个叫package.json的文件. 文件的内容如下:

  1. {
  2. "name": "application-name",
  3. "version": "0.0.1",
  4. "private": true,
  5. "scripts": {
  6. "start": "node ./bin/www"
  7. },
  8. "dependencies": {
  9. "express": "~4.0.0",
  10. "serve-favicon": "~2.1.3",
  11. "morgan": "~1.0.0",
  12. "cookie-parser": "~1.0.1",
  13. "body-parser": "~1.0.0",
  14. "debug": "~0.7.4",
  15. "jade": "~1.3.0"
  16. }
  17. }

这些json内容描述了我们的网站和他的一些依赖. 我们需要添加一些东西. 现在让我们在依赖里面添加MongoDB和Monk.

  1. "dependencies": {
  2. "express": "~4.0.0",
  3. "serve-favicon": "~2.1.3",
  4. "morgan": "~1.0.0",
  5. "cookie-parser": "~1.0.1",
  6. "body-parser": "~1.0.0",
  7. "debug": "~0.7.4",
  8. "jade": "~1.3.0",
  9. "mongodb": "*",
  10. "monk": "*"
  11. }

STEP 5 – 安装依赖

现在我们已经定义了我们的依赖. 注意星号代表获取最新的版本. 打开终端 cd到nodetest1目录, 输入:

  1. C:\node\nodetest1>npm install

现在终端会输出一大堆的东西. 因为读取JSON文件安装我们定义的依赖对象. 运行完后, 你可以发现一个node_modules目录, 里面包含了我们之前定义的依赖.

现在你的网站基本可以运行了. 在运行前我们需要设置一个数据库目录. 在终端输入:

  1. C:\node\nodetest1>mkdir data

这个目录用来存储我们的MongoDB数据. 如果这个目录不存在的话, 数据库会阻塞我们的网站. 好了现在我们可以来运行看看我们的网站了. 在终端输入:

  1. C:\node\nodetest1>npm start

回车后, 你可以在终端看到下面的东西

  1. > application-name@0.0.1 start D:\sites\node\nodetest1
  2. > node ./bin/www

打开浏览器, 输入http://localhost:3000  你可以看到一个Express的欢迎页面

PART 2 – 好了让我们做个"HELLO, WORLD!"

用IDE打开app.js, 内容如下:

  1. var express = require('express');
  2. var path = require('path');
  3. var favicon = require('serve-favicon');
  4. var logger = require('morgan');
  5. var cookieParser = require('cookie-parser');
  6. var bodyParser = require('body-parser');
  7.  
  8. var routes = require('./routes/index');
  9. var users = require('./routes/users');

上面的代码给package、依赖、node functionality和路由创建了相应的变量. 路由是modles和controllers的一种关联. 这里我们忽略不去管user路由只关注于顶级路由 (c:\node\nodetest1\routes\index.js).

app.js

  1. var app = express();

这个非常重要. 他实例化了一个Express并且分配给了app变量. 下面的代码片段使用这个变量配置一堆express的东西.

app.js

  1. // view engine setup
  2. app.set('views', path.join(__dirname, 'views'));
  3. app.set('view engine', 'jade');
  4.  
  5. // uncomment after placing your favicon in /public
  6. //app.use(favicon(__dirname + '/public/favicon.ico'));
  7. app.use(logger('dev'));
  8. app.use(bodyParser.json());
  9. app.use(bodyParser.urlencoded());
  10. app.use(cookieParser());
  11. app.use(express.static(path.join(__dirname, 'public')));
  12.  
  13. app.use('/', routes);
  14. app.use('/users', users);

上面的代码告诉app去哪查找views(视图), 使用何种视图引擎展现我们的视图(Jade), 另外调用了一些方法. 倒数第三行代码告诉Express静态文件放在public目录, 我们获取这些静态文件的时候不需要在url中输入public . 比如, 图片目录在c:\node\nodetest1\public\images, 但是我们通过http://localhost:3000/images 来进入到图片目录.

app.js

  1. /// catch 404 and forwarding to error handler
  2. app.use(function(req, res, next) {
  3. var err = new Error('Not Found');
  4. err.status = 404;
  5. next(err);
  6. });
  7.  
  8. /// error handlers
  9.  
  10. // development error handler
  11. // will print stacktrace
  12. if (app.get('env') === 'development') {
  13. app.use(function(err, req, res, next) {
  14. res.status(err.status || 500);
  15. res.render('error', {
  16. message: err.message,
  17. error: err
  18. });
  19. });
  20. }
  21.  
  22. // production error handler
  23. // no stacktraces leaked to user
  24. app.use(function(err, req, res, next) {
  25. res.status(err.status || 500);
  26. res.render('error', {
  27. message: err.message,
  28. error: {}
  29. });
  30. });

这里有两种错误处理器, 一个是给开发环境用的,另一个是给生产环境使用的.

app.js

  1. module.exports = app;

Node的一个核心部分就是module.exports. 我们的主app导出app对象.

我们先看看app.js现有的路由:

  1. app.use('/', routes);
  2. app.use('/users', users);

上面的代码告诉Express使用那些路由文件. 一般我提倡为应用的不同部分写对应的路由文件. 例如, users路由文件可能包含添加用户、删除用户、更新用户的路由,locations路由文件处理添加、删除、编辑、展示location的路由. 在我们的这个教程中, 为了简单的演示, 我们只关注index路由.

Express generator已经定义了一个"routes" 变量指向index路由. 我们在index路由中添加"helloworld"方法展示一个新的页面. 打开index.js:

  1. var express = require('express');
  2. var router = express.Router();
  3.  
  4. /* GET home page. */
  5. router.get('/', function(req, res) {
  6. res.render('index', { title: 'Express' });
  7. });
  8.  
  9. module.exports = router;

在最后一行前加入下面的代码:

  1. /* GET Hello World page. */
  2. router.get('/helloworld', function(req, res) {
  3. res.render('helloworld', { title: 'Hello, World!' })
  4. });

现在我们还没创建一个helloworld页面. 打开views文件夹, 打开index.jade. 创建一个helloworld.jade文件内容拷贝index.jade的内容.

现在helloworld.jade的内容如下:

  1. extends layout
  2.  
  3. block content
  4. h1= title
  5. p Welcome to #{title}

使用("extends") 将layout.jade作为一个模板, 接下来在layout文件定义的content block下面输出一个h1和p标签. 注意"title"参数是我们在index.js路由中已经定义了的.

下面让我们改变p的内容:

  1. p Hello, World! Welcome to #{title}

保存文件,回到终端, 按ctrl-c退出服务, 输入:

  1. npm start

顺便说一下, 修改Jade模板不需要重启服务, 但是修改app.js或者路由这样的.js文件需要重启服务.

现在打开http://localhost:3000/helloworld 页面, 效果如下:

PART 3 – 创建数据库

STEP 1 – 安装MONGODB

打开http://mongodb.org/ 下载Mongo. 你会得到一个zip文件, 解压到一个临时的目录. 创建一个目录放Mongo, 把解压后的文件放到这个新的目录下.

STEP 2 – 运行MONGOD和MONGO

在你的nodetest1目录, 新建一个data子目录. 先cd到你安装mongo的目录, 然后输入:

  1. mongod --dbpath c:\node\nodetest1\data

Mongo服务运行了. 第一次会消耗一定的时间, 因为mongo要预先分配一些空间, 另外还要运行一些任务. 当看到终端输出"[initandlisten] waiting for connections on port 27017", 这代表启动完成了. 现在另开一个终端cd到mongo的安装目录, 输入:

  1. mongo

回车后看到下面的内容

  1. c:\mongo>mongo
  2. MongoDB shell version: 2.4.5
  3. connecting to: test

这告诉你连接已经建立好了

STEP 3 – 创建数据库

"connecting to: test" …test是mongo默认使用的数据库. 其实这个时候还没有真正的创建了一个名为test的数据库, 除非你给test创建了一条记录, 这个时候test数据库才真正的被创建. 在Mongo console 中输入:

  1. use nodetest1

现在我们使用"nodetest1数据库, 和上面讲到的"test"一样, 这个时候我们并没有真正的创建了nodetest1数据库. 为了真正的创建这个数据库, 我们应该添加一些数据.

STEP 4 – 添加数据

添加一些数据到我们的collection. 在这个教程中, 我们的数据比较简单, 只需要一个username和email.数据格式如下:

  1. {
  2. "_id" : 1234,
  3. "username" : "cwbuecheler",
  4. "email" : "cwbuecheler@nospam.com"
  5. }

在mongo终端输入:

  1. db.usercollection.insert({ "username" : "testuser1", "email" : "testuser1@testdomain.com" })

这里要注意的是: "db" 代表我们的数据库, 这里是我们上面定义的"nodetest1"."usercollection" 是我们的collection. 注意我们没有一个创建usercollection的步骤. 因为第一次使用的时候他会自动被创建.回车. 如果一切顺利的话, 终端不会输出任何东西. 现在输入:

  1. db.usercollection.find().pretty()

.pretty() 方法会使得输出自动换行, 这样返回的内容的可读性更好. 返回内容如下:

  1. {
  2. "_id" : ObjectId("5202b481d2184d390cbf6eca"),
  3. "username" : "testuser1",
  4. "email" : "testuser1@testdomain.com"
  5. }

现在我们一次插入多条记录

  1. newstuff = [{ "username" : "testuser2", "email" : "testuser2@testdomain.com" }, { "username" : "testuser3", "email" : "testuser3@testdomain.com" }]
  2. db.usercollection.insert(newstuff);

是的, 我们可以传递一个对象数组给我们的collection

STEP 5 – HOOK MONGO UP TO NODE

让我们开始创建一个页面显示数据路里面的内容. 这里是我们期望的得到的html

  1. <ul>
  2. <li><a href="mailto:testuser1@testdomain.com">testuser1</a></li>
  3. <li><a href="mailto:testuser2@testdomain.com">testuser2</a></li>
  4. <li><a href="mailto:testuser3@testdomain.com">testuser3</a></li>
  5. </ul>

我们需要在app.js文件中添加几行代码, 用来连接我们的MongoDB. 打开app.js文件:

  1. var express = require('express');
  2. var path = require('path');
  3. var favicon = require('serve-favicon');
  4. var logger = require('morgan');
  5. var cookieParser = require('cookie-parser');
  6. var bodyParser = require('body-parser');

现在让我们来添加3行代码

  1. var express = require('express');
  2. var path = require('path');
  3. var favicon = require('serve-favicon');
  4. var logger = require('morgan');
  5. var cookieParser = require('cookie-parser');
  6. var bodyParser = require('body-parser');
  7.  
  8. // New Code
  9. var mongo = require('mongodb');
  10. var monk = require('monk');
  11. var db = monk('localhost:27017/nodetest1');

这几行代码告诉我们的应用我们想使用MongoDB, 这里使用的是Monk(现在Mongoose比较流行), 我们的数据库位于localhost:27017/nodetest1. 注意27017是MOngoDB的默认端口. 现在看到app.js文件的底部, 代码如下:

  1. app.use('/', routes);
  2. app.use('/users', users);

在这我们需要做点工作.app.use语句是为Express建立中间件. 简短的说: 他们提交了一些自定义的函数使得你的app更加有用. 他们很简单, 但是要注意的是他们必须放在路由定义前才能生效.

在上面两行代码前加入下面的代码

  1. // Make our db accessible to our router
  2. app.use(function(req,res,next){
  3. req.db = db;
  4. next();
  5. });

注意: 如果你不是将上面的代码放在 app.use('/', routes) 之上, 你新加的代码就不会起作用.

当我们添加Mongo和Monk到app.js的时候我们已经定义了db. db是我们的Monk连接对象. 在把上面的代码添加到app.use后, 每个HTTP request对象都有一个db了. 注意: 这个对性能来说可能不是最好的选择, 但是我们这里是讲快速搭建.

再次强调, 上面的代码必须放在我们的路由之上. 现在你的app.js应该是这样子的:

  1. var express = require('express');
  2. var path = require('path');
  3. var favicon = require('serve-favicon');
  4. var logger = require('morgan');
  5. var cookieParser = require('cookie-parser');
  6. var bodyParser = require('body-parser');
  7.  
  8. // New Code
  9. var mongo = require('mongodb');
  10. var monk = require('monk');
  11. var db = monk('localhost:27017/nodetest1');
  12.  
  13. var routes = require('./routes/index');
  14. var users = require('./routes/users');
  15.  
  16. var app = express();
  17.  
  18. // view engine setup
  19. app.set('views', path.join(__dirname, 'views'));
  20. app.set('view engine', 'jade');
  21.  
  22. // uncomment after placing your favicon in /public
  23. //app.use(favicon(__dirname + '/public/favicon.ico'));
  24. app.use(logger('dev'));
  25. app.use(bodyParser.json());
  26. app.use(bodyParser.urlencoded());
  27. app.use(cookieParser());
  28. app.use(express.static(path.join(__dirname, 'public')));
  29.  
  30. // Make our db accessible to our router
  31. app.use(function(req,res,next){
  32. req.db = db;
  33. next();
  34. });
  35.  
  36. app.use('/', routes);
  37. app.use('/users', users);
  38.  
  39. /// catch 404 and forwarding to error handler
  40. app.use(function(req, res, next) {
  41. var err = new Error('Not Found');
  42. err.status = 404;
  43. next(err);
  44. });
  45.  
  46. /// error handlers
  47.  
  48. // development error handler
  49. // will print stacktrace
  50. if (app.get('env') === 'development') {
  51. app.use(function(err, req, res, next) {
  52. res.status(err.status || 500);
  53. res.render('error', {
  54. message: err.message,
  55. error: err
  56. });
  57. });
  58. }
  59.  
  60. // production error handler
  61. // no stacktraces leaked to user
  62. app.use(function(err, req, res, next) {
  63. res.status(err.status || 500);
  64. res.render('error', {
  65. message: err.message,
  66. error: {}
  67. });
  68. });
  69.  
  70. module.exports = app;

接下来我们要修改我们的路由, 这样我们就能使用数据库来展现数据了.

STEP 6 – PULL YOUR DATA FROM MONGO AND DISPLAY IT

在编辑器中打开 C:\node\nodetest1\routes\index.js. 现在让我们来添加一个路由:

  1. /* GET Userlist page. */
  2. router.get('/userlist', function(req, res) {
  3. var db = req.db;
  4. var collection = db.get('usercollection');
  5. collection.find({},{},function(e,docs){
  6. res.render('userlist', {
  7. "userlist" : docs
  8. });
  9. });
  10. });

下一步我们要设置我们的Jade 模版. 导航到C:\node\nodetest1\views\打开index.jade文件. 复制其内容到新建的userlist.jade, 编辑内容如下:

  1. extends layout
  2.  
  3. block content
  4. h1.
  5. User List
  6. ul
  7. each user, i in userlist
  8. li
  9. a(href="mailto:#{user.email}")= user.username

each中的user代表迭代中的user, i(index)是一个计数器.

保存文件, 重启node服务:

  1. C:\node\nodetest1>npm start

Now open your browser and head to http://localhost:3000/userlist and marvel in the results.

现在你从数据库里面取出来数据展现在网页上了!

PART 4 – 数据库的写操作

数据库的写操作不难. 记住写操作一般用 HTTP POST

STEP 1 – 创建数据输入框CREATE YOUR DATA INPUT

我们先为添加用户的表单页面添加一个路由. 打开/routes/index.js 添加下面的代码(在module.exports前) :

  1. /* GET New User page. */
  2. router.get('/newuser', function(req, res) {
  3. res.render('newuser', { title: 'Add New User' });
  4. });

现在我们添加一个jade模版页面  newuser.jade:

  1. extends layout
  2.  
  3. block content
  4. h1= title
  5. form#formAddUser(name="adduser",method="post",action="/adduser")
  6. input#inputUserName(type="text", placeholder="username", name="username")
  7. input#inputUserEmail(type="text", placeholder="useremail", name="useremail")
  8. button#btnSubmit(type="submit") submit

重启node服务, 打开 http://localhost:3000/newuser 内容如下:

现在点击submit按钮会得到一个404错误.

STEP 2 – 创建我们的数据功能

现在我们要做的是添加一个Post路由名为 /adduser.

打开 /routes/index.js 添加下面的内容:

  1. /* POST to Add User Service */
  2. router.post('/adduser', function(req, res) {
  3.  
  4. // Set our internal DB variable
  5. var db = req.db;
  6.  
  7. // Get our form values. These rely on the "name" attributes
  8. var userName = req.body.username;
  9. var userEmail = req.body.useremail;
  10.  
  11. // Set our collection
  12. var collection = db.get('usercollection');
  13.  
  14. // Submit to the DB
  15. collection.insert({
  16. "username" : userName,
  17. "email" : userEmail
  18. }, function (err, doc) {
  19. if (err) {
  20. // If it failed, return error
  21. res.send("There was a problem adding the information to the database.");
  22. }
  23. else {
  24. // If it worked, set the header so the address bar doesn't still say /adduser
  25. res.location("userlist");
  26. // And forward to success page
  27. res.redirect("userlist");
  28. }
  29. });
  30. });

STEP 3 – 连结并且添加一些数据到数据库

确定mongod是正在运行的! 下面重启node :

  1. C:\node\nodetest1>npm start

现在我们打开 http://localhost:3000/newuser 添加一些内容(下面的网址不正确请忽略网址).

点击submit, 我们会跳转到 /userlist 页面, 在这个页面中可以看到我们添加的新用户!

[译]简单得不得了的教程-一步一步用 NODE.JS, EXPRESS, JADE, MONGODB 搭建一个网站的更多相关文章

  1. 玩转Node.js(四)-搭建简单的聊天室

    玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...

  2. 前端使用node.js+express+mockjs+mysql实现简单服务端,2种方式模拟数据返回

    今天,我教大家来搭建一个简单服务端 参考文章: https://www.jianshu.com/p/cb89d9ac635e https://www.cnblogs.com/jj-notes/p/66 ...

  3. Node.js Express 的安装和简单使用

    Express的安装: 1.命令行窗口 //--> npm install 组件名 @版本号 --> npm install express @4   //这里安装最新的版本 也可以这样: ...

  4. [转]分别使用Node.js Express 和 Koa 做简单的登录页

    本文转自:https://blog.csdn.net/weixin_38498554/article/details/79204240 刚刚学了Koa2,由于学的不是很深,并没有感受到网上所说的Koa ...

  5. 方便大家学习的Node.js教程(一):理解Node.js

    理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...

  6. 教程:动手用自己电脑搭建一个网站 (nat123 花生壳 动态域名 个人电脑做服务器)

    先ps一下..今晚试了N种方法,终于找到一个靠谱 免费 好用的方法,来改装自己电脑成为服务器,在外网也能通过域名访问了!!! 需要准备的东西: Tomcat:这个是web容器,其实有了这个就已经让电脑 ...

  7. Docker ASPNetCore https 四步教你搭建一个网站

    序 本教程需要有自己已经申请好的证书 ,没有证书请参照官方教程. Docker 就不多说了,咱只要知道怎么用先. 环境 core:asp net core 2.2 开发机:win10 LTS 服务器: ...

  8. 如何简单便捷的搭建一个网站 - 基于Django

    一.所需工具以及相关环境 1. 系统:win7,win8.1,win10(亲测可用 - 本文为win7,64位) 2. 本文使用的版本是: 1)python-2.7.11[百度云盘分享:http:// ...

  9. 使用node,express,mongodb,ionic,ejs搭建的简单app个人总结

    1.每次修改app.js或者其他路由js文件,都必须重启node app.js,否则修改不起作用!!! 2.<link rel="stylesheet" href=" ...

随机推荐

  1. JS监听DOM结构变化

    在做一个微博的接入,需要判断微博是否被关注,要检查微博标签的DIV是否有“已关注”的字符,但这个DIV的内容是微博JSSDK动态生成.$("#id").html()是获取不到我想要 ...

  2. RCE via XStream object deserialization && SECURITY-247 / CVE-2016-0792 XML reconstruction Object Code Inject

    catalogue . Java xStream . DynamicProxyConverter . java.beans.EventHandler . RCE via XStream object ...

  3. shell !符号

    执行某历史命令 history找出历史命令id号 ! id

  4. TCP/IP详解 笔记十三

    TCP协议(一) 概述 特点 1,  面向连接可靠的字节流服务 2,  只有两方通信,不能用于广播或多播 3,  应用数据被TCP分隔为最合适发送的数据段,传给IP协议栈 4,  发送端并启动定时器, ...

  5. Io 异常: The Network Adapter could not establish the connection 解决方法

    1.IP错误: 在设置URL时错误,例如:jdbc:oracle:thin:@192.168.1.80:1521:orcl 数据库服务器是否正确:ping 服务器IP是否通畅.ping不通则将URL更 ...

  6. HDU #5733 tetrahedron

    tetrahedron 传送门 Time Limit: 2000/1000 MS (Java/Others)   Memory Limit: 65536/65536 K (Java/Others) P ...

  7. HDU 4223 Dynamic Programming?(最小连续子序列和的绝对值O(NlogN))

    传送门 Description Dynamic Programming, short for DP, is the favorite of iSea. It is a method for solvi ...

  8. hdu 2034 - 集合操作

    题意:集合A,B,计算集合差A-B(求只在集合A内的数) 解法: 选用STL内的集合set 1.建立set 1: #include<set> 2:   3: set<int> ...

  9. BCE0019: '' is not a member of 'UnityEngine.Component'的问题

    看自学网上的Unity3D的视频,其中视频中的实力代码: n.rigidbody.AddForce(fwd * 28000); 这个代码运行会出现错误: BCE0144: 'UnityEngine.C ...

  10. 线性回归和批量梯度下降法python

    通过学习斯坦福公开课的线性规划和梯度下降,参考他人代码自己做了测试,写了个类以后有时间再去扩展,代码注释以后再加,作业好多: import numpy as np import matplotlib. ...