深入淺出Webpack 摘要 入門

模塊化

模塊化是指把一個復(fù)雜的系統(tǒng)分解到多個模塊以方便編碼决左。

缺點

  • 命名空間沖突,兩個庫可能會使用同一個名稱疗锐,例如 ZeptojQuery都被放在 window.$ 下点待;
  • 無法合理地管理項目的依賴和版本爱榕;
  • 無法方便地控制依賴的加載順序。
CommonJS

CommonJS 是一種使用廣泛的 JavaScript 模塊化規(guī)范花履,核心思想是通過 require 方法來同步地加載依賴的其他模塊芽世,通過 module.exports 導(dǎo)出需要暴露的接口。

優(yōu)點:代碼可復(fù)用于 Node.js 環(huán)境下并運行诡壁,例如做同構(gòu)應(yīng)用济瓢;通過 NPM 發(fā)布的很多第三方模塊都采用了 CommonJS 規(guī)范。
缺點:代碼無法直接運行在瀏覽器環(huán)境下妹卿,必須通過工具轉(zhuǎn)換成標準的 ES5旺矾。

// 導(dǎo)入
const moduleA = require('./moduleA');

// 導(dǎo)出
module.exports = moduleA.someFunc;
ES6 模塊化

它在語言的層面上實現(xiàn)了模塊化。瀏覽器廠商和 Node.js 都宣布要原生支持該規(guī)范夺克。它將逐漸取代 CommonJSAMD 規(guī)范箕宙,成為瀏覽器和服務(wù)器通用的模塊解決方案。

// 導(dǎo)入
import { readFile } from 'fs';
import React from 'react';
// 導(dǎo)出
export function hello() {};
export default {
  // ...
};
樣式文件中的模塊化
// util.scss 文件

// 定義樣式片段
@mixin center {
  // 水平豎直居中
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}

// main.scss 文件

// 導(dǎo)入和使用 util.scss 中定義的樣式片段
@import "util";
#box{
  @include center;
}

常見的構(gòu)建工具及對比

各種可以提高開發(fā)效率的新思想和框架被發(fā)明铺纽。但是這些東西都有一個共同點:源代碼無法直接運行柬帕,必須通過轉(zhuǎn)換后才可以正常運行。

構(gòu)建就是做這件事情狡门,把源代碼轉(zhuǎn)換成發(fā)布到線上的可執(zhí)行 JavaScrip陷寝、CSSHTML 代碼融撞,包括如下內(nèi)容盼铁。

  • 代碼轉(zhuǎn)換:TypeScript 編譯成 JavaScriptSCSS 編譯成 CSS 等尝偎。
  • 文件優(yōu)化:壓縮 JavaScript饶火、CSSHTML代碼致扯,壓縮合并圖片等肤寝。
  • 代碼分割:提取多個頁面的公共代碼、提取首屏不需要執(zhí)行部分的代碼讓其異步加載抖僵。
  • 模塊合并:在采用模塊化的項目里會有很多個模塊和文件鲤看,需要構(gòu)建功能把模塊分類合并成一個文件。
  • 自動刷新:監(jiān)聽本地源代碼的變化耍群,自動重新構(gòu)建义桂、刷新瀏覽器找筝。
  • 代碼校驗:在代碼被提交到倉庫前需要校驗代碼是否符合規(guī)范,以及單元測試是否通過慷吊。
  • 自動發(fā)布:更新完代碼后袖裕,自動構(gòu)建出線上發(fā)布代碼并傳輸給發(fā)布系統(tǒng)。

構(gòu)建其實是工程化溉瓶、自動化思想在前端開發(fā)中的體現(xiàn)急鳄,把一系列流程用代碼去實現(xiàn),讓代碼自動化地執(zhí)行這一系列復(fù)雜的流程堰酿。 構(gòu)建給前端開發(fā)注入了更大的活力疾宏,解放了我們的生產(chǎn)力

Npm Script

Npm Script 是一個任務(wù)執(zhí)行者。Npm 是在安裝 Node.js 時附帶的包管理器触创,Npm Script則是 Npm 內(nèi)置的一個功能坎藐,允許在 package.json文件里面使用 scripts 字段定義任務(wù):

