前端开发环境搭建 Grunt Bower、Requirejs 、 Angular

如今web开发的趋势是先后端分离。前端采用某些js框架,后端采用某些语言提供restful API,二者以json格式进行数据交互。javascript

若是后端采用node.js,则先后端可使用同一种语言,共享某些可重用的Js代码,并共享构建工具。但不少时候咱们可能采用别的语言,如ruby/java/scala等,此时先后端代码基本上是彻底独立的。虽然你们都在同一个项目中,但能够分红互相独立的两块,而且先后端一般使用不一样的构建工具。css

好比当后端使用Scala时,咱们会使用sbt进行项目构建,对scala代码进行编译、测试、打包等。它的专长是处理与scala相关的任务,但对于前端的支持比较弱。前端一些常见的任务,如js库的下载和管理、css文件的转换、js文件合并压缩、js测试的执行等,很难在sbt中找到好用的插件,而利用js世界里的工具来作反而更加方便一些。html

咱们项目组这几天正在讨论是否在项目中引入一些前端框架,仍是直接用原生Javascript写。通过反复讨论和调研,最终决定引入AngularJs。但AngularJs的引入并非单一的任务,由于咱们还须要考虑前端代码的测试、依赖管理等,都须要有相应的工具支持,因此最后引入了这么一整套工具:前端

  1. Grunt – Js任务管理工具,经过各类插件对项目进行各类操做,好比文件转换、运行测试、打包部署等。至关于java里的ant/maven/gradle,ruby中的rack,scala中的sbt。
  2. Bower – Js库依赖管理工具。当你须要jquery时,不须要手动下载,只须要执行bower install jquery
  3. RequireJs – Js库加载管理,及模块化支持。能够按需及并行加载js库,能够把咱们的代码以模块化的方式组织。
  4. AngularJs – Js前端框架,支持依赖注入,双向绑定等我认为很重要的功能

这套东西都是比较基础且使用比较普遍的。通常一旦在项目中引入前端框架,或者须要写比较多的Js代码时,咱们都会采用它们,因此颇有必要学习并掌握它们。java

各工具都至关的独立

在开始前,须要先提示一下,在javascript的世界里,不少东西都是由社区提供的,因此每一种工具都至关独立。好比,不少工具都有着本身独立的配置文件,本身的命令行参数,有时候还须要有一些额外的插件把两个工具结合起来。node

因此下面将会有不少比较琐碎的命令,咱们须要一一了解。不过好在咱们一旦了解了,下次就可使用已经配置好的文件,经过几条命令将把有的东西都准备好,很方便。python

安装nodejs

在Mac中,咱们可使用brew来安装。在其它系统下,请使用相应的工具或直接到官网下载。jquery

brew install node

Nodejs可让咱们在服务器端使用javascript编程,它是不少js工具的基础。若是你已经安装,请确保使用最新版本:git

brew upgrade node

查看版本:angularjs

node -v

我这里显示:

v0.10.28

npm

Npm是node官方提供的包依赖管理工具。咱们下面使用的grunt等,都是以插件形式下载安装的。

当咱们安装好nodejs后,npm就自动可用了。

查看版本:

npm -v

我这里显示:

2.0.0-alpha-5

建立项目目录

下面咱们从零开始,首先在任意位置新建一个目录做为咱们的项目根目录,好比:

mkdir ~/myproject

而后进入该目录:

cd ~/myproject

后面的命令都将在项目根目录下操做。

为npm建立package.json

首先咱们须要为npm提供一个package.json,告诉它咱们的项目信息,特别是项目中将会使用的插件。咱们不须要手动建立,由于能够直接调用如下命令:

npm init

它会问咱们一些问题,咱们能够按需回答,也能够所有使用默认值,反正之后能够改起来也很容易。

最后将会产生以下的package.json文件:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "https://github.com/freewind/grunt-bower-angular-demo.git" }, "author": "", "license": "BSD", "bugs": { "url": "https://github.com/freewind/grunt-bower-angular-demo/issues" } }

对于像咱们这样的非nodejs项目来讲,里面的大部份内容都没用,能够删掉大部分,只剩下:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0" }

安装 grunt

npm install grunt --save-dev

将使用npm下载grunt插件,它们将保存到项目根目录下的node_components目录下。

后面的--save-dev参数是说,把这个插件信息,同时添加到package.jsondevDependencies中:

"devDependencies": { "grunt": "~0.4.5" }

因为grunt仅在开发阶段使用,因此使用--save-dev。若是是运行时使用的,则用--save

安装 grunt-cli

上面安装的grunt并不包含命令行工具,咱们还需安装相应的grunt-cli,才能在命令行中调用grunt命令:

npm install grunt-cli -g

