前端自動化gulp趕上es6從 無知到深愛

Gulp是什麼?

Gulp是前端自動化的工具,但Gulp能用來作什麼javascript

1.搭建web服務器css

2.使用預處理器Sass,Lesshtml

3.壓縮優化,能夠壓縮JS CSS Html 圖片前端

4.自動將更新變化的代碼實時顯示在瀏覽器java

5.前端測試node

......jquery

這些都不是他的所有功能,社區豐富的插件,爲他提供了強大的後盾。git

首先下載gulp(前提默認你安裝好了node,先 npm install,建立一個package.json)es6

npm install gulp -g //全局安裝
npm install gulp --save-dev //本地安裝並加入package.json

 1、安裝各類神奇的插件

接下來安裝各類須要的插件:github

npm install babel-core babel-preset-es2015 browser-sync gulp gulp-autoprefixer gulp-babel gulp-cache gulp-clean gulp-cssnano gulp-htmlmin gulp-if gulp-imagemin gulp-load-plugins gulp-plumber gulp-sass gulp-size gulp-sourcemaps gulp-uglify gulp-useref gulp-rev-append main-bower-files wiredep --save-dev

各類插件按需求本身選擇,各自功能以下:

1.babel-core babel-preset-es2015 gulp-babel   用於解析es6轉換爲es5

2.browser-sync  服務器同步瀏覽

3.gulp-autoprefixer  根據設置瀏覽器版本自動處理瀏覽器前綴

4.gulp-cache  圖片快取,只有更改過得圖片會進行壓縮

5.gulp-clean 清空文件夾

6.gulp-cssnano 壓縮CSS代碼

7.gulp-htmlmin 壓縮html

8.gulp-if 用於判斷

8.gulp-imagemin 圖片壓縮

9.gulp-load-plugins 自動加載(超級有用 省去一大堆代碼)

10.gulp-plumber 管道工 不會讓錯誤爆出來 繼續執行

11.gulp-sass 預編譯Sass

12.gulp-size 統計管道里面內容的大小的,上面是用它來顯示出壓縮先後的大小用來對比用

13.gulp-sourcemaps 當壓縮的JS出錯,能根據這個找到未壓縮代碼的位置 不會一片混亂代碼

14.gulp-uglify JS壓縮

15.gulp-useref 將html引用順序的CSS JS 變成一個文件  

例如:<!-- build:js scripts/main.js --> <script src="1.js"></script><script src="2.js"></script><!--endbuild--> 最後變成<script src="main.js"></script>

16.gulp-rev-append html引用添加版本號

17.main-bower-files 找到bower.json裏配置的 overrides 下配置的main下的路徑

18.wiredep 在.html文件會把默認bower.json的配置自動注入到下面標籤中去 <!-- bower:js --> <!-- endbower --> <!-- bower:css--> <!-- endbower -->

 

接下來是用 bower安裝 Jquery bootstrap-sass

bower init //新建bower.json
bower install jquery bootstrap-sass --save-dev //安裝jquery bootstrap

 2、get Gulp的簡單語法

1.gulp.task(name[,deps],fn)

說明:定義一個gulp任務

name: 類型(必填):String 指定任務的名稱(不該該有空格)

deps:類型(可選):StringArray,該任務依賴的任務(執行name任務要先去執行的任務)

gulp.task('A' , function(){
   console.log('A') 
});
gulp.task('B' , ['A'] , function(){ //運行B以前先去運行A
   console.log('B')
});

fn:類型(必填):Function 該任務調用的插件操做

 

2.gulp.src(globs[, options])

說明:src方法指定須要處理的源文件路徑,返回當前文件流至可用插件

globs: 類型(必填):String/StringArray  須要處理的源文件匹配符路徑

通配符路徑匹配示例:

  「src/a.js」:指定具體文件;

  「*」:匹配全部文件    例:src/*.js(包含src下的全部js文件);

  「**」:匹配0個或多個子文件夾    例:src/**/*.js(包含src的0個或多個子文件夾下的js文件);

  「{}」:匹配多個屬性    例:src/{a,b}.js(包含a.js和b.js文件)  src/*.{jpg,png,gif}(src下的全部jpg/png/gif文件);

  「!」:排除文件    例:!src/a.js(不包含src下的a.js文件);

options:類型(可選):Object 三個屬性 buffer read base

  options.buffer:類型:Boolean  默認:true 設置爲false,將返回file.content的流而且不緩衝文件,處理大文件時很是有用;

  options.read:  類型:Boolean  默認:true 設置false,將不執行讀取文件操做,返回null;

  options.base:  類型:String  設置輸出路徑以某個路徑的某個組成部分爲基礎向後拼接

gulp.src('client/js/**/*.js') 
  .pipe(minify())
  .pipe(gulp.dest('build'));  // Writes 'build/somedir/somefile.js'
 
