AngularJS + CoffeeScript 前端开发环境布置详解

AngularJS 号称 ‘第贰框架’ (‘The first framework’)
确实是好好。由其从jQuery中完全转入AngularJS后就有孤掌难鸣离开他的感到了。纵然AngularJS的学习曲线很陡峭,入门的门路绝相比高,但那个付出都以值得的依赖用过的恋人都会与自个儿有同感吗。为什么作者这么
地偏爱AngularJS?
也许那样说吧,用AngularJS开发的话实际是给本人了一种工业化开发的概念,小编对软件工业化的浅显理解简单归纳为几点便是:

  • 自动化
  • 智能化
  • 重视品质
  • 重视工艺

前端开发比后端开发须求开发人员做越来越多混乱的事,例如:js和css
的回落、依赖引入、更新,图片压缩、“糖果语言(coffeescript/less/sass)”的语法检查与编写翻译、静态图片/静态网页压缩,单元测试、E2E测试、等等。这么些锁事往往很耗费时间间。

同时,当引入AngularJS作为主前端框架的话,大批量的js源文件管理对文本结构与模块结构合理规划就显得越来越之主要。所幸的是,google
是AngularJS工业化的新秀推手,为了充实前端开发人士的生产力他们也全力地做了累累干活,最为优良的就是[Yeoman|http://www.yeoman.io],他能相当慢地为我们建立各类别型项目标脚手架(项目模板),以她们的“最棒实践”为根基急忙地为我们做到那1层层繁琐的办事。

本人在实际上项目支付觉得官方提供的 angular
生成器并不是11分卓有作用,在经验了有些个品种的磨合后自个儿在 google 官方的
yeoman angular
脚手架项目上举行了部分定制与修改,也在此作1些享受,由于时日关系还未曾去将其成2个generator
所以只可以在此以博文格局共享了。

假定对Yeoman不驾驭也不用要,本文将会单独于yeoman
一步一步详细地解释什么布署1个得以用来生产AngularJS前端开发环境。

工具

以下那一个可谓是前端开发必备了,若是不知底具体用法那么就先请去他们的官网先脑补吗:

npm
Node的借助包管理工科具,能够到 [nodejs
官方下载|http://nodejs.org/download/]页面得到安装包。

** bower **

bower 是由twitter开发的客户端重视包管理工科具

npm install -g bower

** grunt **

自动化职责管理工科具,是任何自动化学工业程的为主。

npm install -g grunt-cli

安装此3大工具后大家就足以动手开首了。

贯彻的指标意义

  • 依照 CoffeeScript并帮助自动编写翻译
  • 能支撑 livereload(一但别的代码、财富发生改变浏览器会活动刷新)
  • 机关编写翻译 less
  • 扶助 ngdocs 从 CoffeeScript 自动提取注释生成 API文书档案网址
  • 机动 连接、最小化靜态财富,包涵:脚本、图片、网页
  • 活动将bower引入的借助包注入页面
  • 布局 Karma 的单元测试
  • 安顿基于 protractor 的e2e测试

主旨目录结构

以下是主导项目目录的组合以及各种目录的效力表达

项目目录/
├── app // 应用程序目录
│ ├── bower_components // bower 组件目录 (由 bower 生成)
│ ├── fonts // 字体
│ ├── images // 图片财富
│ ├── styles // 样式目录 可存放 .css 和 .less
│ └── scripts // 应用程序脚本
│ └── app.coffee // angularJS 应用程序文件
│ └── index.html // HTML HOME 文件
├── dist // 发表后的先后目录
├── test // 测试程序目录
│ ├── mocks // 存放mocks组件文件目录
│ ├── e二e // e二e测试文件目录
│ └── spec // 单元测试文件目录
├── node_modules // NodeJS 的零部件目录 (由 npm 生成)
├── docs // 存放生成文书档案
├── .tmp // 临时文件目录 (由 grunt 职责自动生成)
├── .bowerrc // bower 路径规则钦赐文件
├── conffeelint.json // CoffeeScript 语法检查规则
├── Gruntfile.js // grunt 配置文件
├── karma.conf.js // karma 配置文件
├── protractor.conf.js // protractor 配置文件
├── package.json // nodes 依赖包描述文件
└── bower.json // bower 信赖包描述文件

流程及原理

此项目环境首要提供三种重点的运作情势,分别适用于项面生命周期中的区别的时日,更准备地说应该是适用于差别的风貌。

浮动格局 – build

将全部的文书生成至产品交付目录 dist 内,执行李包裹蕴:

  • coffeescript/less
    • 编译
    • 连结
    • 压缩
    • 引用纠正,蕴含 angular 动态注入修正
    • 拷贝
  • 出口要求的静态文件
    • 网页
    • 图片
    • 字库
  • 出口注释文书档案并扭转文书档案网址

指令:
grunt build

测试格局 – test

多用于开发期,实行自动化单元测试或是e二e测试,考虑到e二e测试的采纳效用绝对于单元测试要低,故此
test指令只默许执行全数单元测试,
而要执行e贰e测试则需投入 e2e 参数作显然钦点。

指令:
grunt test

  • e2e –
    grunt test:e2e

万一投入 keepalive 参数的话,test
指令将间接运转于后台,且会检查评定全体的公文变化,壹但文件发出改变测试将会活动被重新履行。

那种状态多适用于测试程序的编撰与调节。

grunt test:keepalive

调节和测试情势 – debug

要害用于手工业调节和测试与HTML界面设计之用,当启用 debug 格局后,livereload
功能将会被电动载入,也正是具有 app 目录下的此外
变更都能被破获且浏览器能自动刷新应用更改。

指令:
grunt debug

Gruntfile.js 文件的安排性

第一需求设置 load-grunt-tasks 和 time-grunt 八个插件

    npm load-grunt-tasks --save-dev
    npm time-grunt --save-dev

基本的 Gruntfile.js

'use strict';

module.exports = function (grunt) {
    // 自动加载所有可用的grunt 任务
    require('load-grunt-tasks')(grunt);

    // 可以显示每个任务执行的实际时间,可以便于以我们优化任务
    require('time-grunt')(grunt);

    // 配置主要路径
    var config = {
        app: require('./bower.json').appPath || 'app',
        dist: 'dist',
        tmp: '.tmp',
        tasks: grunt.cli.tasks
    };

    grunt.initConfig({
        // 任务配置
    });

配置 CoffeeScript

率先是令CoffeeScript能支撑语法检查,须要安装
[coffeelint|http://www.coffeelint.org] 插件:

npm install coffeelint --save-dev

此插件安装后方可与老牌的
jshint一样将语法检查规则放在叁个单身的公文内,本项目中正是项目根目录下的
coffeelint.json
一经急需追加越多的CoffeeScript语法检查规则能够修改此文件 。

在Gruntfile.js内的安插如下:

coffeelint: {
    options: {
        configFile: 'coffeelint.json'
    },
    all: ['<%= config.app %>/scripts/**/*.coffee'], //检查应用程序目录下的 CoffeeScript脚本
    test: {
        files: {
            src: ['tests/**/*.coffee'] //检查所有测试脚本
        }
    }
}

接下来是安装CoffeeScript编译插件:
[coffee-script|http://github.com/jashkenas/coffeescript]

npm install grunt-contrib-coffee --save-dev

是因为大家编写翻译出来的 javascript
不会直接选取,因为还要开始展览一而再、压缩和拷贝进程,所以我们将富有的输出目录设置为
.tmp 目录。
在固然修改时也足以透过livereload
从.tmp目录直接将改成后的本子直接加载到浏览器内,方便调试之用。

还有少数须求特地提出的是 coffee 选项中本身将
sourceMap安装为true,唯有那些选项打开,当生成map文件后在浏览器调节和测试时才能可靠地将被减去后的
文本正确地重复照射至未压缩的程序源文件。关于 source
map的切切实实用法能够参考 [javascript source
map的使用|http://www.cnblogs.com/Ray-liang/p/4018162.html]
一文。

coffee: {
    options: {
        bare: false,
        sourceMap: true,
        sourceRoot: ''
    },
    dist: {
        files: [
            {
                expand: true,
                cwd: '<%= config.app %>/scripts',
                src: '{,*/}*.{coffee,litcoffee,coffee.md}',
                dest: '.tmp/scripts',
                ext: '.js'
            }
        ]
    },
    test: {
        files: [
            {
                expand: true,
                cwd: 'test/spec',
                src: '{,*/}*.coffee',
                dest: '.tmp/spec',
                ext: '.js'
            },
            {
                expand: true,
                cwd: 'test/e2e',
                src: '{,*/}*.coffee',
                dest: '.tmp/e2e',
                ext: '.js'
            }
        ]
    }
}

配置 Less

Grunt 提供了合法的less 编写翻译安装包
[grunt-contrib-less|https://github.com/gruntjs/grunt-contrib-less]

npm install grunt-contrib-less --save-dev

与布局coffee 编写翻译器的规律壹样大家要求将 styles 目录下的
.less文件预先编写翻译成为 .css并存放在 .tmp/styles下,以备后处理
和livereload 之用。

less: {
    all: {
        files: [
            {
                expand: true,
                flatten: true,
                cwd: '<%= config.app %>/styles',
                src: ['{,*/}*.less'],
                dest: '.tmp/styles',
                ext: '.css'
            }
        ]
    }
}

减掉与连接

在那有个别本人并不曾直接行使 Grunt 官方的 uglify,concat 而是接纳了 usemin
插件那是后续了 yo generator-angular 的做法。他是
yeoman项指标合法插件,那个插件同样是信赖于 uglify,concat
的,可是他扩展了对文件自动引用的援助,能够从页面读出脚本文件的引用而不是因此hardcore的办法写在Gruntfile中。此外,他还是能够充实对bower_components内的依赖举行合成而代替人工合成,那是1个很棒的功用能够节约大家从bower_components下找输出文件的麻烦,只需求关爱bower.json文件内管理包而不是在Gurntfile.js实行硬编码了。

usemin是一个合成包要求以下那个插件同时帮助,为了节约篇幅以下的授命都以以
npm install [包] --save-dev 格局安装

以下配置是从 generate-angular 中拷贝过来用的:

// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
    options: {
        dest: '<%= config.dist %>'
    },
    html: [
        '<%= config.app %>/index.html'
    ]
},

// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
    options: {
        assetsDirs: [
            '<%= config.dist %>',
            '<%= config.dist %>/images'
        ]
    },
    html: ['<%= config.dist %>/{,*/}*.html'],
    css: ['<%= config.dist %>/styles/{,*/}*.css']
},

// The following *-min tasks produce minified files in the dist folder
imagemin: {
    dist: {
        files: [
            {
                expand: true,
                cwd: '<%= config.app %>/images',
                src: '{,*/}*.{gif,jpeg,jpg,png}',
                dest: '<%= config.dist %>/images'
            }
        ]
    }
},

svgmin: {
    dist: {
        files: [
            {
                expand: true,
                cwd: '<%= config.app %>/images',
                src: '{,*/}*.svg',
                dest: '<%= config.dist %>/images'
            }
        ]
    }
},

htmlmin: {
    dist: {
        options: {
            customAttrAssign: [/\?=/],
            collapseBooleanAttributes: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            removeCommentsFromCDATA: true,
            removeEmptyAttributes: true,
            removeOptionalTags: true,
            removeRedundantAttributes: true,
            useShortDoctype: true
        },
        files: [
            {
                expand: true,
                cwd: '<%= config.dist %>',
                src: ['{,*/}*.html', 'views/{,*/}*.html', 'templates/{,*/}*.html'],
                dest: '<%= config.dist %>'
            }
        ]
    }
}

此间需求验证的是 app/index.html文件,也正是在配置中:

useminPrepare: {
    html: [
        '<%= config.app %>/index.html'
    ]
}

本条选项是给 usemin 插件去找脚本引用的,那里默许只是设定了 index.html
文件,因为那是四个Angular
SPA项目,所以惟有三个index.html文件作为主入口,尽管您具备七个例外的视图模板,而且所引用的
script 都不用壹样的话,能够将那些模板页明显地坐落那一个 html
数组选项中。

有关usemin的详细用法能够参考google的官方文书档案,以下只是对最常用的一部分开始展览教学,力求不去看官方这一个硕大的英文文书档案也能高效地采用起来。

打开 index.html :

<!doctype html>
<html ng-app="app">
<head>
    <meta charset="utf-8">
    <title>Project Title</title>
    <!-- build:css styles/vendor.css -->
    <!-- bower:css -->
    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="bower_components/fontawesome/css/font-awesome.css" />
    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:css styles/main.css -->
    <link rel="stylesheet" href="styles/main.css">
    <!-- endbuild -->

    <!-- build:js scripts/vendor.js -->
    <!-- bower:js -->

    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:js({.tmp,app}) scripts/index.js -->
    <!-- endbuild -->
    <base target="_blank">
</head>
<body ng-strict-di>
<div ui-view></div>
</body>
</html>

万一你丰富细心你会发觉此处有1对“与众分裂的”标记,<!--build:js--><!-- endbuild -->
<!--build:css--><!-- endbuild -->
骨子里这不是注释,他们实际是 usemin 的专用配置标记。在那之中
<!-- bower:js--><!--endbower--> 是另三个插件 bowerInstall 的
安顿标记,笔者会在下文再详尽讲解。

其壹标记其实极粗略将她翻译过来正是:<!-- build:类型[js|css] 生成的目标文件>,
源文件目录便是日前html所在的目录,假若要钦定多个
源目录能够通过<!-- build:类型({目录1,目录2}) 生成的目标文件>的法子钦点。

遵守那几个来掌握的话,这里的安装就会输出四个文本:

  • vendor.js //第叁方重视的合成缩小脚本
  • index.js //项目内的的合成收缩脚本
  • vendor.css //第一方信赖的合成压缩样式表
  • main.css //项目内的合成压缩样式表

好啊,先来说说 vendor.*,要是装了 bowerInstall
那么些插件在<!-- bower:类型 --><!-- endbower-->内的引用是由 bowerInstall
自动进入的,他加盟后会修改index.html源文件,大家不须求手工业参加。而对于1些比较坑爹的第一包,这里指的坑爹是他的末段输出文件放在一些怪异的深层目录中,而不是在她的颁发目录的根下,那么大家才须求手工业插足引用。如
ace-builds 那么些包,他的公告文件是在
ace-builds/src/ace.js,同时他又提供了ace-build/src-min/ace.js
文件,对于那类包我们就只好手工将具体的引用文件插手到 <!-- bower-->
标记内,不然bowerInstall是不通晓应该引用哪3个文书的。

而输出地方正是前方大家在 usemin选项中设定的:

useminPrepare {
    options: {
            dest: '<%= config.dist %>'
     }
}

也就是 项目目录/dist

接下去是 main.cssindex.js
,这多少个是从差别的源来生成的,main.css
没有钦赐源,所以她会在脚下的index.html所在地方中找 styles 目录也就是
项目目录/app/styles,那么具体须要引用那个自定的css(从前经过
less生成的)就在此设定。

诠释得越来越清楚壹些就是 若是有一个 app/styles/custom.less 文件,那么在
index.html内进入这些引用应该是:

<!-- build:css styles/main.css -->
  <link rel="stylesheet" href="styles/main.css">
  <link rel="stylesheet" href="styles/custom.css">
<!-- endbuild -->

虽说custom.css在设计期并不设有,但她会被less编写翻译器最后输出,所以引用时只要名字对了就行了。

同样的 build:js 的装置也是那理,只是这里增添了 .tmp
作源搜寻目录,正是说在 .tmp 找不到的源文件 能够到
app/scripts下找,反之亦然。

bowerInstall

联网上文,就是以此 bowerInstall
插件了,他正是能够从bower.json文件自动识别大家的连串引入了怎么着第3方依赖,然后就将借助的文书自动地流入到
<!--bower:js--><!--bower:css-->标记里面。

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

布署如下:

bowerInstall: {
    app: {
        src: ['<%= config.app %>/index.html'],
        ignorePath: '<%= config.app %>/'
    }
}

bowerInstall 有贰个替代品,叫 wiredep
,但以此插件很笨,平常汇合世引用错误的标题,所以那里依旧引进应用bowerInstall

Angular 的自行注重注入

接下去便是要为 Angular
环境作越发的配备了,首先要配备的是注重注入。先来看来来Angular官方推荐的正视性注入方法:

angular.main('myApp',[]).controller('MyCtrl',['$scope','$log','$http','$resource',($scope,$log,$http,$resource)->
    #我们的代码在此
])

只但是为借助注入大家实际是很无趣地编写这几个对应的白痴式引用,当然唯有一几个自然没什么难点,但万一级入得多了那么那么些概念就变得
颇为之难读。要是大家将上边的代码写成这么:

MyCtrl=($scope,$log,$http,$resource)->
 #控制器代码在此
 @

angular.main('myApp',[]).controller 'MyCtrl',MyCtrl

这么是或不是更便于读吧?为了落到实处那几个效用,大家得以应用
[ngAnnotate|https://www.npmjs.com/package/grunt-ng-annotate]
插件帮大家落到实处那
种动态式的插入,使得我们的代码可读性能够大大地充实。

npm install grunt-ng-annotate --save-dev

ngAnnotate:
{
    dist: {
        files: [
            {
                expand: true,
                cwd: '.tmp/concat/scripts',
                src: ['*.js', '!oldieshim.js'],
                dest: '.tmp/concat/scripts'
            }
        ]
    }
}

自动生成 Angular API 文书档案

那是三个自作者觉着很 Cool
的插件,他能一贯从源代码中央直机关接抽出注释并生成四个API参考网址,对于开发产品项目援救相当大。这些插件叫
[ngdocs|https://www.npmjs.com/package/grunt-ngdocs]

npm install ngdocs –save-dev

其1插件配置万分粗略,但她不能帮忙coffeescript,那么大家只能从变化的javascript文件作为注释文书档案生吴兴涵:

ngdocs: {
  all: ['.tmp/scripts/**/*.js']
}

关于 ngdocs 那个大旨未来作者会专门花时间再详尽写1篇小说来具体说美赞臣(Meadjohnson)下。

剧本模板

在运用Angular的 Routing、directive或是其余的插件,如 angular-ui
都恐怕应用到模板。如:

MyDirective=->
  restrict:'E'
  tempalteUrl:'scripts/directives/MyDirective.tpl.html'

angular.module('myApp').directive 'MyDirective',MyDirective

对此使用了 tempalteUrl
钦命的沙盘是心有余而力不足在Karma的测试中找到的,因为jasmine只好找到脚本而无法找到html文件。那样壹来就会令得
directive 成为多个不行测试的构件。能够动用
[html2js|https://github.com/karlgoldstein/grunt-html2js]
解决那1标题(angularJS官方推荐)。这么些插件的最大效果是将html文件一直编写翻译为js文件,而无须要改变我们的源代码,那样一来既可在测试上消除那个标题也得以将html模板文件封装为可颁布的剧本(如若您仔细一点会发觉
angular-ui 就是样做的,angular-ui-tpl.js 就是模板文件)。

npm install grunt-html2js --save-dev

其一布局会有点点复杂

html2js: {
    options: {
        base: 'app',
        target: 'coffee',
        module: 'myApp.templates', //模板会生成至模块内,需要明确指定模块的名称
        singleModule: true,
        useStrict: true,
        htmlmin: {
            collapseBooleanAttributes: true,
            collapseWhitespace: true,
            removeComments: true,
            removeEmptyAttributes: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true
        }
    },
    main: {
        src: ['<%= config.app %>/scripts/**/*.tpl.html'],
        dest: '<%= config.app %>/scripts/templates.coffee'
    }
}

有几点在选用时索要专注:

  1. 那里只检查实验 app 目录下具有的以
    *.tpl.html结尾的HTML文件(视为模板文件)
  2. 以此文件会生成至源目录(app/scripts/)下的templates.coffee
    待coffee编写翻译实行后甩卖
  3. 在 app.coffee 文件内需求显然地引入由 module
    所钦命的模版模块,不然会引用退步

除此以外思虑到本文的篇幅问题,那里就略过了 copy, watch 和 connect
八个非凡常用的天职布置,具体的能够从本文内附的源代码内参考。

karma

Karma runner
应该属于时下最风靡的测试运维器之一了。他的布署在Gurnt貌似很简单,而然事实并非如此。他有单独的布局文件在本项目中为karma.conf.js,他的布署选项相比较多在此就不1一地详细表明了,那里笔者是将Karma配置成能支撑
coffee script并依照 [PhantomJS|http://phantomjs.org]
作为宿主浏览器,以 [jasmine|http://jasmine.github.io/]
作为测试运营架构的的单元测试环境。全数的单元测试文件存放在 test/spec
目录下。

她索要的借助插件分别有:

  • karma-coffee-preprocessor
  • karma-coverage
  • karma-jasmine
  • karma-junit-reporter
  • karma-chrome-launcher
  • karma-phantomjs-launcher
  • karma-requirejs
  • karma-story-reporter

设置后的配置如下:

karma:
 {
    unit: {
        configFile: 'karma.conf.js',
        singleRun: true
    }
}

此地需求专注的是,在 karma.conf.js 配置的文书的 filesexclude
八个挑选,files 内须求配备1体项目运维期
内需利用的 bower 重视包,如:

files: [
            'app/bower_components/angular/angular.js',
            'test/spec/{,*/}*.coffee'
       ]

如运用到此外的angular插件引用必要在此投入,则会也许会造成单元测试因找不到依靠包而导致注入失利。

exclude 就自然是无须要加载的公文。

出于国内网络环境难题 安装 phantomJS
恐怕会偏慢,固然无法下载phantomJS能够将其删除,而使用 chrome 代替。

protractor

对于e二e测试(白盒测试/集成测试)也得以行使Karma+angular-scenario来布局,但以此在AngularJS官方已当做过时配置而不被推举。取而代之的当然是
[protractor|http://angular.github.io/protractor/#/]
他为jasmine所增添的matcher很多,用起来确实是
很好用。可是 protractor
大概相比较新吧(发展了才一年多的时间)他的设置包下载是极其慢的,由其是
[selenium|http://www.seleniumhq.org]的安装。

她的布署有点像 karma 也是由此1个表面包车型客车protractor.conf.js文件作为额外的叠加配置的,在 Gruntfile.js 内:

protractor: {
    options: {
        keepAlive: true,
        configFile: "protractor.conf.js"
    },
    all: {}
}

但是值得1谈的是他所注重的 Webdriver 的设置进程。

安装protractor包

npm install protractor --save-dev

protractor 安装后会得到3个 webdriver-manager 的命令行工具。protractor
依赖于 selenium 服务器,且selenium是多少个基于java开发的,so
从前则须要先安装好JDK。

别的 protractor 只可以支持 chrome 和 ie 二种浏览器驱动,须要在成就
protractor安装后手动运行:

webdriver-manager update

不知是否人品难题(作者相对不以为天朝的互连网不平日的),那几个命令本人是总运维不成功!那些命令会从
google的官网上下载一个chrome的效仿驱动程序至本机的/usr/local/lib/node_modules/protractor/selenium/chromedriver/
目录,假如你的格调与笔者一样,也是心有余而力不足下载的话,那么你可以直接在google上下来载
[chromedriver|https://sites.google.com/a/chromium.org/chromedriver/]
的驱动然后手工业解压到这么些地面目录下即可。(BTW
作者的环境是OSX,在Linux下本身不领悟是哪些情况,试过的情侣请给自个儿留言作为补偿吧)

出于各样的不成事,最终我是一向将 protractor
的安顿指向本相对目录地址的,要是你有壹致的图景出现就将以下的八个布局出席到protractor.conf.js中吗

seleniumServerJar: '/usr/local/lib/node_modules/protractor/selenium/selenium-server-standalone-2.44.0.jar',
chromeDriver: '/usr/local/lib/node_modules/protractor/selenium/chromedriver/'

protractor 有有些相比好的是能够与 WebStorm 以下是有血有肉安顿的不二等秘书诀:

图片 1

WOO

轻率写了如此长壹篇,光是附上小说貌似不太卓绝,那么只要对那一个脚手架项目有趣味的情人请到[我的
github|http://www.github.com/dotnetage/]上下载那个项目吧。项目地址是:https://github.com/DotNetAge/Angular-CoffeeScript-Seed。下载后,须求各自运营

sudo npm install
bower install

对本文所述的包实行1回性安装。权且还没时间将以此包写成 Yeoman Generator
,不过饭依旧一口一口吃啊,大概你能够平素Fork这些项目噢。

相关文章