戴维·温伯格(David Weinberger)在其2002年的书中将蓬勃发展的网络内容描述为“松散加入的小作品”的集合。 这个隐喻一直困扰着我,因为很容易被欺骗,将网络视为一种整体技术堆栈。 实际上,您访问的每个网站都是库,语言和Web框架独特结合的产物。
LAMP堆栈是最早引起人们注意的开源Web技术集合之一:Linux®操作系统,Apache®Web服务器,MySQL数据库,以及Perl(或Python或PHP)使用的编程语言生成基于HTML的网页。 这些技术并不是为了协同工作而编写的。 它们是一个独立的项目,一位雄心勃勃的软件工程师,然后是另一位,然后是另一位,将其拼凑在一起。 从那时起,我们见证了寒武纪卷筒纸爆炸。 每种现代编程语言似乎都有相应的Web框架(或两个),这些框架预组装了许多技术,以使快速轻松地引导新网站成为可能。
MEAN堆栈是Web社区中引起人们广泛关注和兴奋的新兴堆栈: MongoDB , Express , AngularJS , Node.js 。 MEAN堆栈代表了一种完全现代化的Web开发方法:从客户端到服务器再到持久性,在每种应用程序层中都运行一种语言(JavaScript)。 本系列演示了MEAN Web开发项目从端到端的样子,超越了简单的语法。 此初始部分使您开始对堆栈的组件技术进行深入,动手的介绍,包括安装和设置。 请参阅下载以获取示例代码。
“您访问的每个网站都是库,语言和Web框架独特结合的产物。 ”
MEAN不仅仅是对首字母缩写字母和技术升级的简单重新排列。 将基本平台从OS(Linux)切换到JavaScript运行时(Node.js)可以带来OS的独立性:Node.js在Windows®和OS X上的运行与在Linux上一样好。
Node.js还替换了LAMP堆栈中的Apache。 但是Node.js远不只是一个简单的Web服务器。 实际上,您不会将完成的应用程序部署到独立的Web服务器上。 相反,Web服务器包含在您的应用程序中,并自动安装在MEAN堆栈中。 结果,部署过程大大简化了,因为已明确定义了所需的Web服务器版本以及其余的运行时依赖项。
从传统的数据库(如MySQL)到NoSQL,无模式,面向文档的持久性存储(如MongoDB)的转变代表了持久性策略的根本转变。 您将花费更少的时间来编写SQL,而花费更多的时间来编写JavaScript中的map / reduce函数。 您还将削减大量的转换逻辑,因为MongoDB会原生发出JavaScript对象表示法(JSON) 。 因此,编写RESTful Web服务比以往任何时候都容易。
但是,从LAMP到MEAN的最大转变是从传统的服务器端页面生成向客户端单页面应用程序(SPA)方向转变。 借助Express,您仍然可以处理服务器端路由和页面生成,但是现在重点是在客户端视图上,这要归功于AngularJS。 这种更改不仅仅涉及将模型视图控制器(MVC)工件从服务器转移到客户端。 您还将获得从同步思维到本质上基本上是事件驱动和异步的思维的飞跃。 也许最重要的是,您将从应用程序的以页面为中心的视图转变为面向组件的视图。
MEAN堆栈并非以移动设备为中心-AngularJS在台式机,笔记本电脑,智能手机和平板电脑甚至智能电视上均能很好地运行-但它不会将移动设备视为二等公民。 测试不再是事后的想法:借助MochaJS , JasmineJS和KarmaJS等世界一流的测试框架,您可以为MEAN应用程序编写全面而全面的测试套件。
准备好了吗?
您需要可以正常工作的Node.js安装来处理本系列中的示例应用程序,因此现在可以安装Node(如果尚未安装)。
如果您使用的是类似UNIX®的OS(Linux,Mac OS X等),建议您使用Node Version Manager(NVM) 。 (否则,请在Node.js主页上单击“ 安装 ”以下载适用于您的操作系统的安装程序,并接受默认设置。)使用NVM,您可以轻松下载Node.js并从命令行在各种版本之间进行切换。 这有助于我从一个客户端项目无缝迁移到另一个版本,从而从一个版本的Node.js无缝迁移到另一个版本。
安装NVM后,键入nvm ls-remote
以查看哪些版本的Node.js可用于安装,如清单1所示。
$ nvm ls-remote
v0.10.20
v0.10.21
v0.10.22
v0.10.23
v0.10.24
v0.10.25
v0.10.26
v0.10.27
v0.10.28
输入nvm ls
显示您已经在本地安装了哪些版本的Node.js,以及当前正在使用的版本。
在撰写本文时,Node网站建议v0.10.28是最新的稳定版本。 键入nvm install v0.10.28
以将其本地安装。
安装Node.js(通过NVM或特定于平台的安装程序)之后,键入node --version
来验证您使用的是当前版本:
$ node --version
v0.10.28
Node.js是无头JavaScript运行时。 实际上,它与在Google Chrome中运行JavaScript引擎(命名为V8)相同,但使用Node.js可以从命令行而不是在浏览器中运行JavaScript。
我曾让学生嘲笑从命令行运行JavaScript的想法:“如果没有要操纵HTML,JavaScript有什么用?” JavaScript是通过浏览器(Netscape Navigator 2.0)引入世界的,因此那些反对者可以因其短视和天真而被原谅。
实际上,JavaScript编程语言没有用于文档对象模型(DOM)操纵或发出Ajax请求的本机功能。 浏览器提供了DOM API,因此您可以使用JavaScript进行此类操作,但是在浏览器之外,JavaScript失去了这些功能。
这是一个例子。 在浏览器中打开一个JavaScript控制台(请参阅访问浏览器的开发人员工具 )。 输入navigator.appName
。 得到响应后,键入navigator.appVersion
。 您的结果与图1相似。
navigator
对象 在图1中,对navigator.appName
的响应是Netscape
,对navigator.appVersion
的响应是经验丰富的Web开发人员已经知道并且喜欢或讨厌的神秘用户代理字符串。 在图1中(来自OS X上的Chrome),字符串是5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
。
现在,创建一个名为test.js的文件。 在文件中键入相同的命令,并将每个命令包装在console.log()
调用中:
console.log(navigator.appName);
console.log(navigator.appVersion);
保存文件,然后键入node test.js
来运行它,如清单2所示。
navigator is not defined
错误 $ node test.js
/test.js:1
ion (exports, require, module, __filename, __dirname) { console.log(navigator.
^
ReferenceError: navigator is not defined
at Object. (/test.js:1:75)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
如您所见,您可以在浏览器中使用navigator
器,但不能从Node.js中使用navigator
器。 (很抱歉使您的第一个Node.js脚本失败了,但是我想确保您确信在浏览器中运行JavaScript与在Node.js中运行JavaScript不同。)
根据堆栈跟踪,没有加载正确的Module
。 (模块是在浏览器中运行JavaScript和在Node.js中运行它之间的另一个主要区别。稍后将介绍更多模块。)要从Node.js获取类似信息,请将test.js的内容更改为:
console.log(process.versions)
console.log(process.arch)
console.log(process.platform)
再次输入node test.js
,您将看到与清单3类似的输出。
$ node test.js
{ http_parser: '1.0',
node: '0.10.28',
v8: '3.14.5.9',
ares: '1.9.0-DEV',
uv: '0.10.27',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1g' }
x64
darwin
现在,您已经在Node.js中成功运行了第一个脚本,是时候解决下一个主要概念:模块了。
您可以在JavaScript中创建单一用途的函数,但是与Java,Ruby或Perl不同,您无法将多个函数捆绑到可以导入和导出的内聚模块或“包”中。 当然,您可以使用元素包括任何JavaScript源文件,但是这种历史悠久的方法在两个关键方面没有适当的模块声明。
首先,使用元素包含的所有JavaScript都将加载到全局名称空间中。 使用模块,您可以在本地命名空间变量中沙箱导入的功能。 其次,更重要的是,您可以使用模块显式声明依赖关系,而使用
元素则不能。 结果,导入模块A也会以过渡方式导入从属模块B和C。 随着应用程序变得越来越复杂,可传递依赖项管理Swift成为一项至关重要的要求。
模块是JavaScript的下一个主要版本(ECMAScript 6)的一项备受期待的功能,但是在该版本被广泛采用之前,Node.js使用基于CommonJS规范的自己的模块版本。
通过使用require
关键字在脚本中包含CommonJS模块。 例如,清单4是Hello World脚本的略微修改版本,您可以在Node.js主页上找到。 创建一个名为example.js的文件,并将清单4中的代码复制到其中。
var http = require('http');
var port = 9090;
http.createServer(responseHandler).listen(port);
console.log('Server running at http://127.0.0.1:' + port + '/');
function responseHandler(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Hello World
');
}
键入node example.js
来启动新的Web服务器,然后在Web浏览器中访问http://127.0.0.1:9090 。
请看清单4中的前两行。您最有可能编写了简单的语句,例如var port = 9090;
数百次(或数千次)。 该语句定义了一个名为port
的变量,并为其分配了数字9090
。 就像在第一行中一样导入CommonJS模块( var http = require('http');
)确实没有什么不同。 它引入了http
模块,并将其分配给局部变量。 http
依赖的所有相应模块也都require
d。
example.js的后续行:
因此,在几行JavaScript中,您在Node.js中创建了一个简单的Web服务器。 正如您将在本系列的后续教程中学习的那样,Express扩展了这个简单的示例,以处理更复杂的路由并提供静态和动态生成的资源。
http
模块是所有Node.js安装的标准部分。 其他标准的Node.js模块启用文件I / O,从用户读取命令行输入,处理较低级别的TCP和UDP请求,等等。 请访问Node.js文档的“ 模块”部分,以查看标准模块的完整列表并了解其功能。
尽管其中包含的模块列表令人印象深刻,但与可用的第三方模块列表相比却显得苍白。 要访问它们,您需要熟悉另一个命令行实用程序:NPM。
NPM是节点打包模块的缩写。 要查看超过75,000个公共可用的第三方节点模块的列表,请访问NPM
网站 。 在网站上,搜索yo
模块。 图2显示了结果。
yo
模块的详细信息 结果页面为您提供了该模块的简要说明(“用于搭建Yeoman项目的CLI工具”); 过去一天,一周和一个月下载了多少次; 谁写的; 它依赖哪些其他模块(如果有); 以及更多。 最重要的是,结果页面为您提供了安装模块的命令行语法。
要从命令行获取有关yo
模块的类似信息,请键入npm info yo
。 (如果您尚不知道模块的正式名称,则可以键入npm search yo
来搜索名称中包含字符串yo
任何模块。) npm info
命令显示模块的package.json文件的内容。
每个Node.js模块都必须有一个格式正确的package.json文件与之关联,因此值得熟悉此文件的内容。 清单5、6和7展示了yo
的package.json的内容,分为三部分。
清单5中显示的第一个元素通常是name
, description
和可用versions
的JSON数组。
$ npm info yo
{ name: 'yo',
description: 'CLI tool for scaffolding out Yeoman projects',
'dist-tags': { latest: '1.1.2' },
versions:
[
'1.0.0',
'1.1.0',
'1.1.1',
'1.1.2' ],
要安装模块的最新版本,请键入npm install package
。 键入npm install package @ version
将安装特定版本。
接下来,如清单6所示,是作者,维护者和GitHub存储库,您可以在其中直接找到源。
author: 'Chrome Developer Relations',
repository:
{ type: 'git',
url: 'git://github.com/yeoman/yo' },
homepage: 'http://yeoman.io',
keywords:
[ 'front-end',
'development',
'dev',
'build',
'web',
'tool',
'cli',
'scaffold',
'stack' ],
在这种情况下,您还会找到一个指向项目主页的链接以及一个关联关键字的JSON数组。 并非每个package.json文件中都包含所有这些字段,但是用户很少抱怨与项目关联的元数据过多。
最后,您将看到带有显式版本号的依赖项列表,如清单7所示。这些版本号遵循主版本的通用模式。 次要版本 。 名为SemVer (语义版本控制)的补丁程序版本 。
engines: { node: '>=0.8.0', npm: '>=1.2.10' },
dependencies:
{ 'yeoman-generator': '~0.16.0',
nopt: '~2.1.1',
lodash: '~2.4.1',
'update-notifier': '~0.1.3',
insight: '~0.3.0',
'sudo-block': '~0.3.0',
async: '~0.2.9',
open: '0.0.4',
chalk: '~0.4.0',
findup: '~0.1.3',
shelljs: '~0.2.6' },
peerDependencies:
{ 'grunt-cli': '~0.1.7',
bower: '>=0.9.0' },
devDependencies:
{ grunt: '~0.4.2',
mockery: '~1.4.0',
'grunt-contrib-jshint': '~0.8.0',
'grunt-contrib-watch': '~0.5.3',
'grunt-mocha-test': '~0.8.1' },
该package.json文件指示必须将其安装在版本0.8.0或更高版本的Node.js实例上。 如果您尝试将npm install
在不受支持的版本上,则安装将失败。
除了平台要求之外,这个package.json文件还提供了一些依赖关系列表:
dependencies
块列出了运行时依赖关系。 devDependencies
块列出了开发过程中所需的模块。 peerDependencies
块使作者能够定义项目之间的“对等”关系。 此功能通常用于指定基础项目及其插件之间的关系,但是在这种情况下,它可以识别与Ye一起构成Yeoman项目的其他两个项目(Grunt和Bower)。 如果键入不带特定模块名称的npm install
,则npm
在当前目录中查找package.json文件,并安装我刚刚讨论的三个块中列出的所有依赖项。
安装有效的MEAN堆栈的下一步是安装Yeoman和相应的Yeoman-MEAN生成器。
作为Java开发人员,我无法想象如果没有构建系统(如Ant或Maven)就开始一个新项目。 同样,Groovy和Grails开发人员依赖于Gant(Ant的Groovy实现)或Gradle。 这些工具可以构建新的目录结构,即时下载依赖项,并准备项目进行分发。
在纯Web开发世界中,Yeoman满足了这一需求。 Yeoman是三个Node.js和纯JavaScript工具的集合,用于脚手架(Yo),管理客户端依赖项(Bower)和准备要分发的项目(Grunt)。 从检查清单7可以知道,多亏安装了package.json中的peerDependencies
块,Yo的安装使同行的Grunt和Bower peerDependencies
。
通常,您将键入npm install yo --save
来安装yo
模块并更新package.json中的dependencies
块。 ( npm install yo --save-dev
更新devDependencies
块。)但是Yeoman的三个对等模块并不是真正的特定于项目的-它们是命令行实用程序,而不是运行时依赖项。 要全局安装NPM软件包,请将-g
标志添加到install
命令。
在您的系统上安装Yeoman:
npm install -g yo
安装软件包后,键入yo --version
以验证它是否已启动并正在运行。
使用Yeoman和所有其他基础结构之后,就可以安装MEAN堆栈了。
您可以手工安装MEAN堆栈的每个部分。 值得庆幸的是,Yeoman通过其生成器提供了更简单的路径。
Yeoman生成器是引导新Web项目的最简单方法。 生成器提取基本包及其所有依赖项。 它通常包括具有所有相关插件的有效构建脚本。 很多时候,生成器还包括一个示例应用程序,并带有测试。
有超过1,000个Yeoman发电机可用。 其中一些由Yeoman核心开发人员编写和维护-在“作者”列中查找Yeoman团队。 但是大多数生成器是由社区编写的。
您将用来引导您的第一个MEAN应用程序的社区生成器被命名为MEAN.JS ,这并不奇怪。
在MEAN.JS主页上,单击Yo Generator菜单选项,或直接转到Generator页面,其中一部分如图3所示。
该页面的说明告诉您先安装Yeoman,这已经完成。 下一步是在全局安装MEAN.JS生成器:
npm install -g generator-meanjs
生成器到位后,就可以创建第一个MEAN应用了。 创建一个名为test的目录,将其插入cd
,然后键入yo meanjs
生成该应用程序。 回答清单8中所示的最后两个问题。(您可以为前四个问题提供自己的答案。)
$ mkdir test
$ cd test
$ yo meanjs
_-----_
| |
|--(o)--| .--------------------------.
`--------- | Welcome to Yeoman, |
( _ U`_ ) | ladies and gentlemen! |
/___A___\ '__________________________'
| ~ |
__'.___.'__
` | Y `
You're using the official MEAN.JS generator.
[?] What would you like to call your application?
Test
[?] How would you describe your application?
Full-Stack JavaScript with MongoDB, Express, AngularJS, and Node.js
[?] How would you describe your application in comma separated key words?
MongoDB, Express, AngularJS, Node.js
[?] What is your company/author name?
Scott Davis
[?] Would you like to generate the article example CRUD module?
Yes
[?] Which AngularJS modules would you like to include?
ngCookies, ngAnimate, ngTouch, ngSanitize
回答了最后一个问题后,随着NPM下载所有服务器端依赖项(包括Express),您会看到一系列活动。 NPM完成后,您会看到Bower下载了所有客户端依赖项(包括AngularJS,Bootstrap和jQuery)。
至此,您已经安装了EAN堆栈(Express,AngularJS和Node.js)—您所缺少的只是M(MongoDB)。 如果您现在输入grunt
在没有安装MongoDB的情况下启动应用程序,您将看到类似于清单9的错误消息。
events.js:72
throw er; // Unhandled 'error' event
^
Error: failed to connect to [localhost:27017]
at null.
(/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:546:74)
[nodemon] app crashed - waiting for file changes before starting...
如果您启动了该应用程序并看到此错误消息,请按Ctrl + C停止该应用程序。
现在,您将安装MongoDB,以便可以带走新的MEAN应用程序。
MongoDB是NoSQL持久性存储。 它不是用JavaScript编写的,也不是NPM软件包。 您必须单独安装它才能使MEAN堆栈完整且可用。
访问MongoDB主页 ,下载特定于平台的安装程序,并在安装MongoDB时接受所有默认设置。
安装完成后,键入mongod
以启动MongoDB守护程序。
MeanJS Yeoman生成器已经安装了一个名为Mongoose的MongoDB客户端模块; 您可以检查您的package.json文件进行验证。 在以后的部分中,我将详细介绍MongoDB和Mongoose。
安装并运行MongoDB之后,您终于可以启动MEAN应用并四处看看。
要启动新安装的MEAN应用程序,请确保您在运行MeanJS Yeoman生成器之前位于创建的测试目录中。 键入grunt
,应该看到类似于清单10所示的输出。
$ grunt
Running "jshint:all" (jshint) task
>> 46 files lint free.
Running "csslint:all" (csslint) task
>> 2 files lint free.
Running "concurrent:default" (concurrent) task
Running "watch" task
Waiting...
Running "nodemon:dev" (nodemon) task
[nodemon] v1.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: app/views/**/*.* gruntfile.js server.js config/**/*.js app/**/*.js
[nodemon] starting `node --debug server.js`
debugger listening on port 5858
NODE_ENV is not defined! Using default development environment
MEAN.JS application started on port 3000
jshint
和csslint
模块(均由生成器安装)确保源代码在语法上和样式上均正确。 nodemon
程序包会nodemon
文件系统中源代码的更改,并在检测到源代码更改时自动重新启动服务器,这对您快速,频繁地更改代码库而言,对于开发人员的工作速度是一个巨大的福音。 ( nodemon
程序包仅在开发阶段运行;要进行生产更改,必须重新部署应用程序并重新启动Node.js。)
如控制台输出所示,请访问http:// localhost:3000并带走新的MEAN应用。
图4显示了MEAN.JS示例应用程序主页。
单击菜单栏中的注册以创建新的用户帐户。 现在,填写Sign-up页面上的所有字段(如图5所示),然后单击Sign up 。 在以后的教程中,您将通过Facebook,Twitter等启用OAuth登录。
现在,您已经在本地MongoDB实例中存储了一组用户凭据,并且可以开始创建新文章。 单击“ 文章”菜单选项(直到您登录后才会显示),然后创建一些示例文章。 图6显示了Articles页面。
您已经为第一个MEAN应用程序命名了。 欢迎来到派对!
您在本教程中完成了很多工作。 您安装了Node.js并编写了第一个Node.js脚本。 您了解了模块,并使用NPM安装了多个第三方模块。 安装Yeoman是为了给您提供一个坚实的Web开发平台,其中包括一个脚手架实用程序(Yo),一个构建脚本(Grunt)和一个用于管理客户端依赖项的实用程序(Bower)。 您安装了MeanJS Yeoman生成器并使用它来创建您的第一个MEAN应用程序。 您安装了MongoDB和Node.js客户端库Mongoose。 最后,您运行了第一个MEAN应用程序。
下次 ,您将详细浏览示例应用程序的源代码,以便您可以看到MEAN太阳系中的四个行星MongoDB,Express,AngularJS和Node.js如何相互影响。
翻译自: https://www.ibm.com/developerworks/opensource/library/wa-mean1/index.html