Yeoman Grunt Bower配置相关

声明,以下相关全是前端的东西。


  • Yeoman 一个自动化工作流,说白了就是把一些你需要手动操作的东西,自动给你做好。


我的理解就是给你创建一个项目,然后里面该有的东西都有了。


官网:http://www.yeoman.io/


  • Grunt 什么?大G?,其实不是的。


一个类似maven的东西(不知道maven?,那总知道ant吧),能够对前端的文件进行压缩,打包,还有部署,(应该不叫部署,叫整理,更合适一些)。


官网:http://gruntjs.com/


grunt的强大,在于可以有很多第三方的插件可以下载,例如less,coffeescripe等等,grunt可以帮助你自动编译这些文件。


  • Bower 一只肥鸟大笑,官方说法叫做A package manager for the web,也就是包管理器。


自我感觉不是很好用,比如你需要用jquery,它会把jquery相关的文件全部下载,例如jquery.cokkie.js等,不仅浪费时间,还占用空间。


下面来讲解,这三样东西的具体配置:


安装Yeoman


//首先,你可以执行 sudo npm install -g yo grunt-cli bower 这样可以一下安装3个文件,当然你也可以选择不装。。



先得安装Node.js,Git和Ruby,不要问为什么,官网说的。。。


npm install -g yo

创建一个project目录,定位在该目录下


然后安装generator-webapp,这也东西使用来生成器的,也就是能够生成你app的程序


npm install -g generator-webapp
-g 的意思是全局安装,这样的话你就可以在任何地方使用yo命令了。


默认情况下会让你选择webapp所用的框架,例如




可以多选,也可以单选,选择后生成的相关配置文件也会根据你的选择来改变,所以这一配置要慎重。


这样,yeoman就装好了。

让你想执行bower命令时,发现报错,因为你还没装bower。。


安装Bower


npm install -g bower
这个很简单,先装上再说,具体用法,下面会讲。


安装Grunt


npm install -g grunt-cli

cli并不是grunt,只是一个能够让你执行grunt命令的程序


接下来安装grunt


npm install -g grunt

回到你建的project目录,装完之后可以看到 目录下会有一个Gruntfile.js文件,


这个是grunt的核心文件,也是这三样东西交互的文件。应该是下面这个样子


// Generated on 2014-04-08 using generator-webapp 0.4.8
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    // Define the configuration for all the tasks
    grunt.initConfig({

        // Project settings
        config: {
            // Configurable paths
            app: 'app',
            dist: 'dist'
        },

        // Watches files for changes and runs tasks based on the changed files
        watch: {
            bower: {
                files: ['bower.json'],
                tasks: ['bowerInstall']
            },
            js: {
                files: ['<%= config.app %>/scripts/{,*/}*.js'],
                tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            jstest: {
                files: ['test/spec/{,*/}*.js'],
                tasks: ['test:watch']
            },
            gruntfile: {
                files: ['Gruntfile.js']
            },
            styles: {
                files: ['<%= config.app %>/styles/{,*/}*.css'],
                tasks: ['newer:copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: '<%= connect.options.livereload %>'
                },
                files: [
                    '<%= config.app %>/{,*/}*.html',
                    '.tmp/styles/{,*/}*.css',
                    '<%= config.app %>/images/{,*/}*'
                ]
            }
        },

        // The actual grunt server settings
        connect: {
            options: {
                port: 9000,
                livereload: 35729,
                // Change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    open: true,
                    base: [
                        '.tmp',
                        '<%= config.app %>'
                    ]
                }
            },
            test: {
                options: {
                    port: 9001,
                    base: [
                        '.tmp',
                        'test',
                        '<%= config.app %>'
                    ]
                }
            },
            dist: {
                options: {
                    open: true,
                    base: '<%= config.dist %>',
                    livereload: false
                }
            }
        },

        // Empties folders to start fresh
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= config.dist %>/*',
                        '!<%= config.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
            options: {
                jshintrc: '.jshintrc',
                reporter: require('jshint-stylish')
            },
            all: [
                'Gruntfile.js',
                '<%= config.app %>/scripts/{,*/}*.js',
                '!<%= config.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },

        // Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

        // Add vendor prefixed styles
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

        // Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                ignorePath: '<%= config.app %>/'
            }
        },

        // Renames files for browser caching purposes
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

        // 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: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true,
                    removeCommentsFromCDATA: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true
                },
                files: [{
                    expand: true,
                    cwd: '<%= config.dist %>',
                    src: '{,*/}*.html',
                    dest: '<%= config.dist %>'
                }]
            }
        },

        // By default, your `index.html`'s <!-- Usemin block --> will take care of
        // minification. These next options are pre-configured if you do not wish
        // to use the Usemin blocks.
        // cssmin: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

        // Copies remaining files to places other tasks can use
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*',
                        'bower_components/bootstrap/dist/fonts/*.*'
                    ]
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

        // Run some tasks in parallel to speed up build process
        concurrent: {
            server: [
                'copy:styles'
            ],
            test: [
                'copy:styles'
            ],
            dist: [
                'copy:styles',
                'imagemin',
                'svgmin'
            ]
        }
    });


    grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'autoprefixer',
            'connect:livereload',
            'watch'
        ]);
    });

    grunt.registerTask('server', function (target) {
        grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
        grunt.task.run([target ? ('serve:' + target) : 'serve']);
    });

    grunt.registerTask('test', function (target) {
        if (target !== 'watch') {
            grunt.task.run([
                'clean:server',
                'concurrent:test',
                'autoprefixer'
            ]);
        }

        grunt.task.run([
            'connect:test',
            'mocha'
        ]);
    });

    grunt.registerTask('build', [
        'clean:dist',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'cssmin',
        'uglify',
        'copy:dist',
        'rev',
        'usemin',
        'htmlmin'
    ]);

    grunt.registerTask('default', [
        'newer:jshint',
        'test',
        'build'
    ]);
};