gulp.src('client/js/**/*.js', { base: 'client' })
  .pipe(minify())
  .pipe(gulp.dest('build'));  // Writes 'build/js/somedir/somefile.js'

 

3.gulp.dest(path[,options])

說明:處理完後文件輸出的路徑

path:類型(必填):String or Function 指定文件輸出路徑,或者定義函數返回文件輸出路徑亦可

options:  類型(可選):Object,有2個屬性cwd、mode;

  options.cwd:  類型:String  默認:process.cwd():前腳本的工做目錄的路徑 當文件輸出路徑爲相對路徑將會用到;

  options.mode:  類型:String  默認:0777 指定被建立文件夾的權限;

 

4.gulp.watch(glob[,opts],tasks) or gulp.task(glob [,opts ,cd])

說明:watch方法用於監聽文件變化,一被變化就執行指定任務

glob:  須要處理的源文件匹配符路徑。類型(必填):String or StringArray;

opts:  類型(可選):Object 具體參看https://github.com/shama/gaze

tasks:  類型(必填):StringArray 須要執行的任務的名稱數組;

cb(event):  類型(可選):Function 每一個文件變化執行的回調函數;

3、目錄

|--gulp_test
    |--app             //生產文件路徑
        |--fonts
        |--images
|--1.png
|--scripts
|--main.js
|--index.js
|--styles
|--main.scss
|--index.css
|--index.html |--dist //發佈文件路徑 |--fonts |--images |--scripts |--styles |--index.html |--bower_components |--bootstrap-sass |--jquery |--node_modules |--各類插件 |--package.json |--bower.json

 

app是咱們新建的目錄和文件夾,其他是按照上面操做自動生成的。

首先在gulp_test下新建.babelrc (用於配置es6 語法) .bowerrc (用於定義bower的路徑)兩個文件

.babelrc

{
  "presets": [
    "es2015"
  ]
}

.bowerrc

{
  "directory": "bower_components"
}

設置一下bower.json

{
  "name": "gulp_test",
  "authors": [
    "QRL"
  ],
  "keywords": [
    "bower_components"
  ],
  "private": true,
  "devDependencies": {
    "jquery": "^3.0.0"
  },
  "overrides": {
    "bootstrap-sass": {
      "main": [
        "assets/stylesheets/_bootstrap.scss",
        "assets/fonts/bootstrap/*",
        "assets/javascripts/bootstrap.js"
      ]
    }
  },
  "dependencies": {"bootstrap-sass": "^3.3.6"}
}

app下的index.html內容

