Gulp開發(fā)教程

作者:Midaoi
原文地址:http://www.cnblogs.com/Midaoi/p/4969812.html

對網(wǎng)站資源進行優(yōu)化,并使用不同瀏覽器測試并不是網(wǎng)站設(shè)計過程中最有意思的部分,但是這個過程中的很多重復(fù)的任務(wù)能夠使用正確的工具自動完成,從而使效率大大提高,這是讓很多開發(fā)者覺得有趣的地方担败。

Gulp是一個構(gòu)建系統(tǒng),它能通過自動執(zhí)行常見任務(wù),比如編譯預(yù)處理CSS鼠渺,壓縮JavaScript和刷新瀏覽器,來改進網(wǎng)站開發(fā)的過程眷细。通過本文拦盹,我們將知道如何使用Gulp來改變開發(fā)流程,從而使開發(fā)更加快速高效溪椎。

What Is Gulp?

Gulp是一個構(gòu)建系統(tǒng)普舆,開發(fā)者可以使用它在網(wǎng)站開發(fā)過程中自動執(zhí)行常見任務(wù)。Gulp是基于Node.js構(gòu)建的校读,因此Gulp源文件和你用來定義任務(wù)的Gulp文件都被寫進了JavaScript(或者CoffeeScript)里奔害。前端開發(fā)工程師還可以用自己熟悉的語言來編寫任務(wù)去lint JavaScript和CSS、解析模板以及在文件變動時編譯LESS文件(當(dāng)然這些只是一小部分例子)地熄。

Gulp本身雖然不能完成很多任務(wù)华临,但它有大量插件可用,開發(fā)者可以訪問插件頁面或者在npm搜索gulpplugin就能看到端考。例如雅潭,有些插件可以用來執(zhí)行JSHint揭厚、編譯CoffeeScript執(zhí)行Mocha測試扶供,甚至更新版本號筛圆。

對比其他構(gòu)建工具,比如Grunt椿浓,以及最近流行的Broccoli太援,我相信Gulp會更勝一籌(請看后面的”Why Gulp?”部分),同時我匯總了一個使用Javascript編寫的構(gòu)建工具清單扳碍,可供大家參考提岔。

Gulp是一個可以在GitHub上找到的開源項目。

Installing Gulp

安裝Gulp的過程十分簡單笋敞。首先碱蒙,需要在全局安裝Gulp包:

npm install -g gulp

然后,在項目里面安裝Gulp:

npm install --save-dev gulp

Using Gulp

現(xiàn)在我們創(chuàng)建一個Gulp任務(wù)來壓縮JavaScript文件夯巷。首先創(chuàng)建一個名為gulpfile.js的文件赛惩,這是定義Gulp任務(wù)的地方,它可以通過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,最后通過運行g(shù)ulp minify來執(zhí)行任務(wù)后雷。假設(shè)js目錄下有個app.js文件褒搔,那么一個新的app.js將被創(chuàng)建在編譯目錄下,它包含了js/app.js的壓縮內(nèi)容喷面。想一想星瘾,到底發(fā)生了什么?

我們只在gulpfile.js里做了一點事情惧辈。首先琳状,我們加載gulp和gulp-uglify模塊:

var gulp = require('gulp'),
    uglify = require('gulp-uglify');

然后,我們定義了一個叫minify的任務(wù)盒齿,它執(zhí)行時會調(diào)用函數(shù)念逞,這個函數(shù)會作為第二個參數(shù):

gulp.task('minify', function () {

});

最后,也是難點所在边翁,我們需要定義任務(wù)應(yīng)該做什么:

gulp.src('js/app.js')
   .pipe(uglify())
   .pipe(gulp.dest('build'))

如果你對數(shù)據(jù)流非常熟悉(其實大多數(shù)前端開發(fā)人員并不熟悉)翎承,上面所提供的代碼對你來說就沒有太大意義了。

STREAMS

數(shù)據(jù)流能夠通過一系列的小函數(shù)來傳遞數(shù)據(jù)符匾,這些函數(shù)會對數(shù)據(jù)進行修改叨咖,然后把修改后的數(shù)據(jù)傳遞給下一個函數(shù)。

在上面的例子中,gulp.src()函數(shù)用字符串匹配一個文件或者文件的編號(被稱為“glob”),然后創(chuàng)建一個對象流來代表這些文件甸各,接著傳遞給uglify()函數(shù)垛贤,它接受文件對象之后返回有新壓縮源文件的文件對象,最后那些輸出的文件被輸入gulp.dest()函數(shù)趣倾,并保存下來聘惦。

