前端構(gòu)建工具簡介

1.什么是構(gòu)建工具

比如我們執(zhí)行一些例如CoffeeScript/ES6去代替JavascriptJSCSS壓縮雏亚、用Less去寫CSS缨硝、用Jade去寫HTML、用Browserify去模塊化评凝、為非覆蓋式部署的資源加MD5戳等追葡,這些操作如果我們一遍遍手動執(zhí)行,非常耗費時間和精力奕短,所以前端構(gòu)建工具宜肉,或者較前端自動化構(gòu)建工具,就是用來讓我們不再做機械重復的事情翎碑,解放我們的雙手的谬返。

  • 以gulp為例,編寫gulpfile.js

例如:

gulp = require('gulp')
coffee = require('gulp-coffee')
uglify = require('gulp-uglify')
rename = require('gulp-rename')

file = './src/js/a.coffee'

gulp.task('coffe',function(){
  gulp.src(file)
      .pipe(coffee())   //編譯
      .pipe(uglify())    //壓縮
      .pipe(rename({
        extname:".min.js"    //重命名
      }))
  .pipe(gulp.dest('./build/js'))
})

gulp.task('watch',function(
  gulp.watch(file,['coffee'])
))
gulp.task('default',['coffee'])

  • 這樣日杈,我只要執(zhí)行一下gulp watch遣铝,它就可以自動監(jiān)視a.coffee的變化佑刷,每次修改a.coffee并保存后,它就會自動執(zhí)行編譯->壓縮丑化->重命名這一系列動作了酿炸。

2.構(gòu)建工具的發(fā)展

構(gòu)建其實是工程化瘫絮、自動化思想在前端開發(fā)中的體現(xiàn),將一系列流程用代碼去實現(xiàn)填硕,讓代碼自動化地執(zhí)行這一系列復雜的流程麦萤。

構(gòu)建可以實現(xiàn)如下內(nèi)容:

  • 代碼轉(zhuǎn)換: 將 TypeScript/es6 編譯成JavaScript、將 SCSS 編譯成 CSS等扁眯。
  • 文件優(yōu)化: 壓縮JavaScript壮莹、CSS、HTML 代碼姻檀,壓縮合并圖片等命满。
  • 代碼分割: 提取多個頁面的公共代碼,提取首屏不需要執(zhí)行部分代碼讓其異步記在绣版。
  • 模塊合并: 在采用模塊化的項目里會有很多個模塊和文件胶台,需要通過構(gòu)建功能將模塊分類合并成一個文件。
  • 自動刷新: 監(jiān)聽本地源代碼變化僵娃,自動重新構(gòu)建概作、刷新瀏覽器腋妙。
  • 代碼校驗: 在代碼被提交到倉庫前需要校驗代碼是否符合規(guī)范默怨,以及單元測試是否通過。
  • 自動發(fā)布: 更新代碼后骤素,自動構(gòu)建出線上發(fā)布代碼并傳輸給發(fā)布系統(tǒng)匙睹。

構(gòu)建工具發(fā)展:Npm Scripts、Grunt济竹、Gulp痕檬、FIS 3、Webpack送浊、Rollup梦谜、Parcel

Grunt:

Grunt is the older project. It relies on plugin specific configuration. This is fine up to a point but believe me, you don't want to end up having to maintain a 300 line Gruntfile. The approach simply turns against itself at some point. Just in case youare curious what the configuration looks like, here's an examplefrom Grunt documentation:

Grunt是相比后面幾個更早的項目,他依賴于各種插件的配置袭景。這是一個很好的解決方案唁桩,但是請相信我,你不會想看到一個 300 行的 Gruntfile耸棒。如果你好奇 Grunt 的配置會如何荒澡,那么這里是有個從 Grunt 文檔 的例子

module.exports = function(grunt){
  grunt.initCongfig({
    jshint:{
      files:['Gruntgile.js','src/**/*.js','test/**/*.js'],
      options:{
        globals:{
          jQuery:true
        }  
      }
    },
    watch:{
      files:['<%=jshint.files%>'],
      tasks:['jshint']
    }
  });
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.registerTask('defaule',['jshint']);
}

