第四章:優(yōu)化(深入淺出 Webpack 筆記)

Webpack 啟動(dòng)后會(huì)從配置的 Entry 出發(fā),解析出文件中的導(dǎo)入語句竖席,再遞歸的解析戴质。

縮小文件搜索范圍

  • 優(yōu)化 loader 配置
    為了盡可能少的讓文件被 Loader 處理产舞,可以通過 include 去命中只有哪些文件需要被處理。
  • 優(yōu)化 resolve.modules 配置
    可以指明存放第三方模塊的絕對(duì)路徑终抽,以減少尋找。
  • 優(yōu)化 resolve.mainFields 配置
    用于配置采用哪個(gè)字段作為入口文件的描述桶至。

使用本方法優(yōu)化時(shí)昼伴,需要考慮到所有運(yùn)行時(shí)依賴的第三方模塊的入口文件描述字段,就算有一個(gè)模塊搞錯(cuò)了都可能會(huì)造成構(gòu)建出的代碼無法正常運(yùn)行镣屹。

  • 優(yōu)化 resolve.alias 配置
    通過別名來把原導(dǎo)入路徑映射成一個(gè)新的導(dǎo)入路徑圃郊。
  • 優(yōu)化 resolve.extensions 配置
    在導(dǎo)入語句沒帶文件后綴時(shí),Webpack 會(huì)自動(dòng)帶上后綴后去嘗試詢問文件是否存在女蜈,resolve.extensions 用于配置在嘗試過程中用到的后綴列表持舆。
  • 優(yōu)化 module.noParse 配置
    Webpack 忽略對(duì)部分沒采用模塊化的文件的遞歸解析處理,提高構(gòu)建性能伪窖。

被忽略掉的文件里不應(yīng)該包含 import 逸寓、 require 狐援、 define 等模塊化語句芽腾,不然會(huì)導(dǎo)致構(gòu)建出的代碼中包含無法在瀏覽器環(huán)境下執(zhí)行的模塊化語句。

使用 DllPlugin(webpack4不建議使用)

把網(wǎng)頁依賴的基礎(chǔ)模塊抽離出來礼烈,打包到一個(gè)個(gè)單獨(dú)的動(dòng)態(tài)鏈接庫中去簇宽。一個(gè)動(dòng)態(tài)鏈接庫中可以包含多個(gè)模塊勋篓。
Webpack 已經(jīng)內(nèi)置了對(duì)動(dòng)態(tài)鏈接庫的支持,需要通過2個(gè)內(nèi)置的插件接入晦毙,它們分別是:

  • DllPlugin 插件:用于打包出一個(gè)個(gè)單獨(dú)的動(dòng)態(tài)鏈接庫文件生巡。
  • DllReferencePlugin 插件:用于在主要配置文件中去引入 DllPlugin 插件打包好的動(dòng)態(tài)鏈接庫文件。

使用 HappyPack

運(yùn)行在 Node.js 之上的 Webpack 是單線程模型的见妒,
HappyPack 把任務(wù)分解給多個(gè)子進(jìn)程去并發(fā)的執(zhí)行孤荣,子進(jìn)程處理完后再把結(jié)果發(fā)送給主進(jìn)程,從而讓 Webpack 同一時(shí)刻處理多個(gè)任務(wù)须揣,發(fā)揮多核 CPU 電腦的威力盐股。

由于 JavaScript 是單線程模型,要想發(fā)揮多核 CPU 的能力耻卡,只能通過多進(jìn)程去實(shí)現(xiàn)疯汁,而無法通過多線程實(shí)現(xiàn)。

使用 ParallelUglifyPlugin

