• gulp初探


    gulp初探

    gulp是基于node.js的一个前端构建系统。它能通过自己主动运行常见任务,比方编译预处理CSS,压缩JavaScript和刷新浏览器。来改进站点的开发流程

    gulp安装
    1.假设没有安装node.js。请先去node管网安装最新版node.js;
    2.安装了node后,在全局安装gulp;
       npm install -g gulp
    3.然后。在项目里安装Gulp;
         npm install --save-dev gulp

    Gulp使用
    如今我们创建一个Gulp任务来压缩JavaScript文件。首先创建一个名为gulpfile.js的文件,这是定义Gulp任务的地方,它能够通过gulp命令来执行,接着把以下的代码放到gulpfile.js文件中面
    var gulp = require('gulp'),
       uglify 
    = require('gulp-uglify');

    gulp
    .task('minify', function () {
       gulp
    .src('js/app.js')
         
    .pipe(uglify())
         
    .pipe(gulp.dest('build'))});
    然后在npm里面执行npm install -–save-dev gulp-uglify来安装gulp-uglify,最后通过执行gulp minify来执行任务。

    如果js文件夹下有个app.js文件,那么一个新的app.js将被创建在编译文件夹下,它包括了js/app.js的压缩内容。想一想,究竟发生了什么?


    我们仅仅在gulpfile.js里做了一点事情。首先,我们载入gulp和gulp-uglify模块:
    var gulp = require('gulp'),
        uglify 
    = require('gulp-uglify');
    然后,我们定义了一个叫minify的任务,它运行时会调用函数,这个函数会作为第二个參数:
    gulp.task('minify', function () {

    });
    最后,也是难点所在,我们须要定义任务应该做什么:
    gulp.src('js/app.js')
       
    .pipe(uglify())
       
    .pipe(gulp.dest('build'))

    STREAMS
    数据流可以通过一系列的小函数来传递数据,这些函数会对数据进行改动,然后把改动后的数据传递给下一个函数。
    在上面的样例中,gulp.src()函数用字符串匹配一个文件或者文件的编号(被称为“glob”),然后创建一个对象流来代表这些文件,接着传递给uglify()函数。它接受文件对象之后返回有新压缩源文件的文件对象,最后那些输出的文件被输入gulp.dest()函数,并保存下来。

    整个数据流动步骤例如以下图所看到的
    当仅仅有一个任务的时候,函数并不会起太大的作用。

    然而。细致思考以下的代码:

    gulp.task('js', function () {
       
    return gulp.src('js/*.js')
         
    .pipe(jshint())
         
    .pipe(jshint.reporter('default'))
         
    .pipe(uglify())
         
    .pipe(concat('app.js'))
          .pipe(gulp.dest('build'));});
    在执行这段程序之前,你须要先安装gulp,gulp-jshint,gulp-uglify和gulp-concat。
    这个任务会让全部的文件匹配js/*.js(比方js文件夹下的全部JavaScript文件),而且运行JSHint,然后打印输出结果,取消文件缩进。最后把他们合并起来。保存为build/app.js,整个步骤例如以下图所看到的:
     

    假设你对Grunt 足够熟悉,就会注意到。Gulp和Grunt的工作方式非常不一样。Grunt不使用数据流,而是使用文件。对文件运行单个任务然后保存到新的文件里,每一个任务都会反复运行全部进程。文件系统频繁的处理任务会导致Grunt的运行速度比Gulp慢。

    假设想要获取更加全面的数据流知识,请查看“Stream Handbook”.

    GULP.SRC()

    ulp.src()方法输入一个glob(比方匹配一个或多个文件的字符串)或者glob数组,然后返回一个能够传递给插件的数据流。

    Gulp使用node-glob来从你指定的glob里面获取文件,这里列举以下的样例来阐述,方便大家理解:

    • js/app.js 精确匹配文件
    • js/*.js 仅匹配js文件夹下的全部后缀为.js的文件
    • js/*/.js 匹配js文件夹及其子文件夹下全部后缀为.js的文件
    • !js/app.js 从匹配结果中排除js/app.js,这样的方法在你想要匹配除了特殊文件之外的全部文件时很管用
    • *.+(js|css) 匹配根文件夹下全部后缀为.js或者.css的文件

    此外,Gulp也有非常多其它的特征,但并不经常使用。假设你想了解很多其它的特征,请查看Minimatch文档。

    js文件夹下包括了压缩和未压缩的JavaScript文件,如今我们想要创建一个任务来压缩还没有被压缩的文件,我们须要先匹配文件夹下全部的JavaScript文件,然后排除后缀为.min.js的文件:

    gulp.src(['js/**/*.js', '!js/**/*.min.js'])

    DEFINING TASKS

    gulp.task()函数一般会被用来定义任务。当你定义一个简单的任务时,须要传入任务名字和运行函数两个属性。

    gulp.task('greet', function () {
       console.log('Hello world!');});

    运行gulp greet的结果就是在控制台上打印出“Hello world”.

    一个任务有时也能够是一系列任务。

    如果要定义一个任务build来运行css、js、imgs这三个任务,我们能够通过指定一个任务数组而不是函数来完毕。

    gulp.task('build', ['css', 'js', 'imgs']);

    这些任务不是同一时候进行的,所以你不能觉得在js任务開始的时候css任务已经结束了。也可能还没有结束。为了确保一个任务在还有一个任务运行前已经结束,能够将函数和任务数组结合起来指定其依赖关系。

    比如。定义一个css任务。在运行前须要检查greet任务是否已经运行完成。这样做就是可行的:

    gulp.task('css', ['greet'], function () {
       // Deal with CSS here});

    如今,当运行css任务时,Gulp会先运行greet任务,然后在它结束后再调用你定义的函数。

    DEFAULT TASKS

    你能够定义一个在gulp開始执行时候默认执行的任务,并将这个任务命名为“default”:

    gulp.task('default', function () {
       // Your default task});

    PLUGINS

    Gulp上有超过600种插件供你选择,你能够在插件页面或者npm上搜索gulpplugin来浏览插件列表。有些拥有“gulpfriendly”标签的插件,他们不能算插件。可是能在Gulp上正常执行。

    须要注意的是,当直接在npm里搜索时,你无法知道某一插件是否在黑名单上(你须要滚动到插件页面底部才干看到)。

    大多数插件的使用都非常方便。它们都配有具体的文档,并且调用方法也同样(通过传递文件对象流给它),它们一般会对这些文件进行改动(可是有一些插件例外,比方validators),最后返回新的文件给下一个插件。

    让我们用前面的js任务来具体说明一下:

    var gulp = require('gulp'),
        jshint = require('gulp-jshint'),
        uglify = require('gulp-uglify'),
        concat = require('gulp-concat');
    
    gulp.task('js', function () {
       return gulp.src('js/*.js')
          .pipe(jshint())
          .pipe(jshint.reporter('default'))
          .pipe(uglify())
          .pipe(concat('app.js'))
          .pipe(gulp.dest('build'));});

    这里使用了三个插件,gulp-jshint,gulp-uglifygulp-concat

    开发人员能够參考插件的README文档,插件有非常多配置选项,并且给定的初始值通常能满足需求。细心的读者可能会发现,程序中JSHint插件运行了2次,这是由于第一次运行JSHint仅仅是给文件对象附加了jshint属性。并没有输出。你能够自己读取jshint的属性或者传递给默认的JSHint的接收函数或者其它的接收函数,比方jshint-stylish.

    其它两个插件的作用非常清楚:uglify()函数压缩代码,concat(‘app.js’)函数将全部文件合并到一个叫app.js的文件里。

    GULP-LOAD-PLUGINS

    我发现gulp-load-plugin模块十分实用,它可以自己主动地从package.json中载入随意Gulp插件然后把它们附加到一个对象上。

    它的基本使用方法例如以下所看到的:

    var gulpLoadPlugins = require('gulp-load-plugins'),
        plugins = gulpLoadPlugins();
    你能够把全部代码写到一行。可是我并不推荐这样做。
    在运行那些代码之后。插件对象就已经包括了插件,并使用“驼峰式”的方式进行命名(比如。gulp-ruby-sass将被载入成plugins.rubySass),这样就能够非常方便地使用了。

    比如,前面的js任务简化为例如以下:

    var gulp = require('gulp'),
        gulpLoadPlugins = require('gulp-load-plugins'),
        plugins = gulpLoadPlugins();
    
    gulp.task('js', function () {
       return gulp.src('js/*.js')
          .pipe(plugins.jshint())
          .pipe(plugins.jshint.reporter('default'))
          .pipe(plugins.uglify())
          .pipe(plugins.concat('app.js'))
          .pipe(gulp.dest('build'));});

    如果package.json文件如以下所看到的:

    {
       "devDependencies": {
          "gulp-concat": "~2.2.0",
          "gulp-uglify": "~0.2.1",
          "gulp-jshint": "~1.5.1",
          "gulp": "~3.5.6"
       }}

    这个样例尽管已经够短了。可是使用更长更复杂的Gulp文件会把它们简化成一两行代码。

    三月初公布的Gulp-load-plugins0.4.0版本号加入了延迟载入功能,提高了插件的性能。由于插件在使用的时候才会被载入进来,你不用操心package.json里未被使用的插件影响性能(可是你须要把他们清理掉)。换句话说。假设你在运行任务时仅仅须要两个插件。那么其它不相关的插件就不会被载入。

    WATCHING FILES

    Gulp能够监听文件的修修改态,然后在文件被修改的时候运行一个或多个任务。这个特性十分实用(对我来说,这可能是Gulp中最实用的一个功能)。你能够保存LESS文件。接着Gulp会自己主动把它转换为CSS文件并更新浏览器。

    使用gulp.watch()方法能够监听文件。它接受一个glob或者glob数组(和gulp.src()一样)以及一个任务数组来运行回调。

    让我们看看以下,build任务能够将模板转换成html格式,然后我们希望定义一个watch任务来监听模板文件的变化。并将这些模板转换成html格式。

    watch函数的用法例如以下所看到的:

    gulp.task('watch', function () {
       gulp.watch('templates/*.tmpl.html', ['build']);});

    如今,当改变一个模板文件时,build任务会被运行并生成HTML文件,也能够给watch函数一个回调函数,而不是一个任务数组。

    在这个演示样例中,回调函数有一个包括触发回调函数信息的event对象:

    gulp.watch('templates/*.tmpl.html', function (event) {
       console.log('Event type: ' + event.type); // added, changed, or deleted
       console.log('Event path: ' + event.path); // The path of the modified file});

    Gulp.watch()的还有一个很好的特性是返回我们熟知的watcher。利用watcher来监听额外的事件或者向watch中加入文件。

    比如,在运行一系列任务和调用一个函数时,你就能够在返回的watcher中加入监听change事件:

    var watcher = gulp.watch('templates/*.tmpl.html', ['build']);
    watcher.on('change', function (event) {
       console.log('Event type: ' + event.type); // added, changed, or deleted
       console.log('Event path: ' + event.path); // The path of the modified file});

    除了change事件。还能够监听非常多其它的事件:

    • end 在watcher结束时触发(这意味着。在文件改变的时候。任务或者回调不会运行)
    • error 在出现error时触发
    • ready 在文件被找到并正被监听时触发
    • nomatch 在glob没有匹配到不论什么文件时触发

    Watcher对象也包括了一些能够调用的方法:

    • watcher.end() 停止watcher(以便停止运行后面的任务或者回调函数)
    • watcher.files() 返回watcher监听的文件列表
    • watcher.add(glob) 将与指定glob相匹配的文件加入到watcher(也接受可选的回调当第二个參数)
    • watcher.remove(filepath) 从watcher中移除个别文件

    Reloading Changes In The Browser

    当一个文件被改动或者Gulp任务被运行时能够用Gulp来载入或者更新网页。

    LiveReload和BrowserSync插件就能够用来实如今游览器中载入更新的内容。

    LIVERELOAD

    LiveReload结合了浏览器扩展(包含Chrome extension),在发现文件被改动时会实时更新网页。

    它能够和gulp-watch插件或者前面描写叙述的gulp-watch()函数一起使用。以下有一个gulp-livereload仓库中的README文件提到的样例:

    var gulp = require('gulp'),
        less = require('gulp-less'),
        livereload = require('gulp-livereload'),
        watch = require('gulp-watch');
    
    gulp.task('less', function() {
       gulp.src('less/*.less')
          .pipe(watch())
          .pipe(less())
          .pipe(gulp.dest('css'))
          .pipe(livereload());});

    这会监听到全部与less/*.less相匹配的文件的变化。一旦监測到变化,就会生成css并保存,然后又一次载入网页.

    BROWSERSYNC

    BroserSync在浏览器中展示变化的功能与LiveReload很相似,可是它有很多其它的功能。

    当你改变代码的时候,BrowserSync会又一次载入页面,或者如果是css文件。会直接加入进css中,页面并不须要再次刷新。

    这项功能在站点是禁止刷新的时候是非常实用的。

    如果你正在开发单页应用的第4页。刷新页面就会导致你回到開始页。

    使用LiveReload的话,你就须要在每次改变代码之后还须要点击四次。而当你改动CSS时。插入一些变化时,BrowserSync会直接将须要改动的地方加入进CSS,就不用再点击回退。


    BrowserSync提供了一种在多个浏览器里測试网页的非常好方式(查看大图)

    BrowserSync也能够在不同浏览器之间同步点击翻页、表单操作、滚动位置。

    你能够在电脑和iPhone上打开不同的浏览器然后进行操作。

    全部设备上的链接将会随之变化,当你向下滚动页面时。全部设备上页面都会向下滚动(通常还非常流畅!

    )。当你在表单中输入文本时,每一个窗体都会有输入。当你不想要这样的行为时。也能够把这个功能关闭。


    BrowserSync不须要使用浏览器插件,由于它本身就能够给你提供文件。(查看大图)

    BrowserSync不须要使用浏览器插件,由于它本身就能够为你提供文件服务(假设文件是动态的。则为他们提供代理服务)和用来开启浏览器和server之间的socket的脚本服务。

    到眼下为止这个功能的使用都十分顺畅。

    实际上BrowserSync对于Gulp并不算一种插件,由于BrowserSync并不像一个插件一样操作文件。然而,npm上的BrowserSync模块能在Gulp上被直接调用。

    首先。须要通过npm安装一下:

    npm install --save-dev browser-sync

    然后gulpfile.js会启动BrowserSync并监听文件:

    var gulp = require('gulp'),
        browserSync = require('browser-sync');
    
    gulp.task('browser-sync', function () {
       var files = [
          'app/**/*.html',
          'app/assets/css/**/*.css',
          'app/assets/imgs/**/*.png',
          'app/assets/js/**/*.js'
       ];
    
       browserSync.init(files, {
          server: {
             baseDir: './app'
          }
       });});

    运行gulp browser-sync后会监听匹配文件的变化,同一时候为app文件夹提供文件服务。

    此外BrowserSync的开发人员还写了非常多关于BrowserSync+Gulp仓库的其它用途。

    Why Gulp?

    前面提到过。Gulp是为数不多的使用JavaScript开发的构建工具之中的一个。也有其它不是用JavaScript开发的构建工具,比方Rake,那么我们为什么要选择Gulp呢?

    眼下最流行的两种使用JavaScript开发的构建工具是Grunt和Gulp。Grunt在2013年非常流行,由于它彻底改变了很多人开发站点的方式。它有上千种插件可供用户使用,从linting、压缩、合并代码到使用Bower安装程序包,启动Express服务都能办到。这些和Gulp的非常不一样,Gulp仅仅有运行单个小任务来处理文件的插件,由于任务都是JavaScript(和Grunt使用的大型对象不同)。根本不须要插件,你仅仅需用传统方法启动一个Express服务就能够了。

    Grunt任务拥有大量的配置。会引用大量你实际上并不须要的对象属性,可是Gulp里相同的任务或许仅仅有几行。让我们看个简单的Gruntfile.js。它规定一个将LESS转换为CSS的任务,然后运行Autoprefixer:

    grunt.initConfig({
       less: {
          development: {
             files: {
                "build/tmp/app.css": "assets/app.less"
             }
          }
       },
    
       autoprefixer: {
          options: {
             browsers: ['last 2 version', 'ie 8', 'ie 9']
          },
          multiple_files: {
             expand: true,
             flatten: true,
             src: 'build/tmp/app.css',
             dest: 'build/'
          }
       }});
    
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-autoprefixer');
    
    grunt.registerTask('css', ['less', 'autoprefixer']);

    与Gulpfile.js文件进行对照,它们运行的任务同样:

    var gulp = require('gulp'),
       less = require('gulp-less'),
       autoprefix = require('gulp-autoprefixer');
    
    gulp.task('css', function () {
       gulp.src('assets/app.less')
          .pipe(less())
          .pipe(autoprefix('last 2 version', 'ie 8', 'ie 9'))
          .pipe(gulp.dest('build'));});

    由于Grunt比Gulp更加频繁地操作文件系统。所以使用数据流的Gulp总是比Grunt快。

    对于一个小的LESS文件,gulpfile.js通常须要6ms,而gruntfile.js则须要大概50ms——慢8倍多。这仅仅是个简单的样例,对于长的文件。这个数字会添加得更显著。

  • 相关阅读:
    hdu4291 A Short problem
    UVA
    HDU
    Be Geeks!
    HDU
    hdu6559 The Tower
    胜利大逃亡(续) + Maze
    Stealing Harry Potter's Precious
    hdu5172 GTY's gay friends
    Log Concave Sequences Gym
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7256987.html
Copyright © 2020-2023  润新知