Grunt 的優(yōu)點是:

  • 靈活,它只負責執(zhí)行我們定義好的任務与殃;
  • 大量可復用插件封裝好了常見的構(gòu)建任務单山。

Grunt 的缺點是:
集成度不高碍现,要寫很多配置后才可以用,無法做到開箱即用米奸。

Grunt 相當于進化版的 Npm scripts昼接,它的誕生其實是為了彌補 Npm Scripts 的不足。

Gulp:

Gulp takes a different approach. Instead of relying on configuration per plugin you deal with actual code. Gulp builds on top of the tried and true concept of piping. If you are familiar with Unix, it's the same here. You simply have sources, filters and sinks. In this case sources happen to match to some files, filters perform some operations on those (ie. convert to JavaScript) and then output to sinks (your build directory etc.). Here's a sample Gulpfileto give you a better idea of theapproach taken from the project README and abbreviated a bit:

Gulp 提供了一個不一樣的解決方案悴晰,而不是依賴于各種插件的配置辩棒。Gulp 使用了一個文件流的概念。如果你熟悉 Unix膨疏,那么 Gulp 對你來說會差不多一睁,Gulp 會提供你一些簡單化的操作。在這個解決方案中佃却,是去匹配一些文件然后操作(就是說和JavaScript 相反)然后輸出結(jié)果(比如輸出在你設置的編譯路徑等)者吁。這里有一個簡單的 Gulpfile 的例子:

var gulp = require('gulp');
var coffee= require('gulp-coffee');
var concat= require('gulp-concat');
var uglify= require('gulp-uglify');
var sourcemaps= require('gulp-sourcemaps');
var del= require('del');
var paths= {
  script:[
    'client/js/**/*.coffee',
    '!client/external/**/*.coffee',
  ],
};
// 不是左右的任務需要使用streams
// 一個gulpfile,只是另一個node的程序饲帅,所以你可以使用所有npm的包
gulp.task('clean',function(cb){
  // 你可以用`gulp.src`來使用多重通配符模式
  del(['build'],cb);
});
gulp.task('scripts',['clean'],function(){
  // 壓縮和復制所有JavaScript(除了第三方庫)
  // 加上sourcemaps
  return gulp.src(paths.scripts)
    .pipe(sourcemaps.init())
      .pipe(coffee())
      .pipe(uglify())
      .pipe(concat('build/js'))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('build/js'));
});
// 監(jiān)聽文件修改
gulp.task('watch',function(){
  gulp.watch(paths.scripts,['scripts'])
})
// 默認任務(就是你在命令行輸入`gulp`時運行)
gulp.task('default',['watch','scripts']);

Given the configuration is code you canalways just hack it if you run into troubles. You can wrap existing Node.jsmodules as Gulp plugins and so on. You still end up writing a lot ofboilerplate for casual tasks, though.

這些配置都是代碼复凳,所以當你遇到問題也可以修改,你也可以使用已經(jīng)存在的 Gulp 插件灶泵,但是你還是需要寫一堆模板任務育八。

Gulp 是一個基于流的自動化構(gòu)建工具。除了可以管理任務和執(zhí)行任務赦邻,還支持監(jiān)聽文件髓棋、讀寫文件。Gulp 被設計的非常簡單惶洲,只通過下面5個方法就可以支持幾乎所有構(gòu)建場景:

  • 通過 gulp.task 注冊一個任務按声;
  • 通過 gulp.run 執(zhí)行任務;
  • 通過 gulp.watch 監(jiān)聽文件變化恬吕;
  • 通過 gulp.src 讀取文件签则;
  • 通過 gulp.dest 寫完文件。
// 引入 Gulp
var gulp = require("gulp");
// 引入插件
var jshint = require("gulp-jshint");
var sass = require("gulp-sass");
var concat = require("gulp-concat");
....
// 便宜SCSS任務
gulp.task('scss', function() {
  // 讀取文件铐料,通過管道喂給插件
  gulp.src('./scss/*.scss')
  // SCSS 插件將 scss 文件編譯成 css
      .pipe(sass())
      // 輸出文件
      .pipe(guilp.dest('./css'));
});
// 合并壓縮 JavaScript 文件
gulp.task('scripts', function() {
  gulp.src('./js/*.js')
      .pipe(concat('all.js'))
      .pipe(uglify())
      .pipe(gulp.dest('./dest'));
});
// 監(jiān)聽文件變化
gulp.task('watch', function() {
  // 當 SCSS 文件被編輯時執(zhí)行 SCSS 任務
  gulp.watch('./scss/*.scss', ['sass']);
  gulp.watch('./js/*.js', ['scripts']);
});