{
  "scripts": {
    "dev": "node dev.js",
    "pub": "node build.js"
  }
}
// 每個屬性對應(yīng)一段 Shell 腳本其底層實現(xiàn)原理是通過調(diào)用 Shell 去運行腳本命令 
// 例如執(zhí)行 npm run pub 命令等同于執(zhí)行命令 node build.js。
Grunt

GruntNpm Script 類似嗅榕,也是一個任務(wù)執(zhí)行者顺饮。Grunt 有大量現(xiàn)成的插件封裝了常見的任務(wù),也能管理任務(wù)之間的依賴關(guān)系凌那,自動化執(zhí)行依賴的任務(wù)兼雄,每個任務(wù)的具體執(zhí)行代碼和依賴關(guān)系寫在配置文件 Gruntfile.js 里。

module.exports = function(grunt) {
  // 所有插件的配置信息
  grunt.initConfig({
    // uglify 插件的配置信息
    uglify: {
      app_task: {
        files: {
          'build/app.min.js': ['lib/index.js', 'lib/test.js']
        }
      }
    },
    // watch 插件的配置信息
    watch: {
      another: {
          files: ['lib/*.js'],
      }
    }
  });

  // 告訴 grunt 我們將使用這些插件
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // 告訴grunt當(dāng)我們在終端中啟動 grunt 時需要執(zhí)行哪些任務(wù)
  grunt.registerTask('dev', ['uglify','watch']);
};
// 在項目根目錄下執(zhí)行命令 grunt dev 就會啟動 JavaScript 文件壓縮和自動刷新功能帽蝶。

優(yōu)點:靈活赦肋,它只負責(zé)執(zhí)行你定義的任務(wù);大量的可復(fù)用插件封裝好了常見的構(gòu)建任務(wù)励稳。
缺點:集成度不高佃乘,要寫很多配置后才可以用,無法做到開箱即用驹尼。

Gulp

Gulp 是一個基于流的自動化構(gòu)建工具趣避。 除了可以管理和執(zhí)行任務(wù),還支持監(jiān)聽文件新翎、讀寫文件程帕。Gulp被設(shè)計得非常簡單,只通過下面5個方法就可以勝任幾乎所有構(gòu)建場景:

  • 通過 gulp.task 注冊一個任務(wù)地啰;
  • 通過 gulp.run 執(zhí)行任務(wù)愁拭;
  • 通過 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');
var uglify = require('gulp-uglify');

// 編譯 SCSS 任務(wù)
gulp.task('sass', function() {
  // 讀取文件通過管道喂給插件
  gulp.src('./scss/*.scss')
    // SCSS 插件把 scss 文件編譯成 CSS 文件
    .pipe(sass())
    // 輸出文件
    .pipe(gulp.dest('./css'));
});

// 合并壓縮 JS
gulp.task('scripts', function() {
  gulp.src('./js/*.js')
    .pipe(concat('all.js'))
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
});

// 監(jiān)聽文件變化
gulp.task('watch', function(){
  // 當(dāng) scss 文件被編輯時執(zhí)行 SCSS 任務(wù)
  gulp.watch('./scss/*.scss', ['sass']);
  gulp.watch('./js/*.js', ['scripts']);    
});

優(yōu)點:好用又不失靈活,既可以單獨完成構(gòu)建也可以和其它工具搭配使用。相對于Grunt惜论,Gulp增加了監(jiān)聽文件许赃、讀寫文件、流式處理的功能来涨。
缺點:集成度不高图焰,要寫很多配置后才可以用启盛,無法做到開箱即用蹦掐。

webpack

Webpack是一個打包模塊化 JavaScript的工具,在 Webpack 里一切文件皆模塊僵闯,通過 Loader 轉(zhuǎn)換文件卧抗,通過 Plugin 注入鉤子,最后輸出由多個模塊組合成的文件鳖粟。Webpack 專注于構(gòu)建模塊化項目社裆。

優(yōu)點:專注于處理模塊化的項目,能做到開箱即用一步到位向图;通過 Plugin 擴展泳秀,完整好用又不失靈活;使用場景不僅限于Web 開發(fā)榄攀;社區(qū)龐大活躍嗜傅,經(jīng)常引入緊跟時代發(fā)展的新特性,能為大多數(shù)場景找到已有的開源擴展檩赢;良好的開發(fā)體驗吕嘀。
缺點:只能用于采用模塊化開發(fā)的項目

