不解釋
js檢測工具用來css
經常使用的js檢測工具備jshint、jslint、eslint等, 推薦用eslint。
結合gulp的話,用gulp-eslint這個插件。使用eslint時配置一個.eslintrc
文件,用來編寫自定義js規則。
若是用到了es模塊,須要在.eslintrc
配置中指定parserOptions的sourceType爲module
。html
{ "root": true, "env": { "browser": true, "node": true, "es6": true }, "parserOptions": { "sourceType": "module" }, "extends": "eslint:recommended", //使用推薦的eslint語法 "rules": { "indent": ["error", 4], //自定義indent爲4個空格,級別爲error "semi": ["off", "always"], "no-console": "off", "no-unused-vars": "off" } }
使用prettier, 根據prettier自定義來強制修改js代碼。
能夠在使用prettier時添加options,或者創建一個config文件來配置options也能夠。
參考這裏前端
{ singleQuote: true, trailingComma: "all", bracketSpacing : true, semi: true, tabWidth: 4, //定義indent爲4個空格 printWidth: 120 }
若是gulp一個task依賴一個或者多個異步任務時, 須要判斷這個異步是否完成,才能進行下一個任務,
這樣才能保證gulp的任務讓順序執行。
異步任務的處理能夠參考這裏node
經過del模塊能夠刪除指定file
很簡單: gulp.src() 獲取目錄下全部文件 gulp.dest()輸出到指定目錄
run-sequence
這個模塊用來在gulp中控制多個任務讓順序執行git
1. 是否是常常出現indent不齊 2. 當看到別人用雙引號引字符串時想給他改爲單引號 3. 有的語句結尾有分號結束,有的語句結尾沒有分號結束, 強迫症的你有沒有想它的衝動
這些能夠經過下面這個思路解決。es6
// js eslint set gulp.task('js_lint', function () { return gulp.src('./src/js/**/*.js') //步驟1 .pipe($.prettier({ //步驟2 singleQuote: true, //自定義選項 trailingComma: "all", bracketSpacing : true, semi: true, tabWidth: 4, printWidth: 120 })) .pipe($.eslint()) //步驟3 .pipe($.eslint.format()) //輸出到console .pipe($.eslint.failAfterError()) //出現錯誤時,指定這個任務不成功 .pipe(gulp.dest('./src/tempjs')) //步驟4 }); // js file copy gulp.task('copy_js', function () { //步驟5 return gulp.src('./src/tempjs/**/*.js') .pipe(gulp.dest('./src/js')) }); // js file clean gulp.task('clean', function (cb) { //步驟6 return del('./src/tempjs', cb); }); // js forma gulp.task('format_js', function (cb) { runSequence('js_lint','copy_js','clean',cb); //指定執行順序 });
這個插件目的是在commit以前,執行相關操做"precommit": "gulp format_js"
github
這個插件目的是創建和git之間的hooks(鉤子), 一般和precommit結合用,
好比使用git commit這個命令時, 會經過hooks調用precommit語句。
這樣咱們就不須要專門去執行npm run precommit
這個命令了,
當咱們git commit的時候,husky會自動調用npm run precommit
。npm
可是還有一個問題, 上面執行完git commit 後,經過prettier修改了全部的js文件,
有些便不是我本身修改的文件,也會被強制修改,
因而能夠經過lint-staged這個node模塊來指定stage中的文件。
思想很簡單,只對git stage中的文件處理。
能夠參考這裏gulp
一般使用它的思想:segmentfault
precommit
precommit
執行lint-staged
,即只對git stage中的文件進行處理lint-staged
中配置prettier修改js文件(添加一個config文件來配置)lint-staged
中配置eslintjs檢測文件(添加一個eslintrc文件來配置)"scripts": { "precommit": "lint-staged" }, "lint-staged": { "*.js": [ // 要處理的js路徑 "prettier --write", //要處理的文件上修改 "eslint --fix", // 參數fix的意思是:根據eslint配置文件自動修復js文件 "git add" ] },
prettier 能強制修改js,eslint --fix也能強制修改js, 區別是什麼呢???
個人理解prettier更強一點,eslint --fix 強制修改有限。
這裏有一個注意點
,prettier
的配置參數, 經過添加一個config文件來配置。
能夠在使用prettier時添加options,或者創建一個config文件來配置options也能夠。
"lint-staged"的配置的意思是,
坑對git stage中的文件的操做,如eslint *.js, git add *.js
, 不能用寫gulp *.js
參考這裏
我添加的是 prettier.config.js
文件,
module.exports = { printWidth: 120, parser: "flow", singleQuote: true, tabWidth: 4, bracketSpacing : true, semi: true };
eslintrc前面已經寫過了。 經過lint-staged就不須要第7步中生成一個臨時文件(tempjs)來過渡了, 由於prettier就直接處理stage終端文件了。
第7步的思想能夠簡化爲:
這樣減小了臨時文件夾的輸出,複製,刪除。
這樣也不須要寫gulp task了,直接經過兩個prettier,eslint配置文件就搞定了。
babel用來將es6語法轉化爲es5, 好比es6中的let轉化爲var, 變量字符串拼接轉化爲+,等等。 結合gulp用,就是gulp-babel, 它依賴於babel-core,因此須要安裝gulp-babel和babel-core。 本身的理解: babel, babel-core提供了babel的運行環境(理解有錯誤的話,以後改正)。 只有這兩個(babel, babel-core)還不能實現轉譯,須要transform插件(如babel-preset-env) 而後須要安裝babel-preset-env來將本身寫的es6(源碼),根據當前執行環境(瀏覽器), 轉化爲es5(當前環境-瀏覽器能識別的語法) 何時用這個babel呢, 獲取源碼後,合併壓縮以前。
gulp.src('*.js') .pipe($.babel({ presets:['env'] })) .pipe(js合併) .pipe(js壓縮)
坑 若是使用uglify來壓縮js文件, 須要配置babel的options,
添加forceAllTransforms: true
便可以。參考這裏
爲何須要合併js呢,經過合併js文件,能夠減小http請求。
經過gulp-concat能夠將多個js文件合併成一個js文件。 用法相對簡單,
gulp.src('src/js/**/*.js') //想要合併的js文件 .pipe($.concat('all.js')) //concat的參數指定合併後的文件名 .pipe(gulp.dest('dist/js/')) //合併後的目錄
如今有一個新的需求task1, 須要單獨寫幾個js文件,
可是不想和其餘js合併到一塊兒,也就是說想單獨合併這幾個js文件,而後單獨輸出,
這個時候, 就要從新寫一個gulp task來合併。
gulp.src('src/js/task1/**/*.js') //task1下,想要合併的js文件 .pipe($.concat('task1.js')) //task1下全部js文件合併輸出爲task1 .pipe(gulp.dest('dist/js/')) //合併後的目錄
當這種新的需求不少的時候,就須要不斷添加新的gulp task,在大項目多人一塊兒寫不一樣的新需求時很麻煩。
因而能夠創建一箇中間文件(middle),
在這個中間文件添加想要合併的js文件,及想要輸出的js文件。
gulp task只是處理這個中間文件。
這樣有新的需求時,修改中間文件就能夠了, 就不須要修改gulp的配置文件了。
中間文件,我這裏選擇yaml。
concat - src: - src/js/task1/top.js - src/js/task1/background.js out: task1.js - src: - src/js/task2/top.js - src/js/task2/index.js out: task2.js
這樣就實現了輸出到不一樣js中了。
那麼, gulp中task怎麼寫呢?
由於要處理yaml文件,須要安裝js-yaml 這個插件
關於yaml能夠參考阮教授的文章
gulp.task('concat', function() { var concatData = yaml.safeLoad( //經過yaml.safeLoad()轉化爲js語言,能夠用console.log(concatData)打出來出來看看 fs.readFileSync('./example.yml', 'utf8') //讀取fs模塊讀取文件內容,能夠用console.log()打出來出來看看 ); for (var i = 0; i < doc.concat.length; i++) { gulp.src(concatData.concat[i].src) .pipe($.concat({path: concatData.concat[i].out})) .pipe(gulp.dest('../dist/js/build/')) } })
若是task是上面這樣寫的話, 還不能達到要求
由於這個任務是比較耗時的,致使咱們不能準確判斷這個任務何時結束,這時須要進行異步處理,此次用promise處理。
安裝bluebird
使用promise。
var Promise = require( 'bluebird'); gulp.task('concat', function() { var concatData = yaml.safeLoad( //經過yaml.safeLoad()轉化爲js語言,能夠用console.log(concatData)打出來出來看看 fs.readFileSync('./example.yml', 'utf8') //讀取fs模塊讀取文件內容,能夠用console.log()打出來出來看看 ); return new Promise(function (resolve, reject) { setTimeout(function() { for (var i = 0; i < doc.concat.length; i++) { gulp.src(concatData.concat[i].src) .pipe($.concat({path: concatData.concat[i].out})) .pipe(gulp.dest('../dist/js/vendor/')) } resolve(); },500) }) })
gulp-uglify 用來壓縮js文件
壓縮很簡單, 獲取js原文件,合併,而後壓縮
gulp.task('uglify_js', function () { return gulp .src('src/js/**/*.js') .pipe( $.babel({ presets: [ ['env', { forceAllTransforms: true } ] // forceAllTransforms用來解決uglify不支持es6 ] }) ) .pipe($.concat('all.js')) .pipe($.uglify()) .pipe(gulp.dest('./dist')); })
sourcemap 的目的:還原源碼, 什麼意思呢? 當咱們將源碼通過合併,壓縮處理後,成爲了一個文件,不方便調試。 特別是壓縮後更是面目全非,這樣咱們在開發階段不能實現debug,好比打斷點功能就不可能實現了。 sorucemap就是解決的這個問題。 使用sourcemap, * sourcemap.init() 初始化 * sourcemap.write('sourcemap') //指定目錄,存放一一對應的map文件 通過sourcemap處理後,在目標目錄(dest指定的)下,生成一個新文件(與轉譯前對應的map文件), 目錄結構與轉譯前徹底對應。這樣咱們就很容易找到某個文件,而後實現打斷點。
gulp.task('concat_js', function() { return gulp .src('src/js/**/*.js') .pipe($.sourcemaps.init()) .pipe($.concat('all.js')) .pipe($.sourcemaps.write('sourcemap')) .pipe(gulp.dest('./dist')); });
在dist目錄下,就能發現sorucemap文件, 裏面的目錄結構和src/js下的目錄結構如出一轍。這樣和方便查找和操做。
規範校驗js寫法的工具備jslint,jshint,最近的eslint等等, 規範校驗css寫法的工具備csslint,stylelint等等。
stylelint用來檢測css是否根據配置文件來寫的,是基於postcss的一個檢測工具。
stylefmt是一個根據stylelint的配置文件來強制修改css文件的插件。有點prettier的意思。
可是能夠不用stylefmt, 在stylelint的選項中添加 --fix
也能夠修改css文件。
npm install gulp-postcss gulp-stylelint stylelint stylelint-config-standard -save-dev
使用stylelint時,有個標準配置插件, stylelint-config-standard。
如下爲 stylelint的配置文件(.stylelintrc)
{ "extends": "stylelint-config-standard", // 使用stylelint的默認標準配置 "rules": { "declaration-block-trailing-semicolon": null, // 各類規則,根據本身須要能夠靈活配置 "indentation": 4, "block-no-empty": null, "max-empty-lines": 1, "selector-list-comma-newline-after": never-multi-line, "at-rule-no-unknown": null, "declaration-colon-space-after": null, "no-duplicate-selectors" : null, "no-descending-specificity": null, "selector-pseudo-element-colon-notation": null, "no-empty-source": null } }
結合gulp用。
gulp.task('lint_css', function () { return gulp.src('src/css/**/*.css') .pipe($.stylelint({ reporters: [ {formatter: 'string', console: true} //將錯誤輸出到console ], fix: true })) .pipe(gulp.dest('./dist/css')); });
根據不一樣瀏覽器自動添加前綴 (autoprefixer)
當咱們想在css中實現上述等功能時,能夠用postcss。
postcss就是一個平臺,能夠經過添加各類插件來實現上述等功能。
npm install postcss-cssnext postcss-simple-vars postcss-nested --save-dev
能夠寫一個postcss的配置文件來專門規範postcss相關的配置,也能夠直接寫在在gulp配置文件中。
var cssnext = require('postcss-cssnext'); var simpleVars = require('postcss-simple-vars'); var nested = require('postcss-nested') gulp.task('concat_css', function () { var plugins = [ cssnext(), // 處理cssnext simpleVars(), // 處理變量 nested() // 處理向sass那樣的內嵌寫法 ]; return gulp.src('src/css/**/*.css') .pipe($.sourcemaps.init()) .pipe($.postcss(plugins)) .pipe($.sourcemaps.write('sourceMap/css')) .pipe(gulp.dest('./dist/css')); })
gulp經過正則匹配很方便的實現多入口多輸出的功能。 入口文件(多入口): gulp.src('src/css/**/*.css') 出口文件(多出口): gulp.dest('./dist/css') dist/css目錄下的結構和src/css的結構同樣。
css 的壓縮能夠用gulp-clean-css。 `npm install gulp-clean-css --save-dev`
gulp.task('uglify_css', function () { var plugins = [ cssnext(), // 處理cssnext simpleVars(), // 處理變量 nested() // 處理向sass那樣的內嵌寫法 ]; return gulp.src('src/css/**/*.css') .pipe($.sourcemaps.init()) .pipe($.postcss(plugins)) .pipe($.sourcemaps.write('sourceMap/css')) .pipe($.cleanCss()) .pipe(gulp.dest('./dist/css')); })
因而當咱們想要lint css的時候,執行gulp lint_css
,
想要format css的時候執行gulp concat_css
,
想要壓縮css的時候,執行uglify_css
。
可是這樣很麻煩, 能夠在添加一個task,執行全部想要執行的task。
gulp.task('format_js', function (cb) { runSequence('js_lint','copy_js','clean',cb); });
最後附上完整的(github源代碼)[https://github.com/zhangchch/...]。
以上都是本身的理解,若有錯誤的地方,真心求指教。