當(dāng) Webpack 有多個(gè) JavaScript 文件需要輸出和壓縮時(shí)卵酪,會(huì)使用 UglifyJS 去一個(gè)個(gè)挨著壓縮再輸出幌蚊, 但是 ParallelUglifyPlugin 則會(huì)開啟多個(gè)子進(jìn)程谤碳,把對(duì)多個(gè)文件的壓縮工作分配給多個(gè)子進(jìn)程去完成,每個(gè)子進(jìn)程其實(shí)還是通過 UglifyJS 去壓縮代碼溢豆,但是變成了并行執(zhí)行蜒简。 所以 ParallelUglifyPlugin 能更快的完成對(duì)多個(gè)文件的壓縮工作。

使用自動(dòng)刷新

Webpack 開啟監(jiān)聽模式漩仙,有兩種方式:

  • 在配置文件 webpack.config.js 中設(shè)置 watch: true搓茬。
  • 在執(zhí)行啟動(dòng) Webpack 命令時(shí),帶上 --watch 參數(shù)队他,完整命令是 webpack --watch卷仑。

文件監(jiān)聽工作原理:
定時(shí)獲取文件的最后編輯時(shí)間,并存儲(chǔ)麸折,如果發(fā)現(xiàn)當(dāng)前獲取的和最后一次保存的最后編輯時(shí)間不一致锡凝,就認(rèn)為該文件發(fā)生了變化。 watchOptions.poll 就是用于控制定時(shí)檢查的周期垢啼,具體含義是每隔多少毫秒檢查一次私爷。
當(dāng)發(fā)現(xiàn)某個(gè)文件發(fā)生了變化時(shí),并不會(huì)立刻告訴監(jiān)聽者膊夹,而是先緩存起來衬浑,收集一段時(shí)間的變化后,再一次性告訴監(jiān)聽者放刨。 watchOptions.aggregateTimeout 就是用于配置這個(gè)等待時(shí)間工秩。
默認(rèn)情況下 Webpack 會(huì)從配置的 Entry 文件出發(fā),遞歸解析出 Entry 文件所依賴的文件进统,并都加入到監(jiān)聽列表中去助币。
由于保存文件的路徑和最后編輯時(shí)間需要占用內(nèi)存,定時(shí)檢查周期檢查需要占用 CPU 以及文件 I/O螟碎,所以最好減少需要監(jiān)聽的文件數(shù)量和降低檢查頻率眉菱。

優(yōu)化文件監(jiān)聽性能:ignored: /node_modules/

自動(dòng)刷新瀏覽器:
webpack 模塊負(fù)責(zé)監(jiān)聽文件,webpack-dev-server 模塊則負(fù)責(zé)刷新瀏覽器掉分。 在使用 webpack-dev-server 模塊去啟動(dòng) webpack 模塊時(shí)俭缓,webpack 模塊的監(jiān)聽模式默認(rèn)會(huì)被開啟。 webpack 模塊會(huì)在文件發(fā)生變化時(shí)告訴 webpack-dev-server 模塊酥郭。

自動(dòng)刷新的原理:

  1. 借助瀏覽器擴(kuò)展去通過瀏覽器提供的接口刷新华坦,WebStorm IDE 的 LiveEdit 功能就是這樣實(shí)現(xiàn)的。
  2. 往要開發(fā)的網(wǎng)頁中注入代理客戶端代碼不从,通過代理客戶端去刷新整個(gè)頁面惜姐。
  3. 把要開發(fā)的網(wǎng)頁裝進(jìn)一個(gè) iframe 中,通過刷新 iframe 去看到最新效果椿息。
    DevServer 支持第2歹袁、3種方法坷衍,第2種是 DevServer 默認(rèn)采用的刷新方法。

開啟模塊熱替換

當(dāng)一個(gè)源碼發(fā)生變化時(shí)条舔,只重新編譯發(fā)生變化的模塊惫叛,再用新輸出的模塊替換掉瀏覽器中對(duì)應(yīng)的老模塊。
DevServer 默認(rèn)不會(huì)開啟模塊熱替換模式逞刷,要開啟該模式,只需在啟動(dòng)時(shí)帶上參數(shù) --hot妻熊,完整命令是 webpack-dev-server --hot夸浅。

