设置MEANStack单页应用程序
介绍
从头开始应用程序有时可能是最难做的事情。 盯着一个空文件夹和一个没有代码的文件可能是一件非常令人生畏的事情。
在今天的教程中,我们将研究 Node.js、AngularJS、MongoDB 和 Express 应用程序(也称为 MEAN)的 启动设置 。 我知道,我把它们按错了顺序。
对于那些想要学习如何开始 MEAN 堆栈应用程序的人来说,这将是一个起点。 像 mean.io 和 meanjs.org 这样的项目是更成熟的 MEAN 应用程序,具有许多生产项目所需的强大功能。
您将能够从头开始创建一个基本的应用程序结构,让您可以构建任何类型的应用程序。
注意: (7/8/14):更新了 Express 4 支持的文章。 感谢 Caio Mariano 的帮助。
注 (10/12/14): 更新文章添加Nerd模型,让一切更清晰。
本文已更新为与 Express 4.0 一起使用
我们将建造什么
到目前为止,我们处理的许多应用程序都有特定的功能,例如我们的 Node 和 Angular To-Do 单页应用程序。 我们将摆脱这一点,而只是一个很好的旧入门应用程序。
这将是非常简单的,但希望它能帮助您设置应用程序。 我们就称它为 入门套件 。
申请要求
- 单页应用
- 带有 Express 和 MongoDB 的 Node.js 后端
- AngularJS 前端
- 模块化 Angular 组件(控制器、服务)
- 良好的应用程序结构,因此我们的应用程序可以增长
本教程将更多地基于应用程序结构,并为单页 MEAN 堆栈应用程序创建坚实的基础。 有关 CRUD、身份验证或 MEAN 应用程序中其他主题的更多信息,我们将确保编写其他教程来填补这些空白。
后端节点、MongoDB、Express
MEAN 堆栈中的三个字母将在后端(我们的服务器)上处理。 我们将创建我们的服务器,配置我们的应用程序,以及处理应用程序路由。
所需工具
我们将需要 Node 并且为了让我们的生活更轻松,我们将使用 bower 来引入我们所有的依赖项。
Bower 并不是真正需要的。 您可以自己提取我们需要的所有文件(bootstrap
、angular
、angular-route
),但 bower 会为您获取所有文件! 有关更多信息,请阅读我们的 bower 指南以更好地理解。
应用结构
在本教程结束时,我们将拥有一个基本的应用程序结构,它将帮助我们开发 Node 后端和 Angular 前端。 这是它的样子。
- app ----- models/ ---------- nerd.js <!-- the nerd model to handle CRUD --> ----- routes.js - config ----- db.js - node_modules <!-- created by npm install --> - public <!-- all frontend and angular stuff --> ----- css ----- js ---------- controllers <!-- angular controllers --> ---------- services <!-- angular services --> ---------- app.js <!-- angular application --> ---------- appRoutes.js <!-- angular routes --> ----- img ----- libs <!-- created by bower install --> ----- views ---------- home.html ---------- nerd.html ---------- geek.html ----- index.html - .bowerrc <!-- tells bower where to put files (public/libs) --> - bower.json <!-- tells bower which files we need --> - package.json <!-- tells npm which packages we need --> - server.js <!-- set up our node application -->
我们将把我们的文件填充到一个文件夹结构中。 所有后端工作都在 server.js
、app
和 config
中完成,而所有前端工作都在 public
文件夹中处理。
启动我们的节点应用程序 package.json
所有 Node 应用程序都将从 package.json
文件开始,所以让我们从它开始。
{ "name": "starter-node-angular", "main": "server.js", "dependencies": { "express" : "~4.5.1", "mongoose" : "~3.8.0", "body-parser" : "~1.4.2", "method-override" : "~2.0.2" } }
就是这样! 现在我们的应用程序将知道我们想要使用 Express 和 Mongoose。
注意: 由于Express 4.0,body-parser
和method-override
是它们自己的模块,这就是为什么我们必须在这里包含它们。 有关更多信息,这是我们的 Express 4 指南。
Express 是一个 Node.js Web 应用程序框架,它将帮助我们创建我们的应用程序。 Mongoose 是一个 MongoDB ORM,它将帮助我们与 MongoDB 数据库进行通信。
安装节点模块
要安装我们刚刚设置的依赖项,只需进入控制台并输入:
npm install
你会看到你的应用程序将这些模块引入到它创建的 node_modules
目录中。
现在我们有了这些,让我们在 server.js
中设置我们的应用程序。
设置我们的节点应用程序 server.js
由于这是我们用于单页 MEAN 应用程序的入门工具包,因此我们将保持简单。 该文件的完整代码在此处,并对其进行了注释以帮助理解。
服务器.js
// modules ================================================= var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var methodOverride = require('method-override'); // configuration =========================================== // config files var db = require('./config/db'); // set our port var port = process.env.PORT || 8080; // connect to our mongoDB database // (uncomment after you enter in your own credentials in config/db.js) // mongoose.connect(db.url); // get all data/stuff of the body (POST) parameters // parse application/json app.use(bodyParser.json()); // parse application/vnd.api+json as json app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: true })); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT app.use(methodOverride('X-HTTP-Method-Override')); // set the static files location /public/img will be /img for users app.use(express.static(__dirname + '/public')); // routes ================================================== require('./app/routes')(app); // configure our routes // start app =============================================== // startup our app at http://localhost:8080 app.listen(port); // shoutout to the user console.log('Magic happens on port ' + port); // expose app exports = module.exports = app;
我们现在已经引入了我们的模块,为我们的应用程序配置了数据库、一些快速设置、路由等内容,然后启动了我们的服务器。 注意我们没有在这里拉入 mongoose
。 还没有必要。 我们将在我们即将定义的模型中使用它。
让我们看一下 config
、快速的 model
和 routes
,因为我们还没有创建它们。 这些将是我们应用程序后端需要的最后一件事。
配置配置/
我知道现在看起来并不多,因为我们只是将 db.js
配置文件放在这里,但这更多是出于演示目的。 将来,您可能希望添加更多配置文件并在 server.js
中调用它们,所以我们将这样做。
配置/db.js
module.exports = { url : 'mongodb://localhost/stencil-dev' }
现在这个文件已经定义好了,我们已经在我们的 server.js
中使用 var db = require('./config/db');
调用它,你可以使用 db.url
调用它里面的任何项目。
为了让它工作,你需要安装一个本地 MongoDB 数据库,或者你可以获取一个快速的一次性服务,如 Modulus 或 Mongolab。 只需继续在其中一个上创建一个帐户,使用您自己的凭据创建一个数据库,您就可以获取要在您自己的配置文件中使用的 URL 字符串。
接下来,我们将创建一个快速的 Mongoose 模型,以便我们可以在数据库中定义我们的书呆子。
书呆子模型 app/models/nerd.js
这就是在我们的数据库中创建记录所需的全部内容。 一旦我们定义了 Mongoose 模型,它将让我们处理创建、读取、更新和删除我们的书呆子。
让我们进入 app/models/nerd.js
文件并添加以下内容:
应用程序/模型/nerd.js
// grab the mongoose module var mongoose = require('mongoose'); // define our nerd model // module.exports allows us to pass this to other files when it is called module.exports = mongoose.model('Nerd', { name : {type : String, default: ''} });
这是我们将使用 Mongoose 模块并能够使用数据类型 String
的名称属性定义我们的 Nerd 模型的地方。 如果您想要更多字段,请随时在此处添加它们。 阅读 Mongoose 文档 以查看您可以定义的所有内容。
让我们进入路线并使用我们刚刚创建的模型。
节点路由 app/routes.js
将来,您可以使用 app 文件夹添加更多模型、控制器、路由和任何特定于您的应用程序的后端(节点)。
让我们来看看我们的路线。 在创建单页应用程序时,您通常会希望尽可能地分离后端应用程序和前端应用程序的功能。
路线分离
为了分离我们应用程序各个部分的职责,我们将能够为我们的 Node 后端定义任意数量的路由。 这可能包括 API 路由或任何其他具有这种性质的路由。
我们不会深入研究这些,因为在本教程中我们并没有真正处理创建 API 或执行 CRUD,但只需知道这是您处理这些路由的地方。
我们已经注释掉了将这些路线放在这里的地方。
应用程序/routes.js
// grab the nerd model we just created var Nerd = require('./models/nerd'); module.exports = function(app) { // server routes =========================================================== // handle things like api calls // authentication routes // sample api route app.get('/api/nerds', function(req, res) { // use mongoose to get all nerds in the database Nerd.find(function(err, nerds) { // if there is an error retrieving, send the error. // nothing after res.send(err) will execute if (err) res.send(err); res.json(nerds); // return all nerds in JSON format }); }); // route to handle creating goes here (app.post) // route to handle delete goes here (app.delete) // frontend routes ========================================================= // route to handle all angular requests app.get('*', function(req, res) { res.sendfile('./public/views/index.html'); // load our public/index.html file }); };
这是您可以处理 API 路由的地方。 对于所有其他路由(*
),我们会将用户发送到我们的前端应用程序,Angular 可以从那里处理路由它们。
后端完成!
现在我们已经拥有了设置服务器所需的一切! 此时,我们可以启动我们的服务器,向用户发送 Angular 应用程序 (index.html
),并处理 1 个 API 路由以获取所有书呆子。
让我们创建那个 index.html
文件,以便我们可以测试我们的服务器。
创建索引视图文件 public/views/index.html
让我们打开这个文件并添加一些快速文本,以便我们可以测试我们的服务器。
公共/视图/index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Starter MEAN Single Page Application</title> </head> <body> we did it! </body> </html>
测试我们的服务器
准备好所有后端(和一小块前端)后,让我们启动我们的服务器。 进入你的控制台并输入:
node server.js
现在我们可以进入浏览器查看 http://localhost:8080
的运行情况。
如此简单,却又如此美丽。 现在让我们来看看前端单页 AngularJS 的东西。
前端 AngularJS
随着我们所有的后端工作到位,我们可以专注于前端。 我们的 Node 后端会将任何访问我们应用程序的用户发送到我们的 index.html
文件,因为我们已经在 catch-all route (app.get('*')
) 中定义了它。
前端工作将需要一些东西:
- Bower 引入的文件和库
- Angular 应用程序结构(控制器、服务)
- 我们将创建 3 个不同的页面(Home、Nerds、Geeks)
- 使用 ngRoute 处理 Angular 路由,因此不会刷新页面
- 使用 Bootstrap 让它变得漂亮
Bower 和拉入组件
我们将需要某些文件用于我们的应用程序,例如 bootstrap,当然还有 angular。 我们将告诉 Bower 为我们获取这些组件。
Bower 是一个很好的前端工具来管理你的前端资源。 您只需指定所需的软件包,它就会为您获取它们。 这是一篇关于 开始使用 bower 的文章。
首先,我们需要在我们的机器上安装 Bower '。 只需在控制台中输入 npm install -g bower
。
完成此操作后,您现在可以在系统上全局访问 bower。 我们需要 2 个文件来让 Bower 为我们工作(.bowerrc
和 bower.json
)。 我们将把这两个都放在文档的根目录中。
.bowerrc 将告诉 Bower 将我们的文件放在哪里:
{ "directory": "public/libs" }
bower.json 与 package.json 类似,会告诉 Bower 需要哪些包。
{ "name": "starter-node-angular", "version": "1.0.0", "dependencies": { "bootstrap": "latest", "font-awesome": "latest", "animate.css": "latest", "angular": "latest", "angular-route": "latest" } }
让我们运行它! 在您的控制台中,在应用程序的根目录中,键入:
bower install
你可以看到 bower 拉入了我们需要的所有文件,现在我们将它们放在 public/libs
中!
现在我们可以开始做我们的 Angular 工作了。
设置我们的 Angular 应用程序
对于我们的 Angular 应用程序,我们需要:
- 2 个不同的页面(主页、书呆子)
- 每个都有不同的 Angular 控制器
- 为书呆子提供的 Angular 服务
- 切换页面时不刷新页面
让我们创建 Angular 应用程序所需的文件。 这将在 public/js
中完成。 这是我们前端的应用程序结构:
- public ----- js ---------- controllers -------------------- MainCtrl.js -------------------- NerdCtrl.js ---------- services -------------------- NerdService.js ---------- app.js ---------- appRoutes.js
一旦我们创建了我们的 controllers、services 和 routes,我们将把它们全部合并并将这些模块注入到我们的主 app.js
文件中让一切一起工作。
角度控制器
我们不会在这里太深入,所以让我们展示一下我们所有的三个控制器及其代码。
公共/js/controllers/MainCtrl.js
angular.module('MainCtrl', []).controller('MainController', function($scope) { $scope.tagline = 'To the moon and back!'; });
公共/js/controllers/NerdCtrl.js
angular.module('NerdCtrl', []).controller('NerdController', function($scope) { $scope.tagline = 'Nothing beats a pocket protector!'; });
当然,在未来,您将在控制器上做更多事情,但由于这更多是关于应用程序设置,我们将转向服务。
角服务
在这里,您可以使用 $http
或 $resource
从 Angular 前端对 Node 后端进行 API 调用。
公共/js/services/NerdService.js
angular.module('NerdService', []).factory('Nerd', ['$http', function($http) { return { // call to get all nerds get : function() { return $http.get('/api/nerds'); }, // these will work when more API routes are defined on the Node side of things // call to POST and create a new nerd create : function(nerdData) { return $http.post('/api/nerds', nerdData); }, // call to DELETE a nerd delete : function(id) { return $http.delete('/api/nerds/' + id); } } }]);
这就是我们的服务。 唯一可以在 NerdService
中工作的函数是 get
函数。 另外两个只是占位符,除非您在 app/routes.js
文件中定义这些特定路由,否则它们将不起作用。 有关构建 API 的更多信息,请参阅构建 RESTful Node API 的教程。
这些服务将调用我们的 Node 后端,以 JSON 格式检索数据,然后我们可以在 Angular 控制器中使用它。
角度路线
现在我们将在我们的 public/js/appRoutes.js
文件中定义我们的 Angular 路由。
公共/js/appRoutes.js
angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) { $routeProvider // home page .when('/', { templateUrl: 'views/home.html', controller: 'MainController' }) // nerds page that will use the NerdController .when('/nerds', { templateUrl: 'views/nerd.html', controller: 'NerdController' }); $locationProvider.html5Mode(true); }]);
我们的 Angular 前端将使用模板文件并将其注入到我们的 index.html
文件中的 <div ng-view></div>
中。 它将在没有页面刷新的情况下执行此操作,这正是我们想要的单页面应用程序。
有关 Angular 路由和模板的更多信息,请查看我们的其他教程:使用 AngularJS 的单页应用程序。
更新的视图文件
准备好所有 Angular 路由后,我们只需要创建视图文件,然后注入较小的模板文件(home.html
、nerd.html
和 geek.html
)进入 <div ng-view></div>
内的 index.html
文件。
请注意,在我们的 index.html
文件中,我们正在调用我们使用 bower 提取的资源。
公共/index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <base href="/"> <title>Starter Node and Angular</title> <!-- CSS --> <link rel="stylesheet" href="libs/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="css/style.css"> <!-- custom styles --> <!-- JS --> <script src="libs/angular/angular.min.js"></script> <script src="libs/angular-route/angular-route.min.js"></script> <!-- ANGULAR CUSTOM --> <script src="js/controllers/MainCtrl.js"></script> <script src="js/controllers/NerdCtrl.js"></script> <script src="js/services/NerdService.js"></script> <script src="js/appRoutes.js"></script> <script src="js/app.js"></script> </head> <body ng-app="sampleApp" ng-controller="NerdController"> <div class="container"> <!-- HEADER --> <nav class="navbar navbar-inverse"> <div class="navbar-header"> <a class="navbar-brand" href="/">Stencil: Node and Angular</a> </div> <!-- LINK TO OUR PAGES. ANGULAR HANDLES THE ROUTING HERE --> <ul class="nav navbar-nav"> <li><a href="/nerds">Nerds</a></li> </ul> </nav> <!-- ANGULAR DYNAMIC CONTENT --> <div ng-view></div> </div> </body> </html> <!-- public/views/home.html --> <div class="jumbotron text-center"> <h1>Home Page 4 Life</h1> <p>{{ tagline }}</p> </div> <!-- public/views/nerd.html --> <div class="jumbotron text-center"> <h1>Nerds and Proud</h1> <p>{{ tagline }}</p> </div>
让一切协同工作
我们已经定义了我们的资源、控制器、服务和路由,并将这些文件包含在我们的 index.html
中。 现在让我们让它们一起工作。
让我们设置我们的 Angular 应用程序以使用我们所有的组件。 我们将使用依赖注入并设置我们的 Angular 应用程序。
公共/js/app.js
angular.module('sampleApp', ['ngRoute', 'appRoutes', 'MainCtrl', 'NerdCtrl', 'NerdService']);
结论
现在我们有一个具有 Node.js 后端和 AngularJS 前端的应用程序。 我们可以使用这个基础来构建任何类型的应用程序。 我们可以添加身份验证和 CRUD 功能来创建一个好的应用程序。
此外,对于那些寻找添加 Jade 模板引擎的项目的人,Florian Zemke 在他的 GitHub 存储库 中创建了 Jade 版本。
下一步
展望未来,我鼓励你接受这个,看看它是否符合你的需要。 这样做的目的是为启动应用程序奠定基础,这样我们就不会在每次启动新项目时都重新发明轮子。
这是一个非常简单的示例,对于更深入的内容,我鼓励人们查看 mean.io 以获得更深入的入门应用程序。
查看该项目的 GitHub 存储库 并从中获取您需要的内容。 如果您对如何将其扩展到您自己的应用程序有任何疑问,请在评论中发出声音。
入门套件
我们已将本教程作为入门工具包放在 GitHub 存储库 中。 我们将根据要求继续为其添加功能,并且我们认为对应用程序有帮助的任何更新。
希望它将成为任何类型的单页 MEAN 堆栈应用程序的良好基础。
使用入门应用程序
- 下载代码
- 安装 npm 模块:
npm install
- 安装凉亭组件:
bower install
- 启动服务器:
node server.js
- 在浏览器中访问应用程序
http://localhost:8080
- 使用此入门工具包构建您需要的任何应用程序。
进一步阅读:在构建 MEAN 堆栈应用程序时,后端 Node 应用程序通常是我们构建的 API。 这将允许 Angular 前端使用我们通过 Angular 服务构建的 API。 下一步是构建一个 Node API。 下一个教程将教我们这一点,然后我们可以更深入地了解如何构建前端 Angular 应用程序以使用我们的新 API。
想要更多的意思吗?
本文是我们获取 MEAN 系列的一部分。 这是其他文章。
- 设置 MEAN Stack 单页应用程序
- 使用 Node 和 Express 4 构建 RESTful API
- 在 MEAN Stack 应用程序中使用 GruntJS