基于 Express+Gulp+BrowserSync 搭建一套高性能的前端開發環境

qthl001 8年前發布 | 27K 次閱讀 CSS JavaScript開發 gulp

來自: www.kisnows.com

為什么要搭這么一套開發環境

公司 Pc 端以前遺留的項目,都是基于 jekyll+ruby-sass 這一套比較老的技術搭建的。不過 jekyll 的模版繼承加上 sass 強大預處理能力,同時配合 Grunt 做任務管理,一切還是很得心應手的。

然而隨著項目規模的急劇增大,這一套東西的速度是在是太慢了,一至于后來一旦這個項目有需要求要改我就頭疼,倒不是說頭疼需求怎么改,而是你隨便改一個文件,從 jekyll 檢測到改動到編譯完 sass 到瀏覽器自動刷新,基本需要 40+ s,這完全不能接受。

于是一直就打算新搭一套開發環境,剛好前段時間有個新項目,我就拿來操刀動手了,目前已經用它做了倆個項目下來,在原有基礎上做了一些修改之后,已經完全可以替代原來那一套東西了。

性能

得益于 node-sass 對 ruby-sass 在編譯速度上的碾壓以及被 jade 完爆的 jekyll。

現在項目中從文件變動=>編譯完成=>瀏覽器自動刷新,整個過程在 1s 左右,可以說速度提升了幾十倍。

而且整個過程都是全自動的,無論你修改了 js,css 還是 html 文件,瀏覽器都會在重新編譯完成后自動刷新。

文件結構

這是項目開發時的文件結構:

其中 public,router,views 都是 express 默認的文件結構,這里就不做介紹了。submodule 是我們不同項目中公用的代碼庫,這樣可以少寫很多公共代碼。

技術細節

整個項目的技術棧是 jade+node-sass+js,實現全自動開發。首先在 views 下面,定義好 jade 模版文件,然后開始新加頁面

關系依賴

這個環境,主要基于 Express,Gulp 以及一系列的 Gulp 插件搭建,這個是開發環境的依賴關系:

{
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0"
  },
  "devDependencies": {
    "browser-sync": "^2.9.1",
    "del": "^2.0.2",
    "gulp": "^3.9.0",
    "gulp-autoprefixer": "^3.0.1",
    "gulp-jade": "^1.1.0",
    "gulp-nodemon": "^2.0.4",
    "gulp-sass": "^2.0.4",
    "gulp-sourcemaps": "^1.5.2",
    "jade": "^1.11.0"
  }
}

其中,express 主要用來渲染 jade 模版引擎以及提供路由功能,同時起一個本地的服務器。有人說,渲染 jade 模版,我直接用 gulp 也可以啊。是的,gulp 是可以直接渲染 jade 模版,但是有一個問題,就是如果你本地只修改了一個 jade 文件時候,gulp 也需要把所有的 jade 文件全部渲染一遍,這明顯會浪費很多時間。

所以我引入了 express,只會按需渲染 jade,節省了很多時間。同時一個高效的開發環境必須有瀏覽器自動刷新,但是 express 沒有這個功能。所以我引入了 browser-sync,用它來代理 express 啟動的本地服務,然后來監測本地文件的變動,來做到瀏覽器自動刷新。

有同學可能會問了,如果我改了 express 相應的 js 文件怎么辦,或者 jade 文件編譯出錯了怎么辦。因為這些時候 express 服務器都會 crash 掉,需要重啟。所以我引入了 nodemon,來做 express 服務器的自動重啟功能。

在這個環境下面,我在開發中所能碰到的所有 jade,scss,js 文件的改動都會被檢測到并作出相應的動作,而且速度還非常快。讓我可以花更多時間在業務代碼的開發上,而不是不斷重啟服務和刷新瀏覽器。

最后

這個東西被我放到 Github上了, 地址在這。

同時附上 gulpfile 全文,以供參考:

'use strict';

var gulp = require('gulp'); var browserSync = require('browser-sync'); var reload = browserSync.reload; var sass = require('gulp-sass'); var prefix = require('gulp-autoprefixer'); var nodemon = require('gulp-nodemon'); var sourcemaps = require('gulp-sourcemaps'); var jade = require('gulp-jade'); var stylus = require('gulp-stylus'); var rename = require('gulp-rename'); var del = require('del');

//dev task start //DONE can not compile the sass or less file gulp.task('sass', function () { return gulp.src(['./sass/personal.scss']) .pipe(sourcemaps.init()) .pipe(sass({errLogToConsole: true}) .on('error', sass.logError)) .pipe(prefix('last 2 versions', '> 1%', 'ie 8', 'Android 2')) .pipe(sourcemaps.write()) .pipe(gulp.dest('./public/css')) .pipe(reload({stream: true})); });

gulp.task('browser-sync', ['nodemon'], function () { browserSync.init(null, { proxy: 'http://localhost:3000', files: ['public//.', 'views//.', 'submodule/*/.*'], browser: 'google chrome', notify: false, port: 5000 }); });

gulp.task('movesub', function () { return gulp.src(['./submodule/images/*/.*'], {base: './submodule'}) .pipe(gulp.dest('./public')) });

gulp.task('stylus', function () { return gulp.src('submodule/stylus/public.styl') .pipe(stylus()) .pipe(rename({ extname: '.scss' })) .pipe(gulp.dest('submodule/stylus/')) });

gulp.task('nodemon', function (cb) { del(['./public/*.html']);

var called = false;

return nodemon({ script: 'bin/www' }).on('start', function () { if (!called) { cb(); called = true; } }); }); //dev task end

gulp.task('clean', function (cb) { del(['./dist/*'], cb) });

gulp.task('copy', function () { return gulp.src([ 'public/css//*', 'public/images//', 'public/js/**/', 'public/pageScripts/*/' ], {base: './public'}) .pipe(gulp.dest('./dist')) });

//build task start //DONE add build task gulp.task('jade', function () { return gulp.src(['views//*.jade', '!views/layout//.jade', '!views/includes/**/.jade']) .pipe(jade({pretty: true})) .pipe(gulp.dest('./dist')); }); //build task end

gulp.task('dist', ['clean', 'copy', 'jade']);

gulp.task('default', ['browser-sync', 'sass', 'movesub'], function () { gulp.watch(['sass//.', '.submodule/stylus//.'], ['sass']); });</pre> </div>

 本文由用戶 qthl001 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!