整個數(shù)據(jù)流動過程如下圖所示:

當(dāng)只有一個任務(wù)的時候,函數(shù)并不會起太大的作用儒恋。然而善绎,仔細思考下面的代碼:

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诫尽。

這個任務(wù)會讓所有的文件匹配js/*.js(比如js目錄下的所有JavaScript文件)禀酱,并且執(zhí)行JSHint,然后打印輸出結(jié)果箱锐,取消文件縮進比勉,最后把他們合并起來劳较,保存為build/app.js驹止,整個過程如下圖所示:

如果你對Grunt 足夠熟悉,就會注意到观蜗,Gulp和Grunt的工作方式很不一樣臊恋。Grunt不使用數(shù)據(jù)流,而是使用文件墓捻,對文件執(zhí)行單個任務(wù)然后保存到新的文件中抖仅,每個任務(wù)都會重復(fù)執(zhí)行所有進程,文件系統(tǒng)頻繁的處理任務(wù)會導(dǎo)致Grunt的運行速度比Gulp慢砖第。

如果想要獲取更加全面的數(shù)據(jù)流知識撤卢,請查看“Stream Handbook”

GULP.SRC()

gulp.src()方法輸入一個glob(比如匹配一個或多個文件的字符串)或者glob數(shù)組梧兼,然后返回一個可以傳遞給插件的數(shù)據(jù)流放吩。

Gulp使用node-glob來從你指定的glob里面獲取文件,這里列舉下面的例子來闡述羽杰,方便大家理解:

  • js/app.js精確匹配文件渡紫;
  • js/*.js僅匹配js目錄下的所有后綴為.js的文件;
  • js/*/.js匹配js目錄及其子目錄下所有后綴為.js的文件考赛;
  • !js/app.js從匹配結(jié)果中排除js/app.js惕澎,這種方法在你想要匹配除了特殊文件之外的所有文件時非常管用;
  • *.+(js|css) 匹配根目錄下所有后綴為.js或者.css的文件颜骤。

此外唧喉,Gulp也有很多其他的特征,但并不常用。如果你想了解更多的特征欣喧,請查看Minimatch文檔腌零。

js目錄下包含了壓縮和未壓縮的JavaScript文件,現(xiàn)在我們想要創(chuàng)建一個任務(wù)來壓縮還沒有被壓縮的文件唆阿,我們需要先匹配目錄下所有的JavaScript文件益涧,然后排除后綴為.min.js的文件:

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

DEFINING TASKS

gulp.task()函數(shù)通常會被用來定義任務(wù)。當(dāng)你定義一個簡單的任務(wù)時驯鳖,需要傳入任務(wù)名字和執(zhí)行函數(shù)兩個屬性闲询。

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

執(zhí)行g(shù)ulp greet的結(jié)果就是在控制臺上打印出“Hello world”.

一個任務(wù)有時也可以是一系列任務(wù)。假設(shè)要定義一個任務(wù)build來執(zhí)行css浅辙、js扭弧、imgs這三個任務(wù),我們可以通過指定一個任務(wù)數(shù)組而不是函數(shù)來完成记舆。

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

這些任務(wù)不是同時進行的鸽捻,所以你不能認為在js任務(wù)開始的時候css任務(wù)已經(jīng)結(jié)束了,也可能還沒有結(jié)束泽腮。為了確保一個任務(wù)在另一個任務(wù)執(zhí)行前已經(jīng)結(jié)束御蒲,可以將函數(shù)和任務(wù)數(shù)組結(jié)合起來指定其依賴關(guān)系。例如诊赊,定義一個css任務(wù)厚满,在執(zhí)行前需要檢查greet任務(wù)是否已經(jīng)執(zhí)行完畢,這樣做就是可行的:

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

現(xiàn)在碧磅,當(dāng)執(zhí)行css任務(wù)時碘箍,Gulp會先執(zhí)行g(shù)reet任務(wù),然后在它結(jié)束后再調(diào)用你定義的函數(shù)鲸郊。

DEFAULT TASKS

你可以定義一個在gulp開始運行時候默認執(zhí)行的任務(wù)丰榴,并將這個任務(wù)命名為“default”:

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

PLUGINS

Gulp上有超過600種插件供你選擇,你可以在插件頁面或者npm上搜索gulpplugin來瀏覽插件列表秆撮。有些擁有“gulpfriendly”標(biāo)簽的插件四濒,他們不能算插件,但是能在Gulp上正常運行像吻。 需要注意的是峻黍,當(dāng)直接在npm里搜索時,你無法知道某一插件是否在黑名單上(你需要滾動到插件頁面底部才能看到)拨匆。