Gulp 的優(yōu)點:
好用又不失靈活渐裂,既可以單獨完成構(gòu)建,也可以和其他工具搭配使用钠惩。

缺點:
和Grunt 類似柒凉。集成度不高,要寫很多配置后才可以用妻柒,無法做到開箱即用扛拨。

可以將Gulp 看做是 Grunt 的加強版。相對于 Grunt 举塔,Gulp 增加了文件監(jiān)聽绑警、讀寫文件求泰、流式處理的功能。

FIS 3:

Fis3是一個來自百度的優(yōu)秀國產(chǎn)構(gòu)建工具计盒。相對于 Grunt渴频、Gulp 這些只提供了基本功能的工具。Fis3集成了開發(fā)者常用的構(gòu)建功能北启,如下所述卜朗。

  • 讀寫文件:通過 fis.match 讀文件,release 配置文件輸出路徑咕村。
  • 資源定位:解析文件之間的依賴關系和文件位置场钉。
  • 文件指紋:在通過 useHash 配置輸出文件時為文件 URL加上 md5 戳,來優(yōu)化瀏覽器的緩存懈涛。
  • 文件編譯:通過 parser 配置文件解析器做文件轉(zhuǎn)換逛万,例如將 ES6 編譯成 ES5。
  • 壓縮資源:通過 optimizer 配置代碼壓縮方法批钠。
  • 圖片合并:通過 spriter 配置合并 CSS 里導入的圖片到一個文件中宇植,來減少 HTTP 請求數(shù)。

大致使用如下:

// 加 md5
fis.match('*.{js,css,png}', {
  useHash: true
});
// 通過fis3-parse-typescript插件可將 TypeScript 文件轉(zhuǎn)換成 JavaScript 文件
fis.match('*.ts', {
  parser: fis.plugin('typescript')
});
// 對CSS進行雪碧圖合并
fis.match('*.css', {
  // 為匹配到的文件分配屬性 useSprite
  useSprite: true
});
// 壓縮 JavaScript
fis.match('*.js', {
  optimizer: fis.plugin('uglify-js')
});
// 壓縮CSS
fis.match('*.css', {
  optimizer: fis.plugin('clean-css')
});
// 壓縮圖片
fis.match('*.png', {
  optimizer: fis.plugin('png-compressor')
});

可以看出 Fis3 很強大埋心,內(nèi)置了許多功能指郁,無需做太多配置就能完成大量工作。

Fis3的優(yōu)點:
集成了各種Web老發(fā)所需的構(gòu)建功能拷呆,配置簡單闲坎,開箱即用。其缺點是目前官方已經(jīng)不再更新和維護洋腮,不支持最新版本的Node箫柳。

browserify

Dealing with JavaScript modules has alwaysbeen a bit of a problem given the language actually doesn't have a concept ofmodule till ES6\. Ergo we are stuck with the 90s when it comes to browserenvironment. Various solutions, including AMD, have been proposed. Inpractice it can be useful just to use CommonJS, the Node.js format, and lettooling deal with the rest. The advantage is that you can often hook into NPMand avoid reinventing the wheel.

處理 JavaScript 模塊一直是一個大問題,因為這個語言在ES6 之前沒有這方面的概念啥供。因此我們還是停留在90年代,各種解決方案库糠,比如提出了 AMD伙狐。在實踐中只使用 CommonJSNode.js 所采用的格式)會比較有幫助,而讓工具去處理剩下的事情瞬欧。它的優(yōu)勢是你可以發(fā)布到 NPM 上來避免重新發(fā)明輪子贷屎。

Browserify solves this problem. Itprovides a way to bundle CommonJS modules together. You can hook it up withGulp. In addition there are tons of smaller transformation tools that allow youto move beyond the basic usage (ie. watchify provides a file watcherthat creates bundles for you during development automatically). This will savesome effort and no doubt is a good solution up to a point.