Rollup

Rollup 是一個和 Webpack 很類似但專注于 ES6的模塊打包工具。 Rollup 的亮點在于能針對 ES6 源碼進行 Tree Shaking 以去除那些已被定義但沒被使用的代碼贞瞒,以及 Scope Hoisting 以減小輸出文件大小提升運行性能偶房。 然而 Rollup 的這些亮點隨后就被 Webpack 模仿和實現(xiàn)。Rollup 在用于打包 JavaScript 庫時比 Webpack 更加有優(yōu)勢军浆,因為其打包出來的代碼更小更快棕洋。 但功能不夠完善,很多場景都找不到現(xiàn)成的解決方案乒融。

  • Rollup 是在 Webpack 流行后出現(xiàn)的替代品掰盘;
  • Rollup 生態(tài)鏈還不完善,體驗不如 Webpack簇抵;
  • Rollup 功能不如 Webpack完善庆杜,但其配置和使用更加簡單;
  • Rollup 不支持 Code Spliting碟摆,但好處是打包出來的代碼中沒有 Webpack 那段模塊的加載晃财、執(zhí)行和緩存的代碼

安裝與使用

# 安裝最新穩(wěn)定版 -D 安裝到開發(fā)依賴
npm i -D webpack

安裝完后你可以通過這些途徑運行安裝到本項目的 Webpack

  • 在項目根目錄下對應(yīng)的命令行里通過輸入 node_modules/.bin/webpack運行
  • Npm Script 里定義的任務(wù)會優(yōu)先使用本項目下的 Webpack,代碼如下:
"scripts": {
    "start": "webpack --config webpack.config.js"
}

Webpack 在執(zhí)行構(gòu)建時默認會從項目根目錄下的webpack.config.js 文件讀取配置。

const path = require('path');

// 通過 CommonJS 規(guī)范導(dǎo)出一個描述如何構(gòu)建的 Object 對象断盛。 

module.exports = {
  // JavaScript 執(zhí)行入口文件
  entry: './main.js',
  output: {
    // 把所有依賴的模塊合并輸出到一個 bundle.js 文件
    filename: 'bundle.js',
    // 輸出文件都放到 dist 目錄下
    path: path.resolve(__dirname, './dist'),
  }
};

執(zhí)行 webpack 命令運行 Webpack 構(gòu)建罗洗,你會發(fā)現(xiàn)目錄下多出一個 dist 目錄,里面有個 bundle.js 文件钢猛, bundle.js文件是一個可執(zhí)行的 JavaScript文件伙菜,它包含頁面所依賴的模塊及內(nèi)置的 webpackBootstrap 啟動函數(shù)。 這時你用瀏覽器打開 index.html網(wǎng)頁將會看到正常的展示命迈。

Webpack 是一個打包模塊化 JavaScript 的工具贩绕,它會從 main.js 出發(fā),識別出源碼中的模塊化導(dǎo)入語句壶愤, 遞歸的尋找出入口文件的所有依賴淑倾,把入口和其所有依賴打包到一個單獨的文件中。

使用Loader

Webpack 不原生支持解析 如CSS 等文件征椒。要支持非 JavaScript類型的文件娇哆,需要使用 WebpackLoader 機制。

const path = require('path');

module.exports = {
 // JavaScript 執(zhí)行入口文件
 entry: './main.js',
 output: {
   // 把所有依賴的模塊合并輸出到一個 bundle.js 文件
   filename: 'bundle.js',
   // 輸出文件都放到 dist 目錄下
   path: path.resolve(__dirname, './dist'),
 },
 module: {
   rules: [
     {
       // 用正則去匹配要用該 loader 轉(zhuǎn)換的 CSS 文件
       test: /\.css$/,
       use: ['style-loader', 'css-loader?minimize'],
     },
     // 或者
     {
       test: /\.css$/,
       use: [
         'style-loader',
         {
           loader:'css-loader',
           options: {
             minimize: true,
           }
         }
       ],
     }
   ]
 }
};