后面的-g是说,把grunt-cli安装成全局工具,以便在任意目录下使用。

安装后,输入:

grunt --version

我这里显示为:

grunt-cli v0.1.13 grunt v0.4.5

在比较少的状况下,可能提示找不到grunt,则须要根据安装grunt-cli时的提示信息,把相应的路径添加到PATH中:

echo PATH=$PATH:/your/path/to/grunt >> ~/.bashrc source ~/.bashrc

为grunt建立配置文件Gruntfile.js

安装grunt-init

npm install grunt-init -g

下载grunt模板

git clone https://github.com/gruntjs/grunt-init-gruntfile.git ~/.grunt-init/gruntfile

生成Gruntfile

grunt-init gruntfile

根据须要回答问题,或者使用默认值,将获得如下Gruntfile.js文件:

/*global module:false*/ module.exports = function(grunt) { // Project configuration. grunt.initConfig({ // Metadata. pkg: grunt.file.readJSON('package.json'), banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', // Task configuration. concat: { options: { banner: '<%= banner %>', stripBanners: true }, dist: { src: ['lib/<%= pkg.name %>.js'], dest: 'dist/<%= pkg.name %>.js' } }, uglify: { options: { banner: '<%= banner %>' }, dist: { src: '<%= concat.dist.dest %>', dest: 'dist/<%= pkg.name %>.min.js' } }, jshint: { options: { curly: true, eqeqeq: true, immed: true, latedef: true, newcap: true, noarg: true, sub: true, undef: true, unused: true, boss: true, eqnull: true, browser: true, globals: { jQuery: true } }, gruntfile: { src: 'Gruntfile.js' }, lib_test: { src: ['lib/**/*.js', 'test/**/*.js'] } }, qunit: { files: ['test/**/*.html'] }, watch: { gruntfile: { files: '<%= jshint.gruntfile.src %>', tasks: ['jshint:gruntfile'] }, lib_test: { files: '<%= jshint.lib_test.src %>', tasks: ['jshint:lib_test', 'qunit'] } } }); // These plugins provide necessary tasks. grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-watch'); // Default task. grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); };

它里面已经包含了一些经常使用的插件,好比grunt-contrib-jshint等,咱们可根据须要删减一些用不上的。

它同时还会在package.json里添加上这些插件的依赖:

"grunt-contrib-concat": "~0.4.0", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-qunit": "~0.5.2", "grunt-contrib-uglify": "~0.5.0", "grunt-contrib-watch": "~0.6.1"

这些插件还未下载,若是须要,能够运行:

npm install

把它们下载到本地

bower

npm install bower -g

package.json

{ "engines": { "node": ">= 0.10.0" }, "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-watch": "~0.6.1", "grunt-contrib-qunit": "~0.5.2", "grunt-contrib-concat": "~0.4.0", "grunt-contrib-uglify": "~0.5.0" } }

安装bower

bower跟npm在某种意义上类似,它是用来管理经常使用的js库的依赖的,好比jquery, underscore, angularjs等。

咱们能够经过npm安装它:

npm install bower -g

把它装为全局工具

为bower生成配置文件bower.json

bower也有它本身的配置文件bower.json,咱们不须要手动建立。

bower init

将会生成以下的bower.json:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0", "homepage": "https://github.com/freewind/grunt-bower-angular-demo", "authors": [ "Peng Li <nowind_lee@qq.com>" ], "license": "MIT", "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ] }

对于咱们的项目来讲,里面的东西基本上都没用。有用的是后面将会出现的dependencies

下载requirejs、jquery、angularjs

bower insall requirejs --save bower insall jquery --save bower install angularjs --save

将会自动下载jquery到angularjs相应的文件,到项目根目录下的bower_components目录。并在bower.json中添加:

"dependencies": { "angularjs": "~1.2.20", "jquery": "~2.1.1", "requirejs": "~2.1.14" }

安装grunt-bower-task

bower只负责把依赖下载到本地的bower_components目录,并不负责把它们拷贝到咱们项目中实际使用的地方,好比public/js/lib目录下。

为了实现这样的功能,咱们还须要另外一个插件的帮助:

npm install grunt-bower-task --save-dev

而后打开其文档:https://www.npmjs.org/package/grunt-bower-task ,按照上面的提示进行配置。

首先在Gruntfile中合适位置添加:

grunt.loadNpmTasks('grunt-bower-task');

而后在grunt.initConfig({...})参数中,添加相应的配置项:

bower: { install: { options: { targetDir: './public/js/lib', layout: 'byComponent', install: true, verbose: false, cleanTargetDir: false, cleanBowerDir: false, bowerOptions: {} } } }