Browserify 解決了這個問題,它提供了一種可以把模塊集合到一起的方式艘虎。你可以用 Gulp 調(diào)用它唉侄,此外有很多轉(zhuǎn)換小工具可以讓你更兼容的使用(比如 watchify 提供了一個文件監(jiān)視器幫助你在開發(fā)過程中更加自動化地把文件合并起來),這樣會省下很多精力野建。毋庸置疑属划,一定程度來講恬叹,這是一個很好的解決方案。

  • 服務器端NodeJS自帶模塊功能同眯,可以使用require和module.exports構(gòu)建項目
  • 隨著項目的增大绽昼,瀏覽器端任務越來越重,依賴關系越來越復雜须蜗,需要使用工具實現(xiàn)模塊化硅确。
  • Browserify通過require和module.exports來導入和導出。
  • Browserify的原理:部署時處理代碼依賴明肮,將模塊打包為一個文件菱农。

Webpack:

Webpack expands on the idea of hooking into CommonJS require. What if you could just requirewhatever you needed in your code, be it CoffeeScript, Sass, Markdown orsomething? Well, Webpack does just this. It takes your dependencies, puts themthrough loaders and outputs browser compatible static assets. All of this isbased on configuration. Here is a sample configuration from the officialWebpack tutorial:

Webpack 擴展了 CommonJsrequire 的想法,比如你想在 CoffeeScript柿估、Sass大莫、Markdown 或者其他什么代碼中 require 你想要的任何代碼的話?那么 Webpack 正是做這方面的工作官份。它會通過配置來取出代碼中的依賴只厘,然后把他們通過加載器把代碼兼容地輸出到靜態(tài)資源中。這里是一個 Webpack 官網(wǎng) 上的例子:

module.exports = {
  entry:'./entry.js',
  output:{
    path:_dirname,
    filename:'bundle.js'
  },
  module:{
    loaders:[
      {test:/\.css$/,loader:'style!css'}
    ]
  }
}

Webpack 是一個打包模塊化的JavaScript的工具舅巷,在Webpack里一切文件皆模塊羔味,通過 loader 轉(zhuǎn)換文件,通過Plugin注入鉤子钠右,最后輸出由多個模塊組合成的文件赋元。Webpack 專注于構(gòu)建模塊化項目。

其官網(wǎng)的首頁圖很形象的展示了 Webpack 的定義飒房,如下圖:

一切文件搁凸,如JavaScript、CSS狠毯、SCSS护糖、圖片、模板嚼松,對于Webpack 來說都是一個個模塊嫡良,這樣的好處是能清晰地描繪各個模塊之間的依賴關系,以方便Webpack進行組合和打包献酗,經(jīng)過Webpack的處理寝受,最終會輸出瀏覽器能使用的靜態(tài)資源。

Webpack具有很大的靈活性罕偎,能配置處理文件的方式很澄,使用方法大致如下:

module.exports = {
  // 所有模塊的入口,webpack從入口開始遞歸解析出所有依賴的模塊
  entry: './app.js',
  output: {
    // 將入口所依賴的所有模塊打包成一個文件 bundle.js 輸出
    filename: 'bundle.js'
  }
}

Webpack的優(yōu)點是:

  • 專注于處理模塊化的項目,能做到開箱即用甩苛、一步到位蹂楣;
  • 可通過 Plugin 擴展,完整好用又不失靈活性浪藻;
  • 使用場景不局限于Web開發(fā)捐迫;
  • 社區(qū)龐大活躍,經(jīng)常引入緊跟時代發(fā)展的新特性爱葵,能為大多數(shù)場景找到已有的開源擴展施戴;
  • 良好的開發(fā)體驗;

Webpack的缺點是:
只能用于采用模塊化開發(fā)的項目萌丈。

Rollup:

Rollup 是一個和 Webpack 很類似但專注于ES6的模塊打包工具赞哗。它的亮點在于,針對ES6源碼進行 Tree Shaking,以去除那些已經(jīng)被定義但沒被使用的代碼并進行Scope Hoisting辆雾,以減少輸出文件的大小和提升運行性能肪笋。然而 Rollup 的這些亮點隨后就被Webpack模仿和實現(xiàn)了。

Parcel:

Parcel 是 最近新起的Web 應用打包工具度迂,適用于經(jīng)驗不同的開發(fā)者藤乙。它利用多核處理提供了極快的速度,并且不需要任何配置惭墓。

Parcel的優(yōu)點:

  • 極速打包坛梁。Parcel 使用 worker 進程去啟用多核編譯。同時有文件系統(tǒng)緩存腊凶,即使在重啟構(gòu)建后也能快速再編譯划咐。
  • 開箱即用。對 JS, CSS, HTML, 文件 及更多的支持钧萍,而且不需要插件褐缠。
  • 自動轉(zhuǎn)換。如若有需要风瘦,Babel, PostCSS, 和PostHTML甚至 node_modules 包會被用于自動轉(zhuǎn)換代碼队魏。
  • 熱模塊替換。Parcel 無需配置弛秋,在開發(fā)環(huán)境的時候會自動在瀏覽器內(nèi)隨著你的代碼更改而去更新模塊器躏。
  • 友好的錯誤日志。當遇到錯誤時蟹略,Parcel 會輸出 語法高亮的代碼片段,幫助你定位問題遏佣。

缺點:

  • 不支持SourceMap:在開發(fā)模式下挖炬,Parcel也不會輸出SourceMap,目前只能去調(diào)試可讀性極低的代碼状婶;
  • 不支持剔除無效代碼(TreeShaking):很多時候我們只用到了庫中的一個函數(shù)意敛,結(jié)果Parcel把整個庫都打包了進來馅巷;
  • 一些依賴會讓Parcel出錯:當你的項目依賴了一些Npm上的模塊時,有些Npm模塊會讓Parcel運行錯誤草姻;
  • Parcel需要為零配置付出代價钓猬。零配置其實是把各種常見的場景做為默認值來實現(xiàn)的,

這雖然能節(jié)省很多工作量撩独,快速上手敞曹,但這同時會帶來一些問題:

  • 不守規(guī)矩的node_module:有些依賴的庫在發(fā)布到Npm上時可能不小心把.babelrcpostcss.config.js tsconfig.json這些配置文件也一起發(fā)布上去了,
  • 不靈活的配置:零配置的Parcel關閉了很多配置項综膀,在一些需要的配置的場景下無法改變澳迫。

Parcel使用場景受限。目前Parcel只能用來構(gòu)建用于運行在瀏覽器中的網(wǎng)頁剧劝,這也是他的出發(fā)點和專注點橄登。在軟件行業(yè)不可能存在即使用簡單又可以適應各種場景的方案,就算所謂的人工智能也許能解決這個問題讥此,但人工智能不能保證100%的正確性拢锹。

反觀Webpack除了用于構(gòu)建網(wǎng)頁,還可以做:

  • 打包發(fā)布到Npm上的庫
  • 構(gòu)建Node.js應用(同構(gòu)應用)
  • 構(gòu)建Electron應用
  • 構(gòu)建離線應用(ServiceWorkers)

3.為什么選擇Webpack

上面介紹的構(gòu)建工具是按照他們的誕生時間排序的萄喳,他們是時代的產(chǎn)物卒稳,側(cè)面反映出 Web 開發(fā)的發(fā)展趨勢

如下所述:

  • 在 Npm Scripts 和 Grunt 時代,Web 開發(fā)要做的事情變多取胎,流程復雜展哭,自動化思想被引入,用于簡化流程闻蛀;
  • 在 Gulp 時代匪傍,開始出現(xiàn)一些新語言用于提高開發(fā)效率,流程處理思想的出現(xiàn)是為了簡化文件轉(zhuǎn)換的流程觉痛,例如將ES6轉(zhuǎn)換為ES5役衡;
  • 在Webpack時代,由于單頁應用的流行薪棒,網(wǎng)頁的功能和實現(xiàn)代碼變的復雜手蝎、龐大,Web開發(fā)向模塊化改進俐芯。

這些構(gòu)建工具都有各自的定位和專注點棵介,它們之間既可以單獨完成任務,也可以互相搭配起來彌補各自的不足吧史。在了解這些常見的構(gòu)建工具后邮辽,我們需要根據(jù)自己的需求去判斷應該如何進行選擇和搭配它們才能更好的滿足自己的需求。