Loader 可以看作具有文件轉(zhuǎn)換功能的翻譯員勃救,配置里的 module.rules 數(shù)組配置了一組規(guī)則碍讨,告訴 Webpack 在遇到哪些文件時使用哪些 Loader 去加載和轉(zhuǎn)換。 如上配置告訴 Webpack 在遇到以 .css結(jié)尾的文件時先使用 css-loader 讀取 CSS 文件蒙秒,再交給 style-loader 把 CSS 內(nèi)容注入到 JavaScript 里勃黍。 在配置 Loader 時需要注意的是:

  • use 屬性的值需要是一個由Loader 名稱組成的數(shù)組,Loader 的執(zhí)行順序是由后到前的税肪;
  • 每一個 Loader 都可以通過 URL querystring 的方式傳入?yún)?shù)溉躲,例如 css-loader?minimize 中的 minimize 告訴 css-loader 要開啟 CSS 壓縮。

在重新執(zhí)行 Webpack 構(gòu)建前要先安裝新引入的 Loader

npm i -D style-loader css-loader

安裝成功后重新執(zhí)行構(gòu)建時益兄,你會發(fā)現(xiàn) bundle.js 文件被更新了锻梳,里面注入了在 main.css 中寫的 CSS,而不是會額外生成一個 CSS 文件净捅。 但是重新刷新 index.html 網(wǎng)頁時將會發(fā)現(xiàn)樣式生效了疑枯!這其實都是 style-loader 的功勞,它的工作原理大概是把 CSS 內(nèi)容用 JavaScript 里的字符串存儲起來蛔六, 在網(wǎng)頁執(zhí)行 JavaScript 時通過 DOM 操作動態(tài)地往 HTML head標簽里插入 HTML style標簽荆永。 也許你認為這樣做會導(dǎo)致 JavaScript 文件變大并導(dǎo)致加載網(wǎng)頁時間變長,想讓 Webpack 單獨輸出 CSS 文件国章【咴浚可使用 Webpack Plugin 機制來實現(xiàn)。

還可以在源碼中指定用什么 Loader 去處理文件液兽。 以加載 CSS 文件為例骂删,在 main.js 加上以下代碼即可。

require('style-loader!css-loader?minimize!./main.css');
// 指定對 ./main.css 這個文件先采用 css-loader 再采用 style-loader 轉(zhuǎn)換。

使用Plugin

Plugin 是用來擴展 Webpack 功能的宁玫,通過在構(gòu)建流程里注入鉤子實現(xiàn)粗恢,它給 Webpack 帶來了很大的靈活性。

下例展示通過 Plugin 把注入到 bundle.js 文件里的 CSS 提取到單獨的文件中欧瘪。

安裝插件:npm i -D extract-text-webpack-plugin

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  // JavaScript 執(zhí)行入口文件
  entry: './main.js',
  output: {
    // 把所有依賴的模塊合并輸出到一個 bundle.js 文件
    filename: 'bundle.js',
    // 把輸出文件都放到 dist 目錄下
    path: path.resolve(__dirname, './dist'),
  },
  module: {
    rules: [
      {
        // 用正則去匹配要用該 loader 轉(zhuǎn)換的 CSS 文件
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          // 轉(zhuǎn)換 .css 文件需要使用的 Loader
          use: ['css-loader'],
        }),
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      // 從 .js 文件中提取出來的 .css 文件的名稱
      filename: `[name]_[contenthash:8].css`,
    }),
  ]
};

重新構(gòu)建眷射,你會發(fā)現(xiàn) dist 目錄下多出一個 main_1a87a56a.css 文件,bundle.js 里也沒有 CSS 代碼了佛掖,再把該 CSS 文件引入到 index.html 里就完成了妖碉。

從以上代碼可以看出, Webpack 是通過 plugins 屬性來配置需要使用的插件列表的苦囱。 plugins 屬性是一個數(shù)組嗅绸,里面的每一項都是插件的一個實例,在實例化一個組件時可以通過構(gòu)造函數(shù)傳入這個組件支持的配置屬性撕彤。

例如 ExtractTextPlugin 插件的作用是提取出 JavaScript 代碼里的 CSS 到一個單獨的文件。 對此你可以通過插件的 filename屬性猛拴,告訴插件輸出的 CSS 文件名稱是通過 [name]_[contenthash:8].css字符串模版生成的羹铅,里面的 [name] 代表文件名稱, [contenthash:8] 代表根據(jù)文件內(nèi)容算出的8位 hash 值愉昆。