大多數(shù)插件的使用都很方便姆涩,它們都配有詳細的文檔,而且調(diào)用方法也相同(通過傳遞文件對象流給它)惭每,它們通常會對這些文件進行修改(但是有一些插件例外骨饿,比如validators)亏栈,最后返回新的文件給下一個插件。

讓我們用前面的js任務(wù)來詳細說明一下:

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绒北。開發(fā)者可以參考插件的README文檔,插件有很多配置選項察署,而且給定的初始值通常能滿足需求闷游。細心的讀者可能會發(fā)現(xiàn),程序中JSHint插件執(zhí)行了2次贴汪,這是因為第一次執(zhí)行JSHint只是給文件對象附加了jshint屬性脐往,并沒有輸出。你可以自己讀取jshint的屬性或者傳遞給默認的JSHint的接收函數(shù)或者其他的接收函數(shù)扳埂,比如jshint-stylish.

其他兩個插件的作用很清楚:uglify()函數(shù)壓縮代碼业簿,concat(‘a(chǎn)pp.js’)函數(shù)將所有文件合并到一個叫app.js的文件中。

GULP-LOAD-PLUGINS

我發(fā)現(xiàn)gulp-load-plugin模塊十分有用阳懂,它能夠自動地從package.json中加載任意Gulp插件然后把它們附加到一個對象上梅尤。它的基本用法如下所示:

var gulpLoadPlugins = require('gulp-load-plugins'),
    plugins = gulpLoadPlugins();

你可以把所有代碼寫到一行,但是我并不推薦這樣做岩调。

在執(zhí)行那些代碼之后巷燥,插件對象就已經(jīng)包含了插件,并使用“駝峰式”的方式進行命名(例如誊辉,gulp-ruby-sass將被加載成plugins.rubySass)矾湃,這樣就可以很方便地使用了亡脑。例如堕澄,前面的js任務(wù)簡化為如下:

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'));
});

假設(shè)package.json文件如下面所示:

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

這個例子雖然已經(jīng)夠短了,但是使用更長更復(fù)雜的Gulp文件會把它們簡化成一兩行代碼霉咨。

三月初發(fā)布的Gulp-load-plugins0.4.0版本添加了延遲加載功能蛙紫,提高了插件的性能,因為插件在使用的時候才會被加載進來途戒,你不用擔(dān)心package.json里未被使用的插件影響性能(但是你需要把他們清理掉)坑傅。換句話說,如果你在執(zhí)行任務(wù)時只需要兩個插件喷斋,那么其他不相關(guān)的插件就不會被加載唁毒。

WATCHING FILES

Gulp可以監(jiān)聽文件的修改動態(tài),然后在文件被改動的時候執(zhí)行一個或多個任務(wù)星爪。這個特性十分有用(對我來說浆西,這可能是Gulp中最有用的一個功能)。你可以保存LESS文件顽腾,接著Gulp會自動把它轉(zhuǎn)換為CSS文件并更新瀏覽器近零。

使用gulp.watch()方法可以監(jiān)聽文件,它接受一個glob或者glob數(shù)組(和gulp.src()一樣)以及一個任務(wù)數(shù)組來執(zhí)行回調(diào)。

讓我們看看下面久信,build任務(wù)可以將模板轉(zhuǎn)換成html格式窖杀,然后我們希望定義一個watch任務(wù)來監(jiān)聽模板文件的變化,并將這些模板轉(zhuǎn)換成html格式裙士。watch函數(shù)的使用方法如下所示:

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

現(xiàn)在入客,當(dāng)改變一個模板文件時,build任務(wù)會被執(zhí)行并生成HTML文件腿椎,也可以給watch函數(shù)一個回調(diào)函數(shù)痊项,而不是一個任務(wù)數(shù)組。在這個示例中酥诽,回調(diào)函數(shù)有一個包含觸發(fā)回調(diào)函數(shù)信息的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來監(jiān)聽額外的事件或者向watch中添加文件。例如肮帐,在執(zhí)行一系列任務(wù)和調(diào)用一個函數(shù)時咖驮,你就可以在返回的watcher中添加監(jiān)聽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事件,還可以監(jiān)聽很多其他的事件:

  • end 在watcher結(jié)束時觸發(fā)(這意味著训枢,在文件改變的時候托修,任務(wù)或者回調(diào)不會執(zhí)行);
  • error 在出現(xiàn)error時觸發(fā)恒界;
  • ready 在文件被找到并正被監(jiān)聽時觸發(fā)睦刃;
  • nomatch 在glob沒有匹配到任何文件時觸發(fā)。

