什么是Yeoman
应该很多人都知道Yeoman这个词了,也大概知道它是用来做什么的了。如官方文档所述:”Yeoman 1.0版本不仅仅是一个工具,它还是一个工作流;一个让web开发和谐甚至变得更好的工具和最佳实践的集合。” 这次简单的Yeoman实践主要用来体现其工作流的特性。
实践背景
在Django项目的开发过程中,Django会生成项目的脚手架,可以让开发者很方便快速地开始到项目的实战过程中。 前端作为日益重要的一个开发环节,特别是单页应用,需要引入各种各样的第三方组件,还要对这些框架的版本进行控制。如果每一次都要通过复制粘贴的方式来实现,不是不可以,但是既然有了Yeoman,为什么不选择它,这一种更加优雅的实践方式呢? 需要达成的目标很简单,就是通过bower下载需要的第三方组件,然后通过grunt将其build好的文件复制到Django项目的静态文件目录中。
简单实践
请确定你已经安装了Nodejs,Git. 安装yo grunt bower
npm install -g yo grunt-cli bower
准备生成器
npm isntall generator-generator
开始一个生成器
mkdir ~/dev/generator-django && cd $_
Yo会在创建过程中询问你一些问题,以便你更好地描述你正在编写的生成器。 在生成器创建成功后,赶紧试试吧!
npm link cd ~/dev/generator-django-backgroun && cd $_ yo django
是不是已经出现了文件的雏形了? 如果想达成刚才想要实现的目标,那么我们还得继续。现在回到刚才的generator-django目录,这里是不是又一个app文件夹,这里我们可以看到下图所示目录。
index.js 这就是生成器的核心部分。暂时我们不需要管太多,找到askFor和app这两个函数,改成如下代码
DjangoGenerator.prototype.askFor = function askFor() { var cb = this.async(), self = this; console.log(this.yeoman); var prompts = [{ name: 'name', message: 'Would you like your app to be called?', default: 'App' }]; this.prompt(prompts, function (props) { this.name = props.name; cb(); }.bind(this)); }; DjangoGenerator.prototype.app = function app() { this.copy('_package.json', 'package.json'); this.copy('_bower.json', 'bower.json'); this.copy('_Gruntfile.json', 'Gruntfile.json'); };
回头看看刚才修改的代码,这里我们需要了解两个点,虽然你可以去查文档来了解这是什么意思,我还是在这里啰嗦一下。 this.prompt如其字面意思一样,一个简单的询问交互方式,以便我们让一会儿生成的模板更加个性化。在此我只是简单地对name进行了交互,参考文档你还写出更加个性化的模板。 this.copy是将templates里面的模板复制到当前Django项目中来。templates里面的模板我们可以对其加入一些个性化的标签。例如_bower.json
{ "name": "<%= name %>", "version": "1.0.0", "main": "path/to/main.css", "ignore": [ ".jshintrc", "**/*.txt", "**/.*", "node_modules", "bower_components", "test", "tests" ], "dependencies": { "jquery": "*", "backbone": "*", "underscore": "*", "requirejs": "*", "bootstrap": "*" }, "description": "", "license": "MIT" }
<%= name %>就是刚才在prompt中交互得来的值,其他的值也可以通过这种方式个性化。 这样,一个简单的generator就实现了。不过我的目标还没达到,还需要对bower和grunt进行配置才可以。 _bower.json中的代码刚才你已经看过了,项目中需要的jquery,backbone,underscore,requirejs,bootstrap作为依赖存在,在一会儿执行yo django的时候,这些依赖会自动下载到bower_components文件夹中,目录结构如下图
此时的backbone.js,underscore.js,jquery.js等文件分散在各个文件夹中,如何才能更加方便地将它们放到static里对应的目录呢?这个时候就需要grunt出马了,同样是需要配置,我们需要对_Gruntfile.js进行配置,要实现刚才的目标主要需要用到grunt-contrib-copy这个插件,然后对任务进行注册一下就可以了,详细资料你可以到grunt官方获得,_Gruntfile.js的代码如下
'use strict'; module.exports = function(grunt) { // Project configuration. grunt.initConfig({ copy: { main: { files: [ {src: ['bower_components/backbone/backbone.js'], dest: '../static/js/libs/backbone.js'}, {src: ['bower_components/jquery/jquery.js'], dest: '../static/js/libs/jquery.js'}, {src: ['bower_components/requirejs/require.js'], dest: '../static/js/libs/require.js'}, {src: ['bower_components/underscore/underscore.js'], dest: '../static/js/libs/underscore.js'}, {src: ['bower_components/bootstrap/dist/js/bootstrap.js'], dest: '../static/js/libs/bootstrap.js'}, {src: ['bower_components/bootstrap/dist/css/bootstrap.css'], dest: '../static/css/bootstrap.css'} ] } } }); // These plugins provide necessary tasks. grunt.loadNpmTasks('grunt-contrib-copy'); // Default task. grunt.registerTask('default', ['copy']); };
一个简单的Yeoman实践就完成了。 这个时候只需要依次输入
yo django grunt
It works!