區(qū)分環(huán)境

當(dāng)你的代碼中出現(xiàn)了使用 process 模塊的語句時(shí),Webpack 就自動(dòng)打包進(jìn) process 模塊的代碼以支持非 Node.js 的運(yùn)行環(huán)境扔役。 這個(gè)注入的 process 模塊作用是為了模擬 Node.js 中的 process帆喇,以支持上面使用的 process.env.NODE_ENV === 'production' 語句。

const DefinePlugin = require('webpack/lib/DefinePlugin');
module.exports = {
  plugins: [
    new DefinePlugin({
      // 定義 NODE_ENV 環(huán)境變量為 production
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
  ],
};

注意在定義環(huán)境變量的值時(shí)用 JSON.stringify 包裹字符串的原因是環(huán)境變量的值需要是一個(gè)由雙引號(hào)包裹的字符串亿胸,而 JSON.stringify('production')的值正好等于'"production"'坯钦。

壓縮代碼

  • 壓縮 JavaScript
    目前最成熟的 JavaScript 代碼壓縮工具是 UglifyJS , 它會(huì)分析 JavaScript 代碼語法樹侈玄,理解代碼含義婉刀,從而能做到諸如去掉無效代碼、去掉日志輸出代碼序仙、縮短變量名等優(yōu)化突颊。
    直接在啟動(dòng) Webpack 時(shí)帶上 --optimize-minimize 參數(shù),即 webpack --optimize-minimize潘悼, 這樣 Webpack 會(huì)自動(dòng)為你注入一個(gè)帶有默認(rèn)配置的 UglifyJSPlugin律秃。

  • 壓縮 ES6
    UglifyJS 只認(rèn)識(shí) ES5 語法的代碼。 為了壓縮 ES6 代碼治唤,需要使用專門針對(duì) ES6 代碼的 UglifyES棒动。

  • 壓縮 CSS
    要開啟 cssnano 去壓縮代碼只需要開啟 css-loaderminimize 選項(xiàng)。

CDN 加速

CDN 又叫內(nèi)容分發(fā)網(wǎng)絡(luò)宾添,通過把資源部署到世界各地船惨,用戶在訪問時(shí)按照就近原則從離用戶最近的服務(wù)器獲取資源,從而加速資源的獲取速度缕陕。
CDN 其實(shí)是通過優(yōu)化物理鏈路層傳輸過程中的網(wǎng)速有限掷漱、丟包等問題來加速網(wǎng)絡(luò)傳輸?shù)摹?br> 過 publicPath 參數(shù)設(shè)置存放靜態(tài)資源的 CDN 目錄 URL, 為了讓不同類型的資源輸出到不同的 CDN榄檬,需要分別在:

  • output.publicPath 中設(shè)置 JavaScript 的地址卜范。
  • css-loader.publicPath 中設(shè)置被 CSS 導(dǎo)入的資源的的地址。
  • WebPlugin.stylePublicPath 中設(shè)置 CSS 文件的地址鹿榜。

使用 Tree Shaking

Tree Shaking 可以用來剔除 JavaScript中用不上的死代碼海雪。它依賴靜態(tài)的 ES6 模塊化語法锦爵。

提取公共代碼

Webpack 內(nèi)置了專門用于提取多個(gè) Chunk 中公共部分的插件 CommonsChunkPlugin

按需加載

使用 Prepack

Prepack 在保持運(yùn)行結(jié)果一致的情況下奥裸,改變?cè)创a的運(yùn)行邏輯险掀,輸出性能更高的 JavaScript 代碼。 實(shí)際上 Prepack 就是一個(gè)部分求值器湾宙,編譯代碼時(shí)提前將計(jì)算結(jié)果放到編譯后的代碼中樟氢,而不是在代碼運(yùn)行時(shí)才去求值,從而優(yōu)化代碼在運(yùn)行時(shí)的效率侠鳄。

