入門:十分鐘自動化構(gòu)建

你是否還在手動壓縮圖片橙数、js、css帅戒?
是否還在手動編譯sass灯帮、less、coffee逻住?
是否還在手動合并精靈圖钟哥?
是否還在
……

簡單點,干活的方式簡單點鄙信。

在前端技術(shù)飛速發(fā)展的今天瞪醋,如果你還在日復(fù)一日地重復(fù)著那無休止的體力勞動,那你要反思了装诡,這年頭不懂搗鼓個工作流出來都不好意思說自己學(xué)前端的银受。

畢竟javascript是最好的編程語言嘛。:)

玩笑開到這里鸦采,到底什么是工作流宾巍?

工作流(Workflow),指“業(yè)務(wù)過程的部分或整體在計算機(jī)應(yīng)用環(huán)境下的自動化”渔伯。 ——百度百科

如題顶霞,此次的分享主題"自動化構(gòu)建",目的便是介紹如何根據(jù)需要搭建一套工作流锣吼,由淺入深选浑。

一简肴、前提

往下看之前温数,請自備以下知識:

  • nodejs的一些基礎(chǔ)用法,比如:node index.js臼闻;
  • npm的基本用法init读恃、(un)install隧膘、run等;
  • 了解gulp寺惫、webpack(本章不會用到)的用途

以上知識點請務(wù)必掌握疹吃,不然沒法接著往下講,切勿好高騖遠(yuǎn)西雀;
如果你準(zhǔn)備好了萨驶,那我們就開始了!

我們先來設(shè)定一個簡單的需求:

  • 一個本地開發(fā)環(huán)境艇肴,具備監(jiān)控文件變化并實時更新的功能篡撵;
  • 修改代碼判莉,保存之后瀏覽器自動刷新
  • 實時編譯各種預(yù)編譯格式文件
  • 壓縮合并靜態(tài)資源,打包輸出
  • 部署上傳

一言不合就上圖:


自動化構(gòu)建(入門).png

好育谬,有了這個規(guī)劃之后券盅,我們開始著手來實現(xiàn)它。

二膛檀、源碼

首先新建一個項目文件夾project锰镀,接著我們打開命令行工具,切換到這個目錄下咖刃,開始初始化這個項目:

cd project
npm init

按照提示完成初始化泳炉,打開項目我們會得到一個package.json文件像這樣:

// package.json
{
  "name": "project",
  "version": "1.0.0",
  "description": "a test project",
  "main": "index.js",
  "scripts": {
    "test": "node ./build/test.js"
  },
  "author": "jack lo",
  "license": "ISC"
}

緊接著我們先來創(chuàng)造一份源碼,結(jié)構(gòu)如下:

- project
  |- src  // 源文件夾
  | |- tpl
  | | `- index.html
  | |- css
  | | `- index.css
  | |- js
  | | `- index.js
  |- dist  // 打包文件夾
  `- package.json

三嚎杨、編譯打包

一切材料就緒花鹅,我們開始安裝工具包,這一次我們主要使用gulp來構(gòu)建枫浙,不需要用到webpack刨肃,同時,為了實現(xiàn)瀏覽器自動刷新的功能箩帚,我們還需要用到browser-sync真友。

npm install gulp browser-sync --save-dev

這需要花點時間。

---------- 虛度光陰中 ---------

事實上紧帕,這里有個小坑需要我們提前準(zhǔn)備一下盔然,因為我們接下來會用到gulp的cli,所以這里我們需要全局安裝gulp是嗜,沒錯愈案,我就是設(shè)套讓你裝兩遍!

這是個好習(xí)慣鹅搪,請務(wù)必以后也堅持這么做站绪。把開發(fā)時候用到的所有npm包都記錄在package.json文件中,可以方便日后自己以及他人的使用涩嚣。

npm install gulp -g

mac用戶可能還要sudo一下:

sudo npm install gulp -g

回車后按提示輸入密碼崇众,繼續(xù)回車掂僵,就可以正常安裝了航厚。

---------- 再一次虛度光陰中 ---------

ok,安裝完后锰蓬,我們可以開始做點有意義的事了幔睬。

gulp的用法其實相當(dāng)簡單,api也就那么幾個芹扭。簡單來說麻顶,就是寫好一個配置文件gulpfile.js赦抖,然后在命令行里執(zhí)行它。

首先在根目錄下新建一個gulpfile.js辅肾,然后隨便建一個叫做test的任務(wù):