这里指定拷贝的目标目录为public/js/lib,且文件按照模块分红单个目录(byComponent)。若是想把全部的js放在同一个目录,全部的css文件放在同一个目录,则使用byType

关于RequireJs

在前面咱们已经使用bower安装了requirejs:

bower install requirejs

RequireJs可用来管理页面中使用的js库之间的依赖关系,能够按需、并行、延迟加载js库。同时它可让咱们以模块化的形式组织js代码。

强烈建议先了解RequireJs的运行原理再动手写代码,否则确定会遇到各类坑。RequireJs的文档写得有点绕,可参考个人另外一篇文章:TODO

配置RequireJs

前面咱们第三方的依赖,经过grunt-bower-task拷贝到了public/js/lib目录下。咱们本身写的js,将会放置在public/js目录下。

咱们须要手动建立一个config.js文件,用来配置和初始化requirejs。

在HTML中引入requirejs

若是咱们使用了requirejs,则在HTML中,咱们一般只须要一个<script src="http://freewind.me/blog/20140727/..."></script>标签引入requirejs并指定入口文件便可,而不须要写多个script标签手动加载其它js文件。

在HTML中合适位置加入:

<script src="http://freewind.me/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script>

这里首先加载了require.js,并经过data-main属性告诉requirejs:当你加载完之后,请加载config.js文件进行初始化。

config.js

config.js内容以下:

requirejs.config({ baseUrl: '/public/js', paths: { app: 'app', jquery: 'lib/jquery/jquery', angular: 'lib/angularjs/angular' }, shim: { } }); requirejs(['app'], function(app) { app.hello(); });

咱们在paths中声明了几个模块,其中的app是咱们本身建立的js文件,用于放咱们本身的业务代码,它对应于/public/js/app.jsjqueryangular对应的文件是咱们使用grunt-bower-task拷贝过来的第三方js库。

shim中用来处理一些没有遵照requirejs规范的js库,好比underscore之类。可在里面对它们进行一些依赖声明、初始化操做等。这里暂时用不上。

最后用requirejs来导入咱们本身的模块,可在后面的callback中拿到对应模块的实例,并对它进行一些操做,好比咱们调用了app.hello()方法。

app.js

为了让这个例子完整,咱们能够定义相应的app.js:

define([], function() { return { hello: function() { alert("hello, requirejs"); } } });

index.html

为了能让例子跑起来,咱们还须要建立一个public/index.html,内容以下:

<html> <head> <script src="http://freewind.me/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script> </head> <body> <div>Hello, world!</div> </body> </html>

启动 web server

进入项目根目录,运行:

grunt bower

把bower下载的js库拷贝到public/js/lib下。

而后启动web server:

python -m SimpleHTTPServer

最后打开浏览器,访问:

http://localhost:8000/public/index.html

若是一切正常的话,会看到弹出一个提示框,上面内容为:

hello, requirejs

Angularjs

而后咱们作一个简单的angular的例子。

因为angularjs并非按requirejs的模块方式组织代码的,咱们须要在config.js中添加:

shim: { angular : { exports : 'angular'} }

Angularjs会在全局域中添加一个名为angular的变量。咱们必须在shim中显式把它暴露出来,才能经过模块注入的方式使用它,好比:

define(['angular'], function(ng) { // we can use argument `ng` instead of gloabl `angular` now });

在index.html中添加angular代码

<div ng-controller="MyController"> <input type="text" ng-model="name" /> <span>{{name}}</span> </div>

准备相应的controller

app.js的内容改成:

define(['angular'], function(angular) { angular.module('myApp', []) .controller('MyController', ['$scope', function ($scope) { $scope.name = 'Change the name'; }]); angular.element(document).ready(function() { angular.bootstrap(document, ['myApp']); }); });

在这段代码里,我定义了一个angularjs本身的模块myApp,以及相应的MyController。在后面,经过angular.bootstrap方法,把该模块与document结合在了一块儿。

启动web server,就能够看到效果了。当咱们修改了页面上输入框里的内容,它旁边的文字也会跟着改变。

修改angularjs的占位符

在html中显示angularjs里的一个字段时,咱们使用{{}}来占位,好比:

<span>{{name}}</span>

若是咱们同时使用了mustcahe模板,就会有冲突。咱们能够更改angularjs的配置:

angular.module('myApp', []).config(function($interpolateProvider){ $interpolateProvider.startSymbol('[[').endSymbol(']]'); } );

而后咱们就能够写成:

<span>[[name]]</span>

了.

项目代码

上面的操做,都在这个项目中: https://github.com/freewind/grunt-bower-angular-demo

另外,关于requirejs/angularjs的结合使用,能够参看这个比较好的样板项目: https://github.com/tnajdek/angular-requirejs-seed

相关文章
相关标签/搜索