Prepack 還處于初期的開發(fā)階段埠啃,局限性也很大。

開啟 Scope Hoisting伟恶,又叫作用域提升

原理:分析出模塊之間的依賴關(guān)系碴开,盡可能的把打散的模塊合并到一個(gè)函數(shù)中去,但前提是不能造成代碼冗余博秫。 因此只有那些被引用了一次的模塊才能被合并潦牛。

輸出分析

接入 webpack-bundle-analyzer

  • npm i -g webpack-bundle-analyzer
  • 啟動(dòng) Webpack 命令: webpack --profile --json > stats.json
  • 在項(xiàng)目根目錄中執(zhí)行 webpack-bundle-analyzer 后,瀏覽器會(huì)打開對(duì)應(yīng)網(wǎng)頁看到分析結(jié)果挡育。

又話總結(jié)

  • 側(cè)重優(yōu)化開發(fā)體驗(yàn)的配置文件 webpack.config.js
const path = require('path');
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const {AutoWebPlugin} = require('web-webpack-plugin');
const HappyPack = require('happypack');

// 自動(dòng)尋找 pages 目錄下的所有目錄巴碗,把每一個(gè)目錄看成一個(gè)單頁應(yīng)用
const autoWebPlugin = new AutoWebPlugin('./src/pages', {
  // HTML 模版文件所在的文件路徑
  template: './template.html',
  // 提取出所有頁面公共的代碼
  commonsChunk: {
    // 提取出公共代碼 Chunk 的名稱
    name: 'common',
  },
});

module.exports = {
  // AutoWebPlugin 會(huì)為尋找到的所有單頁應(yīng)用,生成對(duì)應(yīng)的入口配置即寒,
  // autoWebPlugin.entry 方法可以獲取到生成入口配置
  entry: autoWebPlugin.entry({
    // 這里可以加入你額外需要的 Chunk 入口
    base: './src/base.js',
  }),
  output: {
    filename: '[name].js',
  },
  resolve: {
    // 使用絕對(duì)路徑指明第三方模塊存放的位置良价,以減少搜索步驟
    // 其中 __dirname 表示當(dāng)前工作目錄,也就是項(xiàng)目根目錄
    modules: [path.resolve(__dirname, 'node_modules')],
    // 針對(duì) Npm 中的第三方模塊優(yōu)先采用 jsnext:main 中指向的 ES6 模塊化語法的文件蒿叠,使用 Tree Shaking 優(yōu)化
    // 只采用 main 字段作為入口文件描述字段明垢,以減少搜索步驟
    mainFields: ['jsnext:main', 'main'],
  },
  module: {
    rules: [
      {
        // 如果項(xiàng)目源碼中只有 js 文件就不要寫成 /\.jsx?$/,提升正則表達(dá)式性能
        test: /\.js$/,
        // 使用 HappyPack 加速構(gòu)建
        use: ['happypack/loader?id=babel'],
        // 只對(duì)項(xiàng)目根目錄下的 src 目錄中的文件采用 babel-loader
        include: path.resolve(__dirname, 'src'),
      },
      {
        test: /\.js$/,
        use: ['happypack/loader?id=ui-component'],
        include: path.resolve(__dirname, 'src'),
      },
      {
        // 增加對(duì) CSS 文件的支持
        test: /\.css$/,
        use: ['happypack/loader?id=css'],
      },
    ]
  },
  plugins: [
    autoWebPlugin,
    // 使用 HappyPack 加速構(gòu)建
    new HappyPack({
      id: 'babel',
      // babel-loader 支持緩存轉(zhuǎn)換出的結(jié)果市咽,通過 cacheDirectory 選項(xiàng)開啟
      loaders: ['babel-loader?cacheDirectory'],
    }),
    new HappyPack({
      // UI 組件加載拆分
      id: 'ui-component',
      loaders: [{
        loader: 'ui-component-loader',
        options: {
          lib: 'antd',
          style: 'style/index.css',
          camel2: '-'
        }
      }],
    }),
    new HappyPack({
      id: 'css',
      // 如何處理 .css 文件痊银,用法和 Loader 配置中一樣
      loaders: ['style-loader', 'css-loader'],
    }),
    // 提取公共代碼
    new CommonsChunkPlugin({
      // 從 common 和 base 兩個(gè)現(xiàn)成的 Chunk 中提取公共的部分
      chunks: ['common', 'base'],
      // 把公共的部分放到 base 中
      name: 'base'
    }),
  ],
  watchOptions: {
    // 使用自動(dòng)刷新:不監(jiān)聽的 node_modules 目錄下的文件
    ignored: /node_modules/,
  }
};
  • 側(cè)重優(yōu)化輸出質(zhì)量的配置文件webpack-dist.config.js