// gulpfile.js
var gulp = require('gulp')

// 創(chuàng)建一個名為test的任務(wù)队萤,任務(wù)內(nèi)容只是簡單地在控制臺輸出一段文本
gulp.task('test', function () {
  return console.log('this is a test')
})

ok,保存矫钓。然后我們回到命令行要尔,輸入以下命令然后回車

gulp test

gulp后面跟的是你所要執(zhí)行的任務(wù)名,于是我們得到了這樣一個結(jié)果

[22:56:35] Using gulpfile ~/project/gulpfile.js
[22:56:35] Starting 'test'...
this is a test
[22:56:35] Finished 'test' after 149 μs

成功輸出文本新娜!恭喜赵辕,你已經(jīng)掌握了gulp一半以上的用法。

現(xiàn)在我們嘗試著來操作文件概龄,我們將src/html里面的html文件給拷貝到dist文件夾(如果不存在則新建)里面去还惠,怎么做?

// 創(chuàng)建一個copy的任務(wù)
gulp.task('copy', function () {
  return gulp.src('src/tpl/*.html')
  .pipe(gulp.dest('dist'))
})

這里的pipe其實是一種管道私杜,你可以一直pipe連著pipe下去蚕键,也就是這個工作流可以一直這樣一層層執(zhí)行下去,隨便你定義多少個處理任務(wù)都行歪今,這就是gulp的特點嚎幸,簡單明了的工作流程。很多人不明白gulp到底是做什么的寄猩,其實到這里嫉晶,就可以有個大概的認(rèn)識了:

gulp是以定義并執(zhí)行一個個任務(wù)的形式來工作的流程管理工具,它的作用在于提供一套簡單易用的工作方式田篇。

在gulp以前替废,處理一份sass文件,你可能需要先執(zhí)行一次編譯的任務(wù)泊柬,編譯成css之后椎镣,再執(zhí)行一遍壓縮css的任務(wù),壓縮完之后兽赁,再手動拷貝到打包文件夾里状答。原本需要分三步來操作的一件事情,在gulp里面就是一個任務(wù)的sei而已:

// 創(chuàng)建一個css的處理任務(wù)
gulp.task('sass', function () {
  return gulp.src('src/sass/*.scss')
  .pipe(sass())
  .pipe(minifycss())
  .pipe(gulp.dest('dist/static'))
})

甚至我們可以同時執(zhí)行多個任務(wù)刀崖,我可以定義好coffee惊科、sass、image亮钦、html的四個任務(wù)馆截,再把他們合并到一個任務(wù)當(dāng)中去,一次性執(zhí)行完:

// 創(chuàng)建一個build的處理任務(wù)
gulp.task('build', ['coffee', 'sass', 'image', 'html'])

我只需要:

gulp build

回車,這酸爽蜡娶。

好了混卵,介紹了這么多內(nèi)容,最后我們還是回到最開始那份需求的實現(xiàn)上來窖张。

我們來建幾個任務(wù)幕随,分別處理js、css宿接、html文件合陵,把js和css文件放到dist/static目錄下,把html文件放到dist下:

gulp.task('css', function () {
  return gulp.src('src/css/*.css')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('js', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('html', function () {
  return gulp.src('src/tpl/*.html')
  .pipe(gulp.dest('dist'))
})

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

命令行g(shù)ulp build一下澄阳,回車拥知!再看看dist文件夾,done碎赢!

咋一看低剔,好像沒什么問題,但好像又有哪里不太對勁肮塞。不對啊襟齿,除了復(fù)制到dist文件夾,好像沒啥功能啊枕赵,說好的壓縮合并呢猜欺?說好的處理預(yù)編譯呢?嗯拷窜,有了這個框架开皿,這些功能我們想加多少加多少。

這樣簡單的項目篮昧,我們沒法玩出花樣赋荆,我們來點預(yù)編譯語言,css用sass代替懊昨,html用swig代替:

- project
  |- src  // 源文件夾
  | |- tpl
  | | `- index.swig
  | |- sass
  | | `- index.scss
  | |- js
  | | `- index.js
  |- dist  // 打包文件夾
  `- package.json

編譯sass需要安裝gulp-sass模塊窄潭,編譯swig需要gulp-swig。注意到了嗎酵颁?基本上gulp的模塊都以gulp-*的形式出現(xiàn)嫉你,所以如果以后你使用gulp的時候想用什么模塊,可以試試在npm搜gulp-模塊名躏惋。

npm install gulp-sass gulp-swig --save-dev

---------- 虛度光陰中 ---------

安裝完后幽污,我們再來修改一下配置文件gulpfile.js

var gulp = require('gulp')
var sass = require('gulp-sass')
var swig = require('gulp-swig')

gulp.task('sass', function () {
  return gulp.src('src/sass/*.scss')
  .pipe(sass({
    outputStyle: 'compressed'  // 此配置使文件編譯并輸出壓縮過的文件
  }))
  .pipe(gulp.dest('dist/static'))
})

gulp.task('js', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('tpl', function () {
  return gulp.src('src/tpl/*.swig')
  .pipe(swig({
    defaults: {
      cache: false  // 此配置強(qiáng)制編譯文件不緩存
    }
  }))
  .pipe(gulp.dest('dist'))
})

gulp.task('build', ['sass', 'js', 'tpl'])

再接著gulp build一下,編譯結(jié)束其掂,可以看看dist下是不是有index.html油挥,dist/static下是不是有編譯完成且壓縮過的index.css潦蝇,沒有你找我款熬!這里就不分別展示源文件和打包后文件的內(nèi)容了深寥,因為并不重要,想看演示項目內(nèi)容的朋友贤牛,可以在文章結(jié)尾處找到本次演示項目的git倉庫鏈接惋鹅。各種預(yù)編語言和前端模板大家可以根據(jù)自己的喜好選擇,筆者只是選擇自己熟悉的幾種來做演示殉簸。

到這里我們基本上已經(jīng)完成打包的工作了闰集,我們來試著搭建開發(fā)環(huán)境。

四般卑、搭建開發(fā)環(huán)境

前文我們提到一個工具browser-sync武鲁,還記得嗎?現(xiàn)在用得上了蝠检!我們先創(chuàng)建一個開發(fā)任務(wù)沐鼠,像gulp build一樣簡單的任務(wù),我們的目標(biāo)是:沒有蛀牙 一句話搞定叹谁。

gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () {
  // do something here...
})

看著好像稍有不同饲梭。這一次我們創(chuàng)建一個叫做dev的任務(wù),這個任務(wù)先執(zhí)行js:dev焰檩、sass:devtpl:dev三個任務(wù)憔涉,然后再執(zhí)行回調(diào)里的內(nèi)容,我們的本地服務(wù)器就是要在回調(diào)里去定義并且啟動析苫。

在這之前兜叨,我們先來了解一下browser-sync:

Browsersync能讓瀏覽器實時、快速響應(yīng)您的文件更改(html衩侥、js浪腐、css、sass顿乒、less等)并自動刷新頁面议街。 ——Browsersync中文網(wǎng)

事實上Browsersync可以理解為一個本地服務(wù)器,類似于Apache璧榄,不同的是特漩,Browsersync只提供很簡單的http功能,它的主要功能骨杂,是通過搭建一個本地服務(wù)器涂身,并且監(jiān)聽文件的更改,自動刷新瀏覽器搓蚪,實時地呈現(xiàn)最新內(nèi)容蛤售。

browser-sync的用法:

var browserSync = require('browser-sync').create()

browserSync.init({
  server: {
    baseDir: "./"  // 設(shè)置服務(wù)器的根目錄
  }
})

其實也很簡單,沒有太多內(nèi)容,現(xiàn)在我們要將它整合進(jìn)我們的gulp任務(wù)里悴能,搗鼓幾下揣钦,我們得到:

gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () {
  browserSync.init({
    server: {
      baseDir: "./dist"  // 設(shè)置服務(wù)器的根目錄為dist目錄
    },
    notify: false  // 開啟靜默模式
  })

  // 我們使用gulp的文件監(jiān)聽功能,來實時編譯修改過后的文件
  gulp.watch('src/js/*.js', ['js:dev'])
  gulp.watch('src/sass/*.scss', ['sass:dev'])
  gulp.watch('src/tpl/*.swig', ['tpl:dev'])
})

這里的watch行為可以簡單理解為:我(gulp)就這么盯著你(src/js/*.js文件)漠酿,只要你被改動了冯凹,我就馬上執(zhí)行js:dev任務(wù)來處理你,產(chǎn)生最新的文件炒嘲。

那么宇姚,我們現(xiàn)在還需要補(bǔ)充一下js:devsass:devtpl:dev這三個任務(wù)夫凸,與原來的js浑劳、sasstpl三個任務(wù)大同小異,這里籠統(tǒng)地過一遍就好夭拌,我們直接看代碼:

var browserSync = require('browser-sync').create()
var reload = browserSync.reload

gulp.task('sass:dev', function () {
  return gulp.src('src/sass/*.scss')
  .pipe(sass())
  .pipe(gulp.dest('dist/static'))
  .pipe(reload({stream: true}))
})

gulp.task('js:dev', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
  .pipe(reload({stream: true}))
})

gulp.task('tpl:dev', function () {
  return gulp.src('src/tpl/*.swig')
  .pipe(swig({
    defaults: {
      cache: false  // 此配置強(qiáng)制編譯文件不緩存
    }
  }))
  .pipe(gulp.dest('dist'))
  .pipe(reload({stream: true}))
})

這里的reload方法呀洲,我們不需要過多了解,只要知道啼止,通過執(zhí)行它就可以刷新瀏覽器。這里的stream用法可以查閱官方文檔献烦,這里不重要所以不細(xì)講。

值得留意的是:這里的sass:dev任務(wù)巩那,我們并沒有像sass任務(wù)一樣配置編譯模式為compressed,也就是不使用壓縮功能即横,為什么呢噪生?事實上,我們在開發(fā)的時候跺嗽,并不需要壓縮靜態(tài)資源文件,可以說我們不在意它的體積是大一點還是小一點桨嫁,我們在意的是樣式是否寫得符合期望,我們在乎的是功能是否實現(xiàn)份帐,所以不需要啟用壓縮或者其他的什么優(yōu)化功能璃吧,這樣可以減輕編譯的負(fù)擔(dān),加快編譯速度废境。如果你對js或者圖片也使用了壓縮功能筒繁,建議在開發(fā)模式下去掉巴元,只在打包模式下使用。

最終我們整理得到一份gulpfile.js文件:

var gulp = require('gulp')
var sass = require('gulp-sass')
var swig = require('gulp-swig')
var browserSync = require('browser-sync').create()
var reload = browserSync.reload

gulp.task('sass', function () {
  return gulp.src('src/sass/*.scss')
  .pipe(sass({
    outputStyle: 'compressed'  // 此配置使文件編譯并輸出壓縮過的文件
  }))
  .pipe(gulp.dest('dist/static'))
})

gulp.task('js', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('tpl', function () {
  return gulp.src('src/tpl/*.swig')
  .pipe(swig({
    defaults: {
      cache: false  // 此配置強(qiáng)制編譯文件不緩存
    }
  }))
  .pipe(gulp.dest('dist'))
})

gulp.task('sass:dev', function () {
  return gulp.src('src/sass/*.scss')
  .pipe(sass())
  .pipe(gulp.dest('dist/static'))
  .pipe(reload({stream: true}))
})

gulp.task('js:dev', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
  .pipe(reload({stream: true}))
})

gulp.task('tpl:dev', function () {
  return gulp.src('src/tpl/*.swig')
  .pipe(swig({
    defaults: {
      cache: false  // 此配置強(qiáng)制編譯文件不緩存
    }
  }))
  .pipe(gulp.dest('dist'))
  .pipe(reload({stream: true}))
})

gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () {
  browserSync.init({
    server: {
      baseDir: "./dist"
    },
    notify: false
  })
  gulp.watch('src/js/*.js', ['js:dev'])
  gulp.watch('src/sass/*.scss', ['sass:dev'])
  gulp.watch('src/tpl/*.swig', ['tpl:dev'])
})

gulp.task('build', ['sass', 'js', 'tpl'])

嗯,完美幻赚,到這一步,我們這個自動化構(gòu)建已經(jīng)基本完成了落恼,而且還算是完整。現(xiàn)在佳谦,我們開發(fā)的時候,就執(zhí)行g(shù)ulp dev啥刻,打包的時候就執(zhí)行g(shù)ulp build,是不是很方便可帽?

注意:gulp dev任務(wù)啟動以后是一直保持工作狀態(tài)的窗怒,也就是它不像gulp build一樣一次性執(zhí)行完映跟,它是keep alive的扬虚,所以我們?nèi)绻V惯@個任務(wù),需要手動按ctrl+c組合鍵辜昵,結(jié)束這個任務(wù)。

五贷洲、補(bǔ)充

然而事情還沒完,我們的目標(biāo)是:裝逼 盡善盡美优构!

有三個地方其實我們還沒做到位:

  • 對命令進(jìn)行包裝雁竞,盡量簡潔钦椭。gulp dev和gulp build其實已經(jīng)很簡潔了,但事實上這只是因為這個項目很簡單侥锦,用到的命令很少,在開發(fā)復(fù)雜的項目時恭垦,我們通常要輸入復(fù)雜的一長串的命令行格嗅。gulp dev其實也是gulp --gulpfile gulpfile.js dev的缺省寫法而已番挺,具體情況可以去gulp官網(wǎng)了解。所以我們需要有更簡潔的方式去執(zhí)行這些預(yù)先準(zhǔn)備好的腳本屯掖,就好像windows系統(tǒng)下的快捷方式玄柏;
  • 目前的情況是,我們每次執(zhí)行贴铜,都會將文件拷貝到dist目錄下粪摘,但是卻沒有刪除的工作,也就是說文件數(shù)量只增不減绍坝,這樣多次下來徘意,隨著文件的增刪改動,必然會遺留很多沒有用的文件轩褐。我們需要每次啟動編譯或者打包之前,先把整個dist文件夾刪除邑退,然后再重新生成dist劳澄;
  • 上傳的功能還沒做呢?秒拔!

二話不說就開工!

第一點很好解決作谚,我們可以把腳本作為一項配置存放在package.json文件中:

{
  "name": "project",
  "version": "1.0.0",
  "description": "a test project",
  "main": "index.js",
  "scripts": {
    "dev": "gulp dev",  // 開發(fā)腳本
    "build": "gulp build",  // 打包腳本
    "test": "node ./build/test.js"
  },
  "author": "jack lo",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.13.0",
    "gulp": "^3.9.1",
    "gulp-sass": "^2.3.2",
    "gulp-swig": "^0.8.0"
  }
}

注意到了嗎庵芭?scripts項就是用來預(yù)定義腳本的地方,我們可以很方便地把腳本按照上面的形式封裝好双吆,然后執(zhí)行的方式就變成了:

npm run dev  // 執(zhí)行開發(fā)
npm run build  // 執(zhí)行打包

搞定会前!

我們接著看第二點匾竿,刪除dist文件夾,多簡單的事傲俦印昵慌!鼠標(biāo)右鍵,刪除废离,搞定礁芦!

……

哪有這么low的事,我們的目標(biāo)是:懶癌晚期 能不自己做的事情肖方,絕不自己動手未状。

有一個叫做rimraf的包,可以幫我們做這事司草,我們需要用到它的cli,所以跟gulp一樣猜憎,我們?nèi)职惭b它:

npm install rimraf -g

安裝完后搔课,我們再重新修改一下package.json文件中的scripts內(nèi)容:

{
  "name": "project",
  "version": "1.0.0",
  "description": "a test project",
  "main": "index.js",
  "scripts": {
    "dev": "gulp dev",  // 開發(fā)腳本
    "build": "rimraf dist && gulp build",  // 打包腳本
    "test": "node ./build/test.js"
  },
  "author": "jack lo",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.13.0",
    "gulp": "^3.9.1",
    "gulp-sass": "^2.3.2",
    "gulp-swig": "^0.8.0"
  }
}

ok,現(xiàn)在試試執(zhí)行npm run build爬泥,dist文件夾是不是先被刪除,然后再重新生成了踩官?

完美境输。

第三點放到最后才補(bǔ)充肾扰,主要是考慮到它并不是必要的蛋逾,因為有些項目并不需要ftp上傳,一般是提交svn区匣,然后再由后端或者運維去部署,筆者是需要將靜態(tài)資源上傳到cdn服務(wù)器進(jìn)行加速的莲绰,所以需要這樣一個任務(wù)姑丑,在此我們簡單介紹一下。

舉一反三一下栅哀,我們再創(chuàng)建一個upload任務(wù):

var ftp = require('gulp-ftp')
var gutil = require('gulp-util')

gulp.task('upload', function () {
  return gulp.src('dist/**')
  .pipe(ftp({
    host: '8.8.8.8',  // 遠(yuǎn)程主機(jī)ip
    port: 22,  // 端口
    user: 'username',  // 帳號
    pass: 'password',  // 密碼
    remotePath: '/project'  // 上傳路徑,不存在則新建
  }))
  .pipe(gutil.noop())
})

自行安裝一下gulp-ftp和gulp-util兩個包戳晌,然后在package.json文件中的scripts補(bǔ)充一個腳本npm run upload來執(zhí)行g(shù)ulp upload痴柔。

筆者通常都是打包之后順便上傳,命令行直接輸入npm run build && npm run upload咳蔚,回車,然后就可以愉快地去跟旁邊的妹紙聊天了侈询。

六堆巧、總結(jié)

到這里,我們已經(jīng)完整搭完了這一套簡易自動化工具谍肤,好像講了很多東西,其實總結(jié)起來內(nèi)容非常少:我們只不過分別用三個小任務(wù)(sass篷角、js系任、tpl)虐块,組成了build和dev這兩個大任務(wù)嘉蕾,僅此而已。熟練的情況下操作起來错忱,整個過程也不過十分鐘!

ps:網(wǎng)絡(luò)太差怪我咯儿普?呵呵掷倔。

由于時間和篇幅關(guān)系,我們只簡單處理了css勒葱、js和html,事實上错森,你還可以在這個基礎(chǔ)上繼續(xù)完善下去篮洁,js可以由coffeejs編譯得到,而且還可以繼續(xù)壓縮瓦阐,甚至可以把全部js文件合并成一個篷牌!html也一樣可以繼續(xù)壓縮。而且枷颊,你完全可以自己創(chuàng)建一個任務(wù)去處理其他諸如圖片、字體等等信卡。

好啦题造,簡易版就講到這里了。

后話:gulp與webpack都是目前比較流行的編譯打包工具界赔,那么它們之間有什么異同點牵触?怎么去進(jìn)行選擇咐低?我們下一節(jié)將介紹如何去用webpack搭建一套開發(fā)工具,從中我們可以感受這兩者的差別绰更,敬請留意锡宋。

本次演示項目的git地址:gulp_base

【下一篇:進(jìn)階:構(gòu)建具備版本管理能力的項目】

(文章有任何謬誤之處,歡迎留言指出)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末徐钠,一起剝皮案震驚了整個濱河市役首,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衡奥,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件失息,死亡現(xiàn)場離奇詭異档址,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绎秒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門尼摹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蠢涝,你說我怎么就攤上這事“鸭” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵场晶,是天一觀的道長怠缸。 經(jīng)常有香客問我,道長揭北,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任恨樟,我火速辦了婚禮疚俱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呆奕。我一直安慰自己,他們只是感情好绳泉,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布姆泻。 她就那樣靜靜地躺著,像睡著了一般蛾娶。 火紅的嫁衣襯著肌膚如雪潜秋。 梳的紋絲不亂的頭發(fā)上胎许,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機(jī)與錄音辜窑,去河邊找鬼。 笑死牙勘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的方面。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼操禀,長吁一口氣:“原來是場噩夢啊……” “哼横腿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耿焊,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤罗侯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歇父,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡护戳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年垂睬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钳枕。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡赏壹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昔瞧,到底是詐尸還是另有隱情,我是刑警寧澤自晰,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布稍坯,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糟把。R本人自食惡果不足惜牲剃,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缠犀。 院中可真熱鬧聪舒,春花似錦、人聲如沸箱残。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盼理。三九已至谈山,卻和暖如春宏怔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸽粉。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工抓艳, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壶硅。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓庐椒,卻偏偏與公主長得像蚂踊,于是被迫代替她去往敵國和親约谈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361

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

  • gulpjs是一個前端構(gòu)建工具泼橘,與gruntjs相比迈勋,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單重归,學(xué)...
    依依玖玥閱讀 3,157評論 7 55
  • gulpjs是一個前端構(gòu)建工具厦凤,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù)较鼓,API也非常簡單,學(xué)...
    井皮皮閱讀 1,305評論 0 10
  • gulpjs是一個前端構(gòu)建工具香椎,與gruntjs相比禽篱,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單谆级,學(xué)...
    小裁縫sun閱讀 932評論 0 3
  • gulpjs是一個前端構(gòu)建工具,與gruntjs相比脚仔,gulpjs無需寫一大堆繁雜的配置參數(shù)舆绎,API也非常簡單,學(xué)...
    build1024閱讀 532評論 0 0
  • 什么是GULP? GULP 是前端開發(fā)過程中對代碼進(jìn)行構(gòu)建的工具吕朵,是自動化項目的構(gòu)建利器;她不僅能 對...
    碧玉含香閱讀 661評論 0 0