Yeoman+Bower+gulp web前端自動化工做流程(初級教程)

Yeoman包括了三個部分yo(腳手架工具)、grunt/gulp(構建工具)、bower(包管理器).據說gulp更容易上手,因此我就沒用grunt而選的gulp

 什麼是開發流程?

  在我看來一個完整的開發流程應該包括:javascript

  • 本地開發環境的初始化
  • 第三方依賴的管理
  • 源文件編譯
  • 自動化測試
  • 發佈到pipeline和各個環境

  而現代的開發流程,就是要使上面的各個部分均可以自動化,一個命令就可使這些流程都自動走完,而且快速的獲得錯誤或經過的反饋,讓咱們能夠方便快速的修復錯誤和release。css

 工具簡單介紹

 腳手架工具(Yeoman官網http://yeoman.io/)

  腳手架是幫你減小「爲減小重複性工做而作的重複性工做」的工具,這就像假如你要開始一個新的小項目,原來你可能至少須要手動建立個js、css、images三個文件夾吧?而腳手架工具就是幫你每次新建項目時候執行這個動做流程部分的工具,也就是說之後就須要一行命令而已,不用本身再去手動建立文件夾及結構了。html

  但是呢,你有可能又要想了,那我每一個項目的目錄結構不可能都要一吧,那應該怎麼辦呢?那就須要根據不一樣的項目安裝不一樣的 generator了(http://yeoman.io/generators/),固然你也能夠自定義個generator,而後公開給別人使用,如今咱們只是學怎麼使用別人的generator,我也不會自定義呢,這個自定義的問題請你們自行百度教程吧!哈哈前端

 構建工具(gulp中文網地址http://www.gulpjs.com.cn/)

  gulp是前端開發過程當中對代碼進行構建的工具,是自動化項目的構建利器,簡單的說就是你把一套什麼壓縮,合併這些規則提早寫好,等你寫完代碼,只需一行命令就能夠生成上線的代碼,而後直接上傳到服務器就行了,固然你也能夠有更高級的使用,後續自行研究。java

 包管理工具(bower官網地址https://bower.io/)

  Bower是一個客戶端技術的軟件包管理器,它可用於搜索、安裝和卸載如JavaScript、HTML、CSS之類的網絡資源。好比:jQuery、Bootstrap node

 具體安裝流程

  準備工做你全局應該已經安裝nodejs、npm了吧?沒安裝的請自行百度安裝,下載安裝包->雙擊->一路next->安裝完畢web

  全局安裝Yeoman、gulp、bowernpm

npm install yo gulp-cli bower -g

  若是執行完這個命令尚未報錯,那麼恭喜你,基本環境就已經搭建完畢了,剩下就是須要根據你的項目,而後按照generator了,暫時先建立個webapp項目爲例,因此咱們先安裝個generator-webappjson

npm install -g generator-webapp

  安裝完generator-webapp後,在項目目錄下直接gulp

yo webapp 

  便可建立一個webapp項目。至此就搭建好了,而後就能夠安靜的寫代碼的。

附:(gulpfile.js配置文件及index.html我的理解)

  index.html

<!-- build:css styles/main.css -->
    <link rel="stylesheet" href="styles/main.css">
    <!-- 這個link是你開發時候頁面引用的css路徑,上面的build:css 是build時候存放的路徑和名字,路徑和名字均可以自定義,下面的js原理同樣 -->
    <!-- endbuild -->

  gulpfile.js

/*
//導入工具包 require('node_modules裏對應模塊')
var gulp = require('gulp'), //本地安裝gulp所用到的地方
    less = require('gulp-less');
 
//定義一個testLess任務(自定義任務名稱)
gulp.task('testLess', function () {
    gulp.src('src/less/index.less') //該任務針對的文件
        .pipe(less()) //該任務調用的模塊
        .pipe(gulp.dest('src/css')); //將會在src/css下生成index.css
});
 
gulp.task('default',['testLess', 'elseTask']); //定義默認任務 elseTask爲其餘任務,該示例沒有定義elseTask任務
 
//gulp.task(name[, deps], fn) 定義任務  name:任務名稱 deps:依賴任務名稱 fn:回調函數
//gulp.src(globs[, options]) 執行任務處理的文件  globs:處理的文件路徑(字符串或者字符串數組) 
//gulp.dest(path[, options]) 處理完後文件生成路徑


 */
// generated on 2016-08-26 using generator-webapp 2.1.0
const gulp = require('gulp');
//能夠批量require package.json中的devDependencies插件,沒必要一個一個導入了
const gulpLoadPlugins = require('gulp-load-plugins');
// 瀏覽器自動刷新插件
const browserSync = require('browser-sync');
//刪除文件和文件夾
const del = require('del');
//wiredep解決了bower前端庫引入進html的問題
const wiredep = require('wiredep').stream;
// 本地開發代理跨域請求用的插件
const proxyMiddleware = require('http-proxy-middleware');

const $ = gulpLoadPlugins();
const reload = browserSync.reload;
// 定義proxy規則,供下面建立服務使用,以/service/開頭的代理到target域名下
const proxy= proxyMiddleware(['/service/'],{target:'http://xxx.xxxx.com',changeOrigin: true});
// 編譯sass
gulp.task('styles', () => {
  return gulp.src('app/styles/*.scss')
    //plumber 是一個錯誤處理插件,當出現錯誤時,不會當即卡主,而是進入 plumber,防止程序運行終止。plumber能夠阻止 gulp 插件發生錯誤致使進程退出並輸出錯誤日誌。
    .pipe($.plumber())
    //sourcemaps 是用來生成映射文件的一個插件,map 文件記錄了從 Sass 編譯成 CSS 的過程當中,每一行的 Sass 代碼對應哪一行的 CSS 代碼。在scss編譯過程當中,添加映射關係,能夠方便調試;
    //在文件流中須要兩條語句:
    //***plugins.sourcemaps.init()
    //若是要輸出sourcemaps文件的話,能夠在write(path)添加路徑;
    //***plugins.sourcemaps.write()
    .pipe($.sourcemaps.init())
    //sass 是核心的編譯 Sass 的插件,指定了輸出格式 expanded,precision 指定了當輸出十進制數字時,使用多少位的精度,而後指定了路徑和錯誤日誌。
    //嵌套輸出方式 nested
    // 展開輸出方式 expanded 
    // 緊湊輸出方式 compact 
    // 壓縮輸出方式 compressed
    .pipe($.sass.sync({
      outputStyle: 'expanded',
      precision: 10,
      includePaths: ['.']
    }).on('error', $.sass.logError))
    //添加瀏覽器前綴
    .pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
    .pipe($.sourcemaps.write())
    // .tmp 臨時目錄,後面還會有一個目錄是 dist 目錄,試想一下,若是咱們編譯了 BootStrap 而在 HTML 中沒有引用,那編譯來還有必要嗎?因此說,.tmp 做爲臨時目錄,它能夠存放被編譯後的文件,可是不必定會被引用。被真正引用的文件纔是真正有用的文件,咱們將它放到 dist 目錄。因此接下來的 HTML 處理就是檢查一下有哪些 CSS 和 JS 被引用了,能夠將它們合併,而後將新的文件放到 dist 並更新它的引用路徑。
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({stream: true}));
});

// 編譯js
gulp.task('scripts', () => {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.plumber())
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.sourcemaps.write('.'))
    .pipe(gulp.dest('.tmp/scripts'))
    .pipe(reload({stream: true}));
});

function lint(files, options) {
  return gulp.src(files)
    .pipe(reload({stream: true, once: true}))
    .pipe($.eslint(options))
    .pipe($.eslint.format())
    .pipe($.if(!browserSync.active, $.eslint.failAfterError()));
}

gulp.task('lint', () => {
  return lint('app/scripts/**/*.js', {
    fix: true
  })
    .pipe(gulp.dest('app/scripts'));
});
gulp.task('lint:test', () => {
  return lint('test/spec/**/*.js', {
    fix: true,
    env: {
      mocha: true
    }
  })
    .pipe(gulp.dest('test/spec/**/*.js'));
});

// 編譯html
gulp.task('html', ['styles', 'scripts'], () => {
  return gulp.src('app/*.html')
    //useref 這個插件,它能夠檢測 HTML 中引用的 CSS 和 JS,能夠執行合併和壓縮,而後更新新的路徑。
    .pipe($.useref({searchPath: ['.tmp', 'app', '.']}))
    .pipe($.if('*.js', $.uglify()))
    .pipe($.if('*.css', $.cssnano({safe: true, autoprefixer: false})))
    // options = {
    // removeComments: true,  //清除HTML註釋
    // collapseWhitespace: true,  //壓縮HTML
    // collapseBooleanAttributes: true,  //省略布爾屬性的值 <input checked="true"/> ==> <input checked />
    // removeEmptyAttributes: true,  //刪除全部空格做屬性值 <input id="" /> ==> <input />
    // removeScriptTypeAttributes: true,  //刪除<script>的type="text/javascript"
    // removeStyleLinkTypeAttributes: true,  //刪除<style>和<link>的type="text/css"
    // minifyJS: true,  //壓縮頁面JS
    // minifyCSS: true  //壓縮頁面CSS
    // };
    .pipe($.if('*.html', $.htmlmin({collapseWhitespace: true})))
    //替換成線上路徑
    .pipe($.replace(/\"images\//g, '"statics/images/'))
    .pipe(gulp.dest('dist'));
});

gulp.task('images', () => {
  return gulp.src('app/images/**/*')
    //只壓縮修改的圖片,沒壓縮的從緩存文件讀取
    //optimizationLevel: 5, //類型:Number  默認:3  取值範圍:0-7(優化等級)
    // progressive: true, //類型:Boolean 默認:false 無損壓縮jpg圖片
    // interlaced: true, //類型:Boolean 默認:false 隔行掃描gif進行渲染
    // multipass: true //類型:Boolean 默認:false 屢次優化svg直到徹底優化
    // svgoPlugins: [{removeViewBox: false}],//不要移除svg的viewbox屬性
    // use: [pngquant()] //使用pngquant深度壓縮png圖片的imagemin插件 
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true,
      // don't remove IDs from SVGs, they are often used
      // as hooks for embedding and styling
      svgoPlugins: [{cleanupIDs: false}]
    })))
    .pipe(gulp.dest('dist/images'));
});