Watcher對象也包含了一些可以調(diào)用的方法:

  • watcher.end()停止watcher(以便停止執(zhí)行后面的任務(wù)或者回調(diào)函數(shù))十酣;
  • watcher.files()返回watcher監(jiān)聽的文件列表涩拙;
  • watcher.add(glob)將與指定glob相匹配的文件添加到watcher(也接受可選的回調(diào)當(dāng)?shù)诙€參數(shù));
  • watcher.remove(filepath)從watcher中移除個別文件耸采。

Reloading Changes In The Browser

當(dāng)一個文件被修改或者Gulp任務(wù)被執(zhí)行時可以用Gulp來加載或者更新網(wǎng)頁兴泥。LiveReload和BrowserSync插件就可以用來實現(xiàn)在游覽器中加載更新的內(nèi)容。

LIVERELOAD

LiveReload結(jié)合了瀏覽器擴展(包括Chrome extension)虾宇,在發(fā)現(xiàn)文件被修改時會實時更新網(wǎng)頁搓彻。它可以和gulp-watch插件或者前面描述的gulp-watch()函數(shù)一起使用。下面有一個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());
});

這會監(jiān)聽到所有與less/*.less相匹配的文件的變化嘱朽。一旦監(jiān)測到變化旭贬,就會生成css并保存,然后重新加載網(wǎng)頁搪泳。

BROWSERSYNC

BroserSync在瀏覽器中展示變化的功能與LiveReload非常相似稀轨,但是它有更多的功能。

當(dāng)你改變代碼的時候森书,BrowserSync會重新加載頁面靶端,或者如果是css文件谎势,會直接添加進css中,頁面并不需要再次刷新杨名。這項功能在網(wǎng)站是禁止刷新的時候是很有用的脏榆。假設(shè)你正在開發(fā)單頁應(yīng)用的第4頁,刷新頁面就會導(dǎo)致你回到開始頁台谍。使用LiveReload的話须喂,你就需要在每次改變代碼之后還需要點擊四次,而當(dāng)你修改CSS時趁蕊,插入一些變化時坞生,BrowserSync會直接將需要修改的地方添加進CSS,就不用再點擊回退掷伙。

BrowserSync提供了一種在多個瀏覽器里測試網(wǎng)頁的很好方式(查看大圖)是己。

BrowserSync也可以在不同瀏覽器之間同步點擊翻頁、表單操作任柜、滾動位置卒废。你可以在電腦和iPhone上打開不同的瀏覽器然后進行操作。所有設(shè)備上的鏈接將會隨之變化宙地,當(dāng)你向下滾動頁面時摔认,所有設(shè)備上頁面都會向下滾動(通常還很流暢!)宅粥。當(dāng)你在表單中輸入文本時参袱,每個窗口都會有輸入。當(dāng)你不想要這種行為時秽梅,也可以把這個功能關(guān)閉抹蚀。

BrowserSync不需要使用瀏覽器插件,因為它本身就可以給你提供文件风纠。(查看大圖

BrowserSync不需要使用瀏覽器插件况鸣,因為它本身就可以為你提供文件服務(wù)(如果文件是動態(tài)的牢贸,則為他們提供代理服務(wù))和用來開啟瀏覽器和服務(wù)器之間的socket的腳本服務(wù)竹观。到目前為止這個功能的使用都十分順暢。

實際上BrowserSync對于Gulp并不算一種插件潜索,因為BrowserSync并不像一個插件一樣操作文件臭增。然而,npm上的BrowserSync模塊能在Gulp上被直接調(diào)用竹习。

首先誊抛,需要通過npm安裝一下:

npm install --save-dev browser-sync

然后gulpfile.js會啟動BrowserSync并監(jiān)聽文件:

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'
      }
   });
});

執(zhí)行gulp browser-sync后會監(jiān)聽匹配文件的變化,同時為app目錄提供文件服務(wù)整陌。

此外BrowserSync的開發(fā)者還寫了很多關(guān)于BrowserSync+Gulp倉庫的其他用途拗窃。

Why Gulp?

前面提到過瞎领,Gulp是為數(shù)不多的使用JavaScript開發(fā)的構(gòu)建工具之一,也有其他不是用JavaScript開發(fā)的構(gòu)建工具随夸,比如Rake九默,那么我們?yōu)槭裁匆x擇Gulp呢?

目前最流行的兩種使用JavaScript開發(fā)的構(gòu)建工具是Grunt和Gulp。Grunt在2013年非常流行宾毒,因為它徹底改變了許多人開發(fā)網(wǎng)站的方式驼修,它有上千種插件可供用戶使用,從linting诈铛、壓縮乙各、合并代碼到使用Bower安裝程序包,啟動Express服務(wù)都能辦到。這些和Gulp的很不一樣幢竹,Gulp只有執(zhí)行單個小任務(wù)來處理文件的插件耳峦,因為任務(wù)都是JavaScript(和Grunt使用的大型對象不同),根本不需要插件焕毫,你只需用傳統(tǒng)方法啟動一個Express服務(wù)就可以了妇萄。

Grunt任務(wù)擁有大量的配置,會引用大量你實際上并不需要的對象屬性咬荷,但是Gulp里同樣的任務(wù)也許只有幾行冠句。讓我們看個簡單的Gruntfile.js,它規(guī)定一個將LESS轉(zhuǎn)換為CSS的任務(wù)幸乒,然后執(zhí)行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文件進行對比懦底,它們執(zhí)行的任務(wù)相同:

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更加頻繁地操作文件系統(tǒng),所以使用數(shù)據(jù)流的Gulp總是比Grunt快罕扎。對于一個小的LESS文件聚唐,gulpfile.js通常需要6ms,而gruntfile.js則需要大概50ms——慢8倍多腔召。這只是個簡單的例子杆查,對于長的文件,這個數(shù)字會增加得更顯著臀蛛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亲桦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浊仆,更是在濱河造成了極大的恐慌客峭,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抡柿,死亡現(xiàn)場離奇詭異舔琅,居然都是意外死亡,警方通過查閱死者的電腦和手機洲劣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門备蚓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來课蔬,“玉大人,你說我怎么就攤上這事郊尝」喊剩” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵虚循,是天一觀的道長同欠。 經(jīng)常有香客問我,道長横缔,這世上最難降的妖魔是什么铺遂? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮茎刚,結(jié)果婚禮上襟锐,老公的妹妹穿的比我還像新娘。我一直安慰自己膛锭,他們只是感情好粮坞,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著初狰,像睡著了一般莫杈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奢入,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天筝闹,我揣著相機與錄音,去河邊找鬼腥光。 笑死关顷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的武福。 我是一名探鬼主播议双,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捉片!你這毒婦竟也來了平痰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤界睁,失蹤者是張志新(化名)和其女友劉穎觉增,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翻斟,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年说铃,在試婚紗的時候發(fā)現(xiàn)自己被綠了访惜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘹履。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖债热,靈堂內(nèi)的尸體忽然破棺而出砾嫉,到底是詐尸還是另有隱情,我是刑警寧澤窒篱,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布焕刮,位于F島的核電站,受9級特大地震影響墙杯,放射性物質(zhì)發(fā)生泄漏配并。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一高镐、第九天 我趴在偏房一處隱蔽的房頂上張望溉旋。 院中可真熱鬧,春花似錦嫉髓、人聲如沸观腊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梧油。三九已至,卻和暖如春州邢,著一層夾襖步出監(jiān)牢的瞬間婶溯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工偷霉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迄委,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓类少,卻偏偏與公主長得像叙身,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子硫狞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 對網(wǎng)站資源進行優(yōu)化信轿,并使用不同瀏覽器測試并不是網(wǎng)站設(shè)計過程中最有意思的部分,但是這個過程中的很多重復(fù)的任務(wù)能夠使用...
    懵逼js閱讀 1,057評論 0 8
  • 編輯于2015年 轉(zhuǎn)載自某作者的譯文 作者要是看到請聯(lián)系我注明出處 對網(wǎng)站資源進行優(yōu)化残吩,并使用不同瀏覽器測試并不是...
    krock01閱讀 445評論 0 2
  • gulpjs是一個前端構(gòu)建工具财忽,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù)泣侮,API也非常簡單即彪,學(xué)...
    依依玖玥閱讀 3,149評論 7 55
  • 1、gulp的安裝 首先確保你已經(jīng)正確安裝了nodejs環(huán)境活尊。然后以全局方式安裝gulp: npm install...
    F_imok閱讀 2,357評論 1 11
  • gulpjs是一個前端構(gòu)建工具隶校,與gruntjs相比漏益,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單深胳,學(xué)...
    井皮皮閱讀 1,291評論 0 10