<!doctype html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test gulp webapp</title>

    <link rel="apple-touch-icon" href="apple-touch-icon.png">
    <!-- Place favicon.ico in the root directory -->

    <!-- build:css styles/index_main.css -->   //這個註釋的意思是 將兩個css合併成一個index_main.css 注意順序
    <link rel="stylesheet" href="styles/index.css">
    <link rel="stylesheet" href="styles/main.css">
    <!-- endbuild -->
  </head>
  <body>
  
    <div class="container">
      <div class="header">
        <ul class="nav nav-pills pull-right">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">About</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
        <h3 class="text-muted">Hello</h3>
      </div>

      <div class="jumbotron">
        <h1>Hello Gulp!</h1>
        <p class="lead">Always a pleasure scaffolding your apps.</p>
        <p><a class="btn btn-lg btn-success" href="#">Splendid!</a></p>
      </div>

      <div class="row marketing">
        <div class="col-lg-6">
          <h4>HTML5 Boilerplate</h4>
          <p>HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.</p>
          
          <h4>Sass</h4>
          <p>Sass is the most mature, stable, and powerful professional grade CSS extension language in the world.</p>
          
          <h4>Bootstrap</h4>
          <p>Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.</p>
          <h4>Modernizr</h4>
          <p>Modernizr is an open-source JavaScript library that helps you build the next generation of HTML5 and CSS3-powered websites.</p>
          
        </div>
      </div>

      <div class="footer">
        <p>♥ from the Yeoman team</p>
      </div>
    </div>
    
    <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
    <script>
      (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
      function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
      e=o.createElement(i);r=o.getElementsByTagName(i)[0];
      e.src='https://www.google-analytics.com/analytics.js';
      r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
      ga('create','UA-XXXXX-X');ga('send','pageview');
    </script>

    <!-- build:js scripts/vendor.js --> //將如下js合併成一個,並改名爲vendor.js
    <script src="/bower_components/jquery/dist/jquery.js"></script>
    <!-- endbuild -->
    
    <!-- build:js scripts/plugins.js --> //注意一下這裏 待會會按照順序變成一個plugins.js文件
     //是否遇到過這麼多的插件引用,Ctrl+c Ctrl+v 還要細緻的修改 請留意 wiredep 任務 留意下面的<!-- bower:js --><!-- endbower -->註釋,這可不是隨隨便便的註釋
    <!-- bower:js -->
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/affix.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/alert.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/modal.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/transition.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/button.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/popover.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/carousel.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/scrollspy.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/collapse.js"></script>
    <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/tab.js"></script>
    <!-- endbower -->
    <!-- endbuild -->
    
    <!-- build:js scripts/index_main.js -->   
    <script src="scripts/index.js"></script>
    <script src="scripts/main.js"></script>
    <!-- endbuild -->
  </body>
</html>

接下來最重要了,一樣在gulp_test下新建gulpfile.babel.js(由於這裏使用es6,因此須要將本來的gulpfile.js 改名爲 gulpfile.babel.js )

4、開始gulp之旅

打開gulpfile.babel.js,開始操做

首先寫進如下代碼:

import gulp from 'gulp'; //引入gulp
import gulpLoadPlugins from 'gulp-load-plugins'; //自動加載插件 省去一個一個require進來
import browserSync from 'browser-sync'; //瀏覽器同步
import {stream as wiredep} from 'wiredep'; //把bower 下載的文件引入到html文件中
const $ = gulpLoadPlugins();
const reload = browserSync.reload;

接下來

 先嚐試刪除dist文件夾  終端運行 "gulp clean"

gulp.task('clean' , function(){
   return gulp.src([
      'dist', //刪除dist整個文件夾
      'dist/test/**/*', //刪除dist下的test寫任意子文件夾裏的文件
      '!package.json'  //不刪除package.json文件
     ] ).pipe($.clean());
});

預編譯Sass

gulp.task('styles' , ()=>{
   return gulp.src('app/styles/*.scss') //指明源文件路徑 讀取其數據流
        .pipe($.plumber()) //替換錯誤的pipe方法  使數據流正常運行
        .pipe($.sourcemaps.init()) //壓縮環境出現錯誤能找到未壓縮的錯誤來源
        .pipe($.sass.sync({        //預編譯sass
            outputStyle: 'expanded', //CSS編譯後的方式
            precision: 10,//保留小數點後幾位
            includePaths: ['.']
        }).on('error', $.sass.logError))
        .pipe($.autoprefixer({browsers:['> 1%', 'last 2 versions', 'Firefox ESR']}))     //自動匹配瀏覽器支持的後綴
        .pipe($.sourcemaps.write('.'))  //map文件命名
        .pipe(gulp.dest('dist/styles'))  //指定輸出路徑
});
../dist/styles目錄下會生成 對應的 *.css 和 *.css.map

轉化es6的JS

gulp.task('scripts' , ()=>{
    return gulp.src('app/scripts/**/*.js')
        .pipe($.plumber())
        .pipe($.sourcemaps.init())
        .pipe($.babel())    //靠這個插件編譯
        .pipe($.sourcemaps.write('.'))
        .pipe(gulp.dest('dist/scripts'));     
});
../dist/scripts目錄下會生成 對應的 *.js 和 *.js.map

壓縮圖片

gulp.task('images',()=>{
    return gulp.src('app/images/**/*')
         .pipe ($.cache ($.imagemin ({ //使用cache只壓縮改變的圖片
              optimizationLevel: 3,         //壓縮級別
              progressive: true, 
              interlaced: true})
         )).pipe (gulp.dest ('dist/images'));
});
經過對比圖片大小,能夠看出壓縮了多少

引用字體文件

gulp.task('fonts', () => {
    return gulp.src(require('main-bower-files')('**/*.   {eot,svg,ttf,woff,woff2}', function (err) {})  //main-bower-files會從bower.json文件裏尋找定義好的主要文件路徑
        .concat('app/fonts/**/*'))  //將bootstrap-sass的fonts和app下咱們本身選用的fonts合併起來
.pipe(gulp.dest('dist/fonts')); });
../dist/fonts目錄下會生成 對應的文件

接下來是最最有用的操做,將CSS合併壓縮,JS合併壓縮,html壓縮,加上時間戳避免緩存

gulp.task('html', ['styles' , 'scripts'], ()=>{   //先執行styles scripts任務
    var version = (new Date).valueOf() + '';
    var options = {
        removeComments: false,//清除HTML註釋
        collapseWhitespace: true,//壓縮HTML
        collapseBooleanAttributes: false,//省略布爾屬性的值 <input checked="true"/> ==> <input />
        removeEmptyAttributes: false,//刪除全部空格做屬性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: false,//刪除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: false,//刪除<style>和<link>的type="text/css"
        minifyJS: false,//壓縮頁面裏的JS
        minifyCSS: false//壓縮頁面裏的CSS
    };
    return gulp.src('app/*.html')
        .pipe($.plumber())
        .pipe($.useref({searchPath: ['app', '.']}))  //將頁面上 <!--endbuild--> 根據上下順序合併
        .pipe($.if('*.js', $.uglify()))
        .pipe($.if('*.css', $.cssnano()))
        .pipe($.if('*.html', $.htmlmin(options)))
        .pipe($.replace('.js"></script>' , '.js?v=' + version + '"></script>'))   //這種方法比較不成熟 每一次的任務都會改變,無論文件是否被修改 
        .pipe($.replace('.css">' , '.css?v=' + version + '">'))
        .pipe(gulp.dest('dist'));
});

 查看dist/index.html , 是否還記得

是否是瞬間被嚇到了,不再用一個個壓縮JS文件,不再要擔憂緩存這種問題,不再用由於頁面的臃腫而煩惱,幾行配置,一鍵搞定。

優化上面的引用加版本號: 使用插件 gulp-rev-append

import rev from 'gulp-rev-append'

gulp.task('html', ['styles' , 'scripts'], ()=>{   //先執行styles scripts任務
   
    return gulp.src('app/*.html')
        .pipe($.plumber())
        .pipe($.useref({searchPath: ['app', '.']}))  //將頁面上 <!--endbuild--> 根據上下順序合併
        .pipe($.if('*.js', $.uglify()))
        .pipe($.if('*.css', $.cssnano()))
        .pipe(rev())       //爲引用添加版本號
        .pipe($.if('*.html', $.htmlmin(options)))      
        .pipe(gulp.dest('dist'));
});

 

同時須要在index.html的引用後面加上 ?rev=@@hash

<script src="scripts/index.js?rev=@@hash"></script>

 

添加後的效果

<script src="scripts/index.js?rev=200c90563a2be0adfd8c03f8e4162df7"></script>

 

最重要是隻要app/index.js裏不發生改變,這個版本號就不會變化。

 

 

 

接下來再學一個黑魔法——本地建站和自動刷新

gulp.task('serve', ['styles','scripts','fonts'] , ()=>{
    browserSync({
        notify : false,
        port:9000,  //端口號
        server:{
            baseDir:['dist'], //肯定根目錄
            routes:{
                '/bower_components': 'bower_components'
            }
        }
    });

    gulp.watch([      //監測文件變化 實行從新加載
        'app/*.html', 
        'app/images/**/*' 
    ]).on('change',reload);

    gulp.watch('app/styles/**/*.scss' , ['styles']); //監測變化 執行styles任務
    gulp.watch('app/scripts/**/*.js' , ['scripts']);
    gulp.watch('app/fonts/**/*' , ['fonts']);
    gulp.watch('bower.json' , ['wiredep','fonts']);
});

終端一運行gulp serve 瀏覽器直接打開dist下的index.html,只要一修改監測的文件,瀏覽器當即刷新。

小插曲:接下來解決 wiredep 任務,這個插件主要是用在bower下載文件,方便頁面引用文件

首先在app下新建一個 index_test.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>

    <!--bower:css-->
    <!--endbower-->
</head>
<body>
    <p>Hellp wirdep</p>
    <a href="index.html">dianwo</a>
    <!-- bower:js -->
    <!-- endbower -->
</body>
</html>

而後在gulpfile.babel.js中寫上任務

gulp.task('wiredep_test' , function(){
    gulp.src('./app/index_test.html')
    .pipe(wiredep({
            optional:'configuration',
            goes : 'here',
            ignorePath:/^(\.\.\/)+/      //生成的路徑忽略../   
        }))
    .pipe(gulp.dest('./app'))    //輸出到原路徑
});

而後運行一下,index_test.html 本來的<!-- bower:js --> <!-- endbower --> 變成

 

 <!-- bower:js -->
    <script src="bower_components/jquery/dist/jquery.js"></script>
    <script src="bower_components/bootstrap-sass/assets/javascripts/bootstrap.js"></script>
 <!-- endbower -->

 

你或許很疑惑這是根據什麼自動查找生成的啊?由於沒有中文文檔,本身摸索後是在bower.json裏面配置的,review一下剛纔的bower.json

  "devDependencies": {
    "jquery": "^3.0.0"
  },
  "overrides": {
    "bootstrap-sass": {
      "main": [
        "assets/stylesheets/_bootstrap.scss",
        "assets/fonts/bootstrap/*",
        "assets/javascripts/bootstrap.js"
      ]
    }
  },
  "dependencies": {"bootstrap-sass": "^3.3.6"}

根據以上三個根據,起最大做用的是overrides,最終會根據這些進行生成。

能夠稍微測試一下,將bower.json作點小修改 ,增長jquery的選擇

"overrides": {
    "bootstrap-sass": {
      "main": [
        "assets/stylesheets/_bootstrap.scss",
        "assets/fonts/bootstrap/*",
        "assets/javascripts/bootstrap.js"
      ]
    }, "jquery" :{
      "main":[
        "src/*.js" ] }
  }

回頭看看index_test.html  剛纔的jquery.js 被src下的js代替

<!-- bower:js -->
    <script src="bower_components/modernizr/modernizr.js"></script>
    <script src="bower_components/jquery/src/ajax.js"></script>
    <script src="bower_components/jquery/src/attributes.js"></script>
    <script src="bower_components/jquery/src/callbacks.js"></script>
    <script src="bower_components/jquery/src/core.js"></script>
    <script src="bower_components/jquery/src/css.js"></script>
    <script src="bower_components/jquery/src/data.js"></script>
    <script src="bower_components/jquery/src/deferred.js"></script>
    <script src="bower_components/jquery/src/deprecated.js"></script>
    <script src="bower_components/jquery/src/dimensions.js"></script>
    <script src="bower_components/jquery/src/effects.js"></script>
    <script src="bower_components/jquery/src/event.js"></script>
    <script src="bower_components/jquery/src/jquery.js"></script>
    <script src="bower_components/jquery/src/manipulation.js"></script>
    <script src="bower_components/jquery/src/offset.js"></script>
    <script src="bower_components/jquery/src/queue.js"></script>
    <script src="bower_components/jquery/src/selector-native.js"></script>
    <script src="bower_components/jquery/src/selector-sizzle.js"></script>
    <script src="bower_components/jquery/src/selector.js"></script>
    <script src="bower_components/jquery/src/serialize.js"></script>
    <script src="bower_components/jquery/src/traversing.js"></script>
    <script src="bower_components/jquery/src/wrap.js"></script>
    <script src="bower_components/bootstrap-sass/assets/javascripts/bootstrap.js"></script>
    <!-- endbower -->

最後一步,就結束了

gulp.task('build' , ['html' , 'images' , 'fonts'],()=>{
    return gulp.src('dist/**/*')
    .pipe($.size({title:'build' , gzip:true}));
});

gulp.task('default' ,['clean'],()=>{
    gulp.start('build');
});

這就是單獨運行 gulp 就會執行default 而後執行咱們想要的操做,同時能夠根據size看到壓縮後節省的空間。

感謝您堅持看完,一步步跟着作,你會發現gulp原來辣麼容易,前端自動化工具辣麼方便。

對於老項目也能夠這樣一步一步改造哦!

 

 聲明:上述的 2、get Gulp的簡單語法 摘抄於 Gulp中文網的API文檔 。其他內容均屬樓主一點一滴碼出來的。

相關文章
相關標籤/搜索