这是系统默认生成的,当时我选择的是bootstrap。


可以看到,文件中的每个配置项都是一个task,并且每一个task都是需要下载grunt插件的。


require('load-grunt-tasks')(grunt);

这段代码很重要,他会找到项目下的node_modules文件夹,具体说应该是package.json文件,把其中的grunt插件全部引入。 所以package.json文件和node_moudles要完全对应


接下来便可以执行grunt serve命令了


执行完毕后是否看到浏览器自动打开,而且访问localhost 9000端口,如果不是,那么回去检查一下是否配置有错。


grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'autoprefixer',
            'connect:livereload',
            'watch'
        ]);
    });

上面说的grunt serve命令就是上面这段代码执行的。


可以看到这个serve命令还接受一个参数target,如果执行grunt serve:dist 就会执行build task还有connect下的dist下的 keeplive task。


在这说明一下如果grunt 某个task时没有传target,会默认寻找第一个target的task。


如果不传参数,正常执行if外面的命令,最后也个watch task很关键,会启动一个临时server来给你debug用,会监听你的每个文件是否改变来刷新你的浏览器(livereload task配

置相关),很智能吧。


关于livereload可以自己百度一下,一个解放你f5的东西。


下面来介绍里面的每个task

copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*',
                        'bower_components/bootstrap/dist/fonts/*.*'
                    ]
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

copy task 可以看到,有两个key,dist和styles 在这声明一下,以下所有在key为dis下的task都是和build有关的,也就是只有执行build task是才会和用到这些task


files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*',
                        'bower_components/bootstrap/dist/fonts/*.*'
                    ]
                }]

file下一般配置的就是源文件和目标文件的转换了,具体参照http://gruntjs.com/configuring-tasks


styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }

就是一个task 名字叫做styles,目的是把styles下的css文件拷到tmp/styles下,怎么调用呢?copy:styles ,因为是自动生成的,所以感觉没啥用。


// By default, your `index.html`'s <!-- Usemin block --> will take care of
        // minification. These next options are pre-configured if you do not wish
        // to use the Usemin blocks.
        // cssmin: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

这段代码配置了3个task,但是为什么会被注释掉呢?


你不会看头两句话么? usemin block?


usemin block 是一种注释语言,写在你的html页面中,你可以打开index.html来查看,是不是有类似下面的




类似build:js这种,当配置过usemin之后,便可以使用他们,从而不用直接写在Gruntfile.js文件里,直接写在html页面里来执行task。。


// 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']
        },

具体自己看注释吧,写的的很清楚。。

rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

这个task就是为了在build时给每个引入的文件家一个时间戳来防止浏览器304用的。。  上面的英文注释,自己看吧。。大笑


autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

autoprefixed 顾名思义,就是给css里的属性加前缀的,例如 -webkit -mozila 就是这种前缀。