經(jīng)過多年的額發(fā)展,Webpack 已經(jīng)成為構(gòu)建工具中的首選吨述,這是因為:

  • 大多數(shù)團隊在開發(fā)新項目時會采用緊跟時代的技術岩睁,這些技術幾乎都會采用“模塊化+新語言+新框架”,Webpack可以為這些新項目提供一站式的解決方案揣云;
  • Webpack有良好的生態(tài)和維護團隊捕儒,能提供良好的開發(fā)體驗并保證質(zhì)量;
  • Webpack 被全世界大量的Web開發(fā)者使用和驗證邓夕,能找到各個層面所需要的教程和經(jīng)驗分享刘莹。

4.Gulp和Webpack的區(qū)別

常有人拿gulpwebpack來比較,知道這兩個構(gòu)建工具功能上有重疊的地方翎迁,可單用栋猖,也可一起用,但本質(zhì)的區(qū)別就沒有那么清晰汪榔。

Gulp強調(diào)的是前端開發(fā)的工作流程蒲拉,我們可以通過配置一系列的task,定義task處理的事務(例如文件壓縮合并痴腌、雪碧圖雌团、啟動server、版本控制等)士聪,然后定義執(zhí)行順序锦援,來讓gulp執(zhí)行這些task,從而構(gòu)建項目的整個前端開發(fā)流程剥悟。 簡單說就一個Task Runner灵寺,就是用來跑一個一個任務的。

Gulp沒發(fā)解決的是 js module 的問題区岗,是你寫代碼時候如何組織代碼結(jié)構(gòu)的問題略板。

Webpack是一個前端模塊化方案,更側(cè)重模塊打包慈缔,我們可以把開發(fā)中的所有資源(圖片叮称、js文件、css文件等)都看成模塊藐鹤,通過loader(加載器)和plugins(插件)對資源進行處理瓤檐,打包成符合生產(chǎn)環(huán)境部署的前端資源。

  • 相同點: 文件合并與壓縮(css,js)娱节,sass/less預編譯挠蛉,啟動server,版本控制肄满。

  • 不同點: 雖然都是前端自動化構(gòu)建工具碌秸,但看他們的定位就知道不是對等的绍移。

  • gulp嚴格上講悄窃,模塊化不是他強調(diào)的東西讥电,他旨在規(guī)范前端開發(fā)流程。

  • webpack更是明顯強調(diào)模塊化開發(fā)轧抗,而那些文件壓縮合并恩敌、預處理等功能,不過是他附帶的功能横媚。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纠炮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子灯蝴,更是在濱河造成了極大的恐慌恢口,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穷躁,死亡現(xiàn)場離奇詭異耕肩,居然都是意外死亡,警方通過查閱死者的電腦和手機问潭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門猿诸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狡忙,你說我怎么就攤上這事梳虽。” “怎么了灾茁?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵窜觉,是天一觀的道長。 經(jīng)常有香客問我北专,道長禀挫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任逗余,我火速辦了婚禮特咆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘录粱。我一直安慰自己腻格,他們只是感情好,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布啥繁。 她就那樣靜靜地躺著菜职,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旗闽。 梳的紋絲不亂的頭發(fā)上酬核,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天蜜另,我揣著相機與錄音,去河邊找鬼嫡意。 笑死举瑰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蔬螟。 我是一名探鬼主播此迅,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旧巾!你這毒婦竟也來了耸序?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤鲁猩,失蹤者是張志新(化名)和其女友劉穎坎怪,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廓握,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡搅窿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了疾棵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戈钢。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖是尔,靈堂內(nèi)的尸體忽然破棺而出殉了,到底是詐尸還是另有隱情,我是刑警寧澤拟枚,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布薪铜,位于F島的核電站,受9級特大地震影響恩溅,放射性物質(zhì)發(fā)生泄漏隔箍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一脚乡、第九天 我趴在偏房一處隱蔽的房頂上張望蜒滩。 院中可真熱鬧,春花似錦奶稠、人聲如沸俯艰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竹握。三九已至,卻和暖如春辆飘,著一層夾襖步出監(jiān)牢的瞬間啦辐,已是汗流浹背谓传。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芹关,地道東北人续挟。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像充边,于是被迫代替她去往敵國和親庸推。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

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