使用 DevServer

前面只是讓 Webpack 正常運行起來了职员,但在實際開發(fā)中你可能會需要:

  • 提供 HTTP 服務(wù)而不是使用本地文件預(yù)覽;
  • 監(jiān)聽文件的變化并自動刷新網(wǎng)頁跛溉,做到實時預(yù)覽焊切;
  • 支持 Source Map,以方便調(diào)試芳室。

Webpack 原生支持上述第2专肪、3點內(nèi)容,再結(jié)合官方提供的開發(fā)工具 DevServer 也可以很方便地做到第1點堪侯。DevServer會啟動一個 HTTP 服務(wù)器用于服務(wù)網(wǎng)頁請求嚎尤,同時會幫助啟動Webpack ,并接收 Webpack 發(fā)出的文件更變信號伍宦,通過 WebSocket 協(xié)議自動刷新網(wǎng)頁做到實時預(yù)覽芽死。

安裝:npm i -D webpack-dev-server

安裝成功后執(zhí)行 webpack-dev-server 命令, DevServer 就啟動了次洼。

DevServer 啟動的 HTTP 服務(wù)器監(jiān)聽在 http://localhost:8080/(端口可以設(shè)置)关贵,DevServer 啟動后會一直駐留在后臺保持運行,訪問這個網(wǎng)址你就能獲取項目根目錄下的 index.html卖毁。 用瀏覽器打開這個地址你會發(fā)現(xiàn)頁面空白錯誤原因是 ./dist/bundle.js 加載404了揖曾。 同時你會發(fā)現(xiàn)并沒有文件輸出到 dist 目錄,原因是 DevServer 會把 Webpack 構(gòu)建出的文件保存在內(nèi)存中,在要訪問輸出的文件時翩肌,必須通過HTTP服務(wù)訪問模暗。 由于 DevServer 不會理會 webpack.config.js 里配置的 output.path 屬性,所以要獲取 bundle.js 的正確 URLhttp://localhost:8080/bundle.js

所以在 index.html 中這樣引入 <script src="bundle.js"></script> 而不是引入預(yù)料中打包后的dist文件下的bundle.js

實時預(yù)覽

Webpack 在啟動時可以開啟監(jiān)聽模式念祭,開啟監(jiān)聽模式后 Webpack 會監(jiān)聽本地文件系統(tǒng)的變化兑宇,發(fā)生變化時重新構(gòu)建出新的結(jié)果。Webpack 默認是關(guān)閉監(jiān)聽模式的粱坤,你可以在啟動 Webpack 時通過 webpack --watch 來開啟監(jiān)聽模式隶糕。

通過 DevServer 啟動的 Webpack 會開啟監(jiān)聽模式,當(dāng)發(fā)生變化時重新執(zhí)行完構(gòu)建后通知 DevServer站玄。 DevServerWebpack在構(gòu)建出的 JavaScript 代碼里注入一個代理客戶端用于控制網(wǎng)頁枚驻,網(wǎng)頁和 DevServer 之間通過 WebSocket 協(xié)議通信, 以方便 DevServer主動向客戶端發(fā)送命令株旷。 DevServer 在收到來自 Webpack文件變化通知時通過注入的客戶端控制網(wǎng)頁刷新再登。

如果嘗試修改 index.html 文件并保存,你會發(fā)現(xiàn)這并不會觸發(fā)以上機制晾剖,導(dǎo)致這個問題的原因是 Webpack 在啟動時會以配置里的 entry 為入口去遞歸解析出 entry 所依賴的文件锉矢,只有 entry 本身和依賴的文件才會被 Webpack 添加到監(jiān)聽列表里。 而 index.html 文件是脫離了JavaScript 模塊化系統(tǒng)的齿尽,所以 Webpack 不知道它的存在沽损。

模塊熱替換

除了通過重新刷新整個網(wǎng)頁來實現(xiàn)實時預(yù)覽,DevServer 還有一種被稱作模塊熱替換的刷新技術(shù)循头。 模塊熱替換能做到在不重新加載整個網(wǎng)頁的情況下绵估,通過將被更新過的模塊替換老的模塊,再重新執(zhí)行一次來實現(xiàn)實時預(yù)覽卡骂。 模塊熱替換相對于默認的刷新機制能提供更快的響應(yīng)和更好的開發(fā)體驗国裳。 模塊熱替換默認是關(guān)閉的,要開啟模塊熱替換偿警,你只需在啟動 DevServer 時帶上 --hot參數(shù)躏救。