// Run some tasks in parallel to speed up build process
        concurrent: {
            server: [
                'copy:styles'
            ],
            test: [
                'copy:styles'
            ],
            dist: [
                'copy:styles',
                'imagemin',
                'svgmin'
            ]
        }

根据注释可以看出,这个task是为了让一些task并行执行,从而提高build的速度,一开始感觉没什么用,不过我吧这个去掉之后,build的时间还真的增加了。。


// Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

这个东西我从来没有成功过,看注释貌似是关于测试用的,可以我一直没有下载成功过这个插件,有兴趣的同学可以研究一下。。


其他的一些关于min的task都是压缩文件的,很容易理解,再次就不多说了。


如果你的项目需要编译coffee 和 less 等文件,你也可以配置一些task来让grunt编译,像是这样


coffee: {
            dist: {
                files: [{
                    // rather than compiling multiple files here you should
                    // require them into your main .coffee file
                    expand: true,
                    cwd: '<%= yeoman.app %>/scripts',
                    src: '{,*/}*.coffee',
                    dest: '.tmp/scripts',
                    ext: '.js'
                }]
            },
            test: {
                files: [{
                    expand: true,
                    cwd: 'test/spec',
                    src: '{,*/}*.coffee',
                    dest: '.tmp/spec',
                    ext: '.js'
                }]
            }
        },
		less: {
			  dist: {
				expand: true,
				cwd: "<%= yeoman.app %>/styles",
				src: "{,*/}*.less",
				dest: ".tmp/styles",
				ext: ".css"
			    
			  }
		},


然后在watch里配置一下


coffee: {
                files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
                tasks: ['coffee:dist']
            },
            
            less: {
            	files: ["<%= yeoman.app %>/styles/{,*/}*.less"],
            	tasks: ["less:dist"]
            },

最后说明一下关于Gruntfile.js文件中的.tmp路径,这个路径可以理解为一个文件中转站,你的js或者css或者html等文件在执行build命令或者编译是都需要先拷贝的这个路径下来,然后在拷到dist目录,而且如果livereload配置的也是这个,就可以在watch task里自动引入.tmp下的js和css了。


如果你的项目里引入了requirejs,那么请你先下载grunt-contrib-requirejs,然后给配置文件增加一个task,像是这样


requirejs: {
            dist: {
                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
                options: {
                    baseUrl: '.tmp/scripts',
                    optimize: 'none',
                    paths: {
                       // 'templates': '../../.tmp/scripts/templates',
                        'modernizr' : '../../app/bower_components/modernizr/modernizr',
                        'fastclick' : '../../app/bower_components/fastclick/lib/fastclick',
                        'jquery_cookie' : '../../app/bower_components/jquery.cookie/jquery.cookie',
                        'jquery_placeholder' : '../../app/bower_components/jquery-placeholder/jquery.placeholder',
                        'foundation' : '../../app/bower_components/foundation/js/foundation',
                        'jquery': '../../app/bower_components/jquery/dist/jquery.min',
                        'wow' : '../../app/bower_components/wow/wow',
                        'app': '../../.tmp/scripts/app'
                    },
                    // TODO: Figure out how to make sourcemaps work with grunt-usemin
                    // https://github.com/yeoman/grunt-usemin/issues/30
                    //generateSourceMaps: true,
                    // required to support SourceMaps
                    // http://requirejs.org/docs/errors.html#sourcemapcomments
                    preserveLicenseComments: false,
                    useStrict: true,
                    wrap: true
                    //uglify2: {} // https://github.com/mishoo/UglifyJS2
                }
            }
        },

这样在build的时候,requirejs会把你的相关的js管理起来,最终build一个mian文件。


下面说一下bower


bower可以搭配这grunt一块用,在回头看上面的Gruntfile.js文件

// Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                ignorePath: '<%= config.app %>/'
            }
        },

可以看到,如果你执行这个task ,bower会自动把bower_comments下的文件里的相关js或者css全部引入,引入位置是index,html里的<!-- bower:css --> 或者<!-- bower:js -->标签内,个人感觉如果和requirejs搭配起来不太好用,不过有另外一个grunt插件grunt-bower-requirejs可以解决这个问题,可是我至今没试成功。。可怜


最后上传一个我做的视觉滑动落差页面,有兴趣的朋友可以参考下


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值