gulp.task('fonts', () => {
  return gulp.src(require('main-bower-files')('**/*.{eot,svg,ttf,woff,woff2}', function (err) {})
    .concat('app/fonts/**/*'))
    .pipe(gulp.dest('.tmp/fonts'))
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('extras', () => {
  return gulp.src([
    'app/*.*',
    '!app/*.html'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

gulp.task('serve', ['styles', 'scripts', 'fonts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['.tmp', 'app'],
      routes: {
        '/bower_components': 'bower_components'
      },
      //這是代理跨域,規則上面已經定義了
      middleware: [proxy]
    }
  });

  gulp.watch([
    'app/*.html',
    'app/images/**/*',
    '.tmp/fonts/**/*'
  ]).on('change', reload);

  gulp.watch('app/styles/**/*.scss', ['styles']);
  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('app/fonts/**/*', ['fonts']);
  gulp.watch('bower.json', ['wiredep', 'fonts']);
});

gulp.task('serve:dist', () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['dist']
    }
  });
});

gulp.task('serve:test', ['scripts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    ui: false,
    server: {
      baseDir: 'test',
      routes: {
        '/scripts': '.tmp/scripts',
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('test/spec/**/*.js').on('change', reload);
  gulp.watch('test/spec/**/*.js', ['lint:test']);
});

// inject bower components
gulp.task('wiredep', () => {
  gulp.src('app/styles/*.scss')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      exclude: ['bootstrap-sass'],
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});
//執行build以前先執行數組列表裏的任務
gulp.task('build', ['lint', 'html', 'images', 'fonts', 'extras'], () => {
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});
//gulp==gulp default  默認執行的任務
gulp.task('default', ['clean'], () => {
  gulp.start('build');
});

  

 

本文標題:Yeoman+Bower+gulp web前端自動化工做流程(初級教程)

原創做者:Jiao Shou

發佈時間:2016年10月12日 - 12:20

最後更新:2016年10月12日 - 22:39

原始連接:http://www.cnblogs.com/jiaoshou/p/5910129.html

許可協議:轉載本篇文章時請務必以超連接形式標明文章原文連接和做者信息。

掃描二維碼,分享此文章

相關文章
相關標籤/搜索