const path = require('path');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const {AutoWebPlugin} = require('web-webpack-plugin');
const HappyPack = require('happypack');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');

// 自動(dòng)尋找 pages 目錄下的所有目錄,把每一個(gè)目錄看成一個(gè)單頁應(yīng)用
const autoWebPlugin = new AutoWebPlugin('./src/pages', {
  // HTML 模版文件所在的文件路徑
  template: './template.html',
  // 提取出所有頁面公共的代碼
  commonsChunk: {
    // 提取出公共代碼 Chunk 的名稱
    name: 'common',
  },
  // 指定存放 CSS 文件的 CDN 目錄 URL
  stylePublicPath: '//css.cdn.com/id/',
});

module.exports = {
  // AutoWebPlugin 會(huì)找為尋找到的所有單頁應(yīng)用施绎,生成對(duì)應(yīng)的入口配置溯革,
  // autoWebPlugin.entry 方法可以獲取到生成入口配置
  entry: autoWebPlugin.entry({
    // 這里可以加入你額外需要的 Chunk 入口
    base: './src/base.js',
  }),
  output: {
    // 給輸出的文件名稱加上 Hash 值
    filename: '[name]_[chunkhash:8].js',
    path: path.resolve(__dirname, './dist'),
    // 指定存放 JavaScript 文件的 CDN 目錄 URL
    publicPath: '//js.cdn.com/id/',
  },
  resolve: {
    // 使用絕對(duì)路徑指明第三方模塊存放的位置,以減少搜索步驟
    // 其中 __dirname 表示當(dāng)前工作目錄谷醉,也就是項(xiàng)目根目錄
    modules: [path.resolve(__dirname, 'node_modules')],
    // 只采用 main 字段作為入口文件描述字段致稀,以減少搜索步驟
    mainFields: ['jsnext:main', 'main'],
  },
  module: {
    rules: [
      {
        // 如果項(xiàng)目源碼中只有 js 文件就不要寫成 /\.jsx?$/,提升正則表達(dá)式性能
        test: /\.js$/,
        // 使用 HappyPack 加速構(gòu)建
        use: ['happypack/loader?id=babel'],
        // 只對(duì)項(xiàng)目根目錄下的 src 目錄中的文件采用 babel-loader
        include: path.resolve(__dirname, 'src'),
      },
      {
        test: /\.js$/,
        use: ['happypack/loader?id=ui-component'],
        include: path.resolve(__dirname, 'src'),
      },
      {
        // 增加對(duì) CSS 文件的支持
        test: /\.css$/,
        // 提取出 Chunk 中的 CSS 代碼到單獨(dú)的文件中
        use: ExtractTextPlugin.extract({
          use: ['happypack/loader?id=css'],
          // 指定存放 CSS 中導(dǎo)入的資源(例如圖片)的 CDN 目錄 URL
          publicPath: '//img.cdn.com/id/'
        }),
      },
    ]
  },
  plugins: [
    autoWebPlugin,
    // 開啟ScopeHoisting
    new ModuleConcatenationPlugin(),
    // 使用HappyPack
    new HappyPack({
      // 用唯一的標(biāo)識(shí)符 id 來代表當(dāng)前的 HappyPack 是用來處理一類特定的文件
      id: 'babel',
      // babel-loader 支持緩存轉(zhuǎn)換出的結(jié)果俱尼,通過 cacheDirectory 選項(xiàng)開啟
      loaders: ['babel-loader?cacheDirectory'],
    }),
    new HappyPack({
      // UI 組件加載拆分
      id: 'ui-component',
      loaders: [{
        loader: 'ui-component-loader',
        options: {
          lib: 'antd',
          style: 'style/index.css',
          camel2: '-'
        }
      }],
    }),
    new HappyPack({
      id: 'css',
      // 如何處理 .css 文件抖单,用法和 Loader 配置中一樣
      // 通過 minimize 選項(xiàng)壓縮 CSS 代碼
      loaders: ['css-loader?minimize'],
    }),
    new ExtractTextPlugin({
      // 給輸出的 CSS 文件名稱加上 Hash 值
      filename: `[name]_[contenthash:8].css`,
    }),
    // 提取公共代碼
    new CommonsChunkPlugin({
      // 從 common 和 base 兩個(gè)現(xiàn)成的 Chunk 中提取公共的部分
      chunks: ['common', 'base'],
      // 把公共的部分放到 base 中
      name: 'base'
    }),
    new DefinePlugin({
      // 定義 NODE_ENV 環(huán)境變量為 production 去除 react 代碼中的開發(fā)時(shí)才需要的部分
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    // 使用 ParallelUglifyPlugin 并行壓縮輸出的 JS 代碼
    new ParallelUglifyPlugin({
      // 傳遞給 UglifyJS 的參數(shù)
      uglifyJS: {
        output: {
          // 最緊湊的輸出
          beautify: false,
          // 刪除所有的注釋
          comments: false,
        },
        compress: {
          // 在UglifyJs刪除沒有用到的代碼時(shí)不輸出警告
          warnings: false,
          // 刪除所有的 `console` 語句,可以兼容ie瀏覽器
          drop_console: true,
          // 內(nèi)嵌定義了但是只用到一次的變量
          collapse_vars: true,
          // 提取出出現(xiàn)多次但是沒有定義成變量去引用的靜態(tài)值
          reduce_vars: true,
        }
      },
    }),
  ]
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矛绘,隨后出現(xiàn)的幾起案子耍休,更是在濱河造成了極大的恐慌,老刑警劉巖货矮,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羊精,死亡現(xiàn)場離奇詭異,居然都是意外死亡囚玫,警方通過查閱死者的電腦和手機(jī)喧锦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抓督,“玉大人燃少,你說我怎么就攤上這事”净瑁” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵枪汪,是天一觀的道長涌穆。 經(jīng)常有香客問我,道長雀久,這世上最難降的妖魔是什么宿稀? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮赖捌,結(jié)果婚禮上祝沸,老公的妹妹穿的比我還像新娘。我一直安慰自己越庇,他們只是感情好罩锐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卤唉,像睡著了一般涩惑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桑驱,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天竭恬,我揣著相機(jī)與錄音,去河邊找鬼熬的。 笑死痊硕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的押框。 我是一名探鬼主播岔绸,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了亭螟?” 一聲冷哼從身側(cè)響起挡鞍,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎预烙,沒想到半個(gè)月后墨微,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扁掸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年翘县,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谴分。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锈麸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出牺蹄,到底是詐尸還是另有隱情忘伞,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布沙兰,位于F島的核電站氓奈,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鼎天。R本人自食惡果不足惜舀奶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斋射。 院中可真熱鬧育勺,春花似錦、人聲如沸罗岖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桑包。三九已至化借,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捡多,已是汗流浹背蓖康。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垒手,地道東北人蒜焊。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像科贬,于是被迫代替她去往敵國和親泳梆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鳖悠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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