支持 Source Map

在瀏覽器中運行的 JavaScript 代碼都是編譯器輸出的代碼,你可能需要通過斷點調(diào)試去找出問題螟蒸。 在編譯器輸出的代碼上進行斷點調(diào)試是一件辛苦和不優(yōu)雅的事情盒使, 調(diào)試工具可以通過 Source Map 映射代碼,讓你在源代碼上斷點調(diào)試七嫌。 Webpack 支持生成 Source Map少办,只需在啟動時帶上 --devtool source-map 參數(shù)。

核心概念

  • Entry:入口诵原,Webpack 執(zhí)行構(gòu)建的第一步將從 Entry 開始英妓,可抽象成輸入挽放。
  • Module:模塊,在 Webpack 里一切皆模塊蔓纠,一個模塊對應(yīng)著一個文件辑畦。Webpack 會從配置的 Entry開始遞歸找出所有依賴的模塊。
  • Chunk:代碼塊腿倚,一個 Chunk 由多個模塊組合而成纯出,用于代碼合并與分割。
  • Loader:模塊轉(zhuǎn)換器敷燎,用于把模塊原內(nèi)容按照需求轉(zhuǎn)換成新內(nèi)容暂筝。
  • Plugin:擴展插件,在 Webpack 構(gòu)建流程中的特定時機注入擴展邏輯來改變構(gòu)建結(jié)果或做你想要的事情硬贯。
  • Output:輸出結(jié)果焕襟,在 Webpack 經(jīng)過一系列處理并得出最終想要的代碼后輸出結(jié)果。

Webpack 啟動后會從 Entry 里配置的 Module 開始遞歸解析 Entry 依賴的所有 Module饭豹。 每找到一個 Module鸵赖, 就會根據(jù)配置的 Loader 去找出對應(yīng)的轉(zhuǎn)換規(guī)則,對 Module 進行轉(zhuǎn)換后墨状,再解析出當(dāng)前 Module 依賴的 Module卫漫。 這些模塊會以 Entry 為單位進行分組,一個 Entry 和其所有依賴的 Module 被分到一個組也就是一個 Chunk肾砂。最后 Webpack 會把所有 Chunk 轉(zhuǎn)換成文件輸出。 在整個流程中 Webpack 會在恰當(dāng)?shù)臅r機執(zhí)行 Plugin 里定義的邏輯宏悦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末镐确,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饼煞,更是在濱河造成了極大的恐慌源葫,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砖瞧,死亡現(xiàn)場離奇詭異息堂,居然都是意外死亡,警方通過查閱死者的電腦和手機块促,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門荣堰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竭翠,你說我怎么就攤上這事振坚。” “怎么了斋扰?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵渡八,是天一觀的道長啃洋。 經(jīng)常有香客問我,道長屎鳍,這世上最難降的妖魔是什么宏娄? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮逮壁,結(jié)果婚禮上孵坚,老公的妹妹穿的比我還像新娘。我一直安慰自己貌踏,他們只是感情好十饥,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祖乳,像睡著了一般逗堵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眷昆,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天蜒秤,我揣著相機與錄音,去河邊找鬼亚斋。 笑死作媚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的帅刊。 我是一名探鬼主播纸泡,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赖瞒!你這毒婦竟也來了女揭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤栏饮,失蹤者是張志新(化名)和其女友劉穎吧兔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袍嬉,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡境蔼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了伺通。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箍土。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泵殴,靈堂內(nèi)的尸體忽然破棺而出涮帘,到底是詐尸還是另有隱情,我是刑警寧澤笑诅,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布调缨,位于F島的核電站疮鲫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弦叶。R本人自食惡果不足惜俊犯,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伤哺。 院中可真熱鬧燕侠,春花似錦、人聲如沸立莉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜓耻。三九已至茫舶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刹淌,已是汗流浹背饶氏。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留有勾,地道東北人疹启。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像蔼卡,于是被迫代替她去往敵國和親喊崖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361