webpack

一.webpack的一些理解

1.什么是webpack

webpack是一款模塊加載器兼打包工具,它把各種資源,例如js(含jsx)、coffee哟绊、樣式(含less/sass)、圖片等作為模塊來使用和處理痰憎,它的目的就是把有依賴關(guān)系的各種文件打包成一系列的靜態(tài)資源

2.webpack的優(yōu)勢

  • webpack是以commonJs的形式來書寫腳本的票髓,但對AMD/CMD的支持也很全面
  • 支持很多模塊加載器的調(diào)用,可以使模塊加載器靈活定制铣耘,比如babel-loader加載器洽沟,該加載器能使我們使用es6的語法來編寫代碼;less-loader加載器蜗细,可以將less編譯成css文件
  • 開發(fā)便捷裆操,能替代部分grunt/gulp的工作,比如打包炉媒、壓縮混淆踪区、圖片轉(zhuǎn)base64等
  • 可以通過配置打包成多個文件,有效的利用瀏覽器的緩存功能提升性能

3.webpack與其他類似工具有哪些不同

  • 有同步和異步兩種不同的加載方式
  • loader吊骤,加載器可以將其他資源整合到j(luò)s文件中缎岗,通過這種方式,將所有源文件形成一個模塊
  • 優(yōu)秀的語法分析能力白粉,支持CommonJs AMD規(guī)范
  • 有豐富的開源插件庫传泊,可以根據(jù)自己的需求定制webpack的配置

4.webpack的打包流程

4-1.讀取webpack的配置參數(shù)
4-2.啟動webpack鼠渺,創(chuàng)建Compiler對象并開始解析項目
4-3.從入口文件entry開始解析,并且找到其導入的依賴模塊眷细,遞歸遍歷分析拦盹,形成依賴關(guān)系樹
4-4.對不同文件類型的依賴模塊文件使用對應(yīng)的Loader進行編譯,最終轉(zhuǎn)為javascript文件
4-5.整個過程中webpack會通過發(fā)布訂閱模式薪鹦,向外拋出一些hooks掌敬,而webpack的插件即可通過監(jiān)聽這些關(guān)鍵的事件節(jié)點惯豆,執(zhí)行插件任務(wù)進而達到干預輸出結(jié)果的目的

5.webpack文件的解析與構(gòu)建

文件的解析與構(gòu)建是一個比較復雜的過程池磁,在webpack源碼中主要依賴compiler和compilation兩個核心對象實現(xiàn)
compiler是一個全局單例,他負責把控整個webpack打包的構(gòu)建過程楷兽,compilation對象是每一次構(gòu)建的上下文對象地熄,它包含了當次構(gòu)建所需要的所有信息,每次熱更新和重新構(gòu)建芯杀,compiler都會重新生成一個新的compilation對象端考,負責此次更新的構(gòu)建過程
 而每個模塊間的依賴關(guān)系,則依賴于AST語法樹揭厚。每個模塊文件在通過Loader解析完成之后却特,會通過acorn庫生成模塊代碼的AST語法樹,通過語法樹就可以分析這個模塊是否還有依賴的模塊筛圆,進而繼續(xù)循環(huán)執(zhí)行下一個模塊的編譯解析裂明。

最終Webpack打包出來的bundle文件是一個IIFE的執(zhí)行函數(shù)。

6.webpack里的sourcemap

sourmap是一項將編譯太援、打包闽晦、壓縮后的代碼映射回源代碼的技術(shù),由于打包壓縮后的代碼沒有閱讀性可言提岔,一旦報錯或者遇到問題仙蛉,我們只能定位到壓縮處理后的代碼位置,無法定位到開發(fā)環(huán)境的代碼碱蒙,不好調(diào)試荠瘪,而sourcemap可以快速幫我們定位到源代碼的位置,提高開發(fā)效率
在項目打包完后赛惩。在打包的文件夾里除了js,css等資源文件外巧还,還有xxx.js.map的文件,這種帶map后綴的文件就是sourcemap文件坊秸,它保存了源代碼和轉(zhuǎn)換之后代碼(通常經(jīng)過壓縮混淆和其他轉(zhuǎn)換)的關(guān)系

6-1.常見的轉(zhuǎn)換過程包括但不限于:

壓縮混淆(UglifyJS)
編譯(TypeScript, CoffeeScript)
轉(zhuǎn)譯(Babel)
合并多個文件麸祷,減少帶寬請求。

6-2.sourcemap
SourceMap 的主要作用是為了方便調(diào)試

映射轉(zhuǎn)換過后的代碼和源代碼之間的關(guān)系
源代碼引入 //# sourceMappingURL=build.js.map
source Map 解決了源代碼和運行代碼不一致所產(chǎn)生的問題

注:sourceMap并不是webpack特有的功能

二.webpack配置

1.使用不同的配置文件:

如果需要使用不同的配置文件褒搔,需要在package.json文件中使用--config標志修改阶牍,例:


1663120531125.png

2.webpack使用不同編程語言和數(shù)據(jù)描述格式來編寫配置文件

2-1.typeScript

npm install --save-dev typescript ts-node @types/node @types/webpack
# 如果使用版本低于 v4.7.0 的 webpack-dev-server喷面,還需要安裝以下依賴
npm install --save-dev @types/webpack-dev-server
 
#webpack.config.ts
import * as path from 'path';
import * as webpack from 'webpack';
// in case you run into any typescript error when configuring `devServer`
import 'webpack-dev-server';

const config: webpack.Configuration = {
 mode: 'production',
 entry: './foo.js',
 output: {
  path: path.resolve(__dirname, 'dist'),
  filename: 'foo.bundle.js',
 },
};
export default config;

該示例需要 typescript 版本在 2.7 及以上,并在 tsconfig.json 文件的 compilerOptions 中添加 esModuleInterop 和 allowSyntheticDefaultImports 兩個配置項走孽。

注意:你需要確保tsconfig.json的compilertions文件的compilerOptions中module選項的值為common.js,否則webpack的運行會失敗報錯惧辈,因為ts-node不支持commonjs以外的其他的模塊規(guī)范。

你可以通過三個途徑來完成module的設(shè)置:

  • 直接修改tscinfig.json文件
  • 修改tsconfig.json并且添加ts-node的設(shè)置
  • 使用tsconfig-paths

第一種方法就是打開你的 tsconfig.json 文件磕瓷,找到 compilerOptions 的配置盒齿,然后設(shè)置 target 和 module 的選項分別為 "ES5" 和 "CommonJs" (在 target 設(shè)置為 es5 時你也可以不顯示編寫 module 配置)。

第二種方法 就是添加 ts-node 設(shè)置:

你可以為 tsc 保持 "module": "ESNext"配置困食,如果你是用 webpack 或者其他構(gòu)建工具的話边翁,為 ts-node 設(shè)置一個重載(override)

{
 "compilerOptions": {
  "module": "ESNext",
 },
"ts-node": {
 "compilerOptions": {
  "module": "CommonJS"
  }
 }
}

第三種方法需要先安裝 tsconfig-paths 這個 npm 包,如下所示:
npm install --save-dev tsconfig-paths
安裝后你可以為 webpack 配置創(chuàng)建一個單獨的 TypeScript 配置文件硕盹,示例如下:

# tsconfig-for-webpack-config.json
{
  "compilerOptions": {
  "module": "commonjs",
    "target": "es5",
    "esModuleInterop": true
  }
}

注:ts-node 可以根據(jù) tsconfig-paths 提供的環(huán)境變量 process.env.TS_NODE_PROJECT 來找到 tsconfig.json 文件路徑符匾。

# package.json

{
 "scripts": {
 "build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack"
 }
}

注:之所以要添加 cross-env,是因為我們在直接使用 TS_NODE_PROJECT 時遇到過 "TS_NODE_PROJECT" unrecognized command 報錯的反饋瘩例,添加 cross-env 之后該問題也似乎得到了解決啊胶。

2-2.coffeeScript
npm install --save-dev coffeescript
示例如下:

#webpack.config.coffee

HtmlWebpackPlugin = require('html-webpack-plugin')
webpack = require('webpack')
path = require('path')

config =
  mode: 'production'
  entry: './path/to/my/entry/file.js'
  output:
  path: path.resolve(__dirname, 'dist')
  filename: 'my-first-webpack.bundle.js'
  module: rules: [ {
  test: /\.(js|jsx)$/
  use: 'babel-loader'
  } ]
  plugins: [
  new HtmlWebpackPlugin(template: './src/index.html')
  ]

module.exports = config

3.導出

3-1.導出函數(shù):

module.exports=function(env,argv){
  return {
  mode:env.production ? 'production' : 'development',
  devtool:env.production ? 'source-map' : 'eval',
  plugins:[
    new TerserPlugin({
    terserOptions:{
    compress:argv.mode === 'production' //only if `--mode production` was passed
    }
    })
  ]
  }
}

3-2.導出promise

module.exports=()=>{
return new Promise((resolve,reject)=>{
  setTimeout(()=>{
    resolve({
    entry:'./app.js'
    })
  },5000)
})
}

注:支持使用Promise.all導出多個promise

3-3.導出多種配置

module.exports = [
{
  output: {
    filename: './dist-amd.js',
    libraryTarget: 'amd',
  },
  name: 'amd',
  entry: './app.js',
  mode: 'production',
},
{
  output: {
    filename: './dist-commonjs.js',
    libraryTarget: 'commonjs',
  },
  name: 'commonjs',
  entry: './app.js',
  mode: 'production',
},
];

注:如果你只傳了一個 --config-name 名字標識,webpack 將只會構(gòu)建指定的配置項垛贤。

3-3-1.dependencies
以防你的某個配置依賴于另一個配置的輸出焰坪,你可以使用一個dependencies列表指定一個依賴列表

#webpack.config.js

module.exports = [
{
  name: 'client',
  target: 'web',
  // …
},
{
  name: 'server',
  target: 'node',
  dependencies: ['client'],
},
];

3-3-2.parallelism
如果你導出了多個配置,你可以在配置中使用parallelism選項來指定編譯的最大并發(fā)數(shù)

#webpack.config.js

module.exports = [
 {
  //config-1
},
{
  //config-2
},
];
module.exports.parallelism = 1;

4.入口和上下文

入口對象是用于 webpack 查找開始構(gòu)建 bundle 的地方聘惦。上下文是入口文件所處的目錄的絕對路徑的字符串某饰。
4-1.content(基礎(chǔ)目錄,絕對路徑部凑,用于從配置中解析入口點和加載器)

const path = require('path');

module.exports = {
//...
  context: path.resolve(__dirname, 'app'),
};

默認使用 Node.js 進程的當前工作目錄露乏,但是推薦在配置中傳入一個值。這使得你的配置獨立于 CWD(current working directory, 當前工作目錄)涂邀。
4-2.entry開始應(yīng)用程序打包過程的一個或多個起點(配置文件中entry接受三種形式的值:字符串瘟仿,數(shù)組,函數(shù)和對象比勉,如果entry是字符串或者字符串數(shù)組劳较,文件導出后會被命名為main,如果傳入的是個對象浩聋,則每個屬性的鍵是導出的文件的名字观蜗,鍵值則是該文件的入口點)
例1:
module.exports={
entry:'./app.js'
}
例2:
entry: {
'path/of/entry': './deep-app.js',
'app': './app.js'
}
例3:
entry: {
vendor: ['jquery', 'lodash']
}
例4:
entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])),
如果傳入的是個函數(shù),它將在每次make事件中被調(diào)用

默認情況下衣洁,入口的輸出文件名是從output.filename中提取出來的墓捻,但可以指定一個自定義的輸出文件名
例5:
module.exports = {
//...
entry: {
app: './app.js',
home: { import: './contact.js', filename: 'pages/[name][ext]' },
about: { import: './about.js', filename: 'pages/[name][ext]' },
},
};

5.mode

5-1.用法
在配置對象中使用mode選項
例:
module.exports={
mode:'development'
}
從CLI參數(shù)中傳遞
例:
webpack --mode-development
mode支持以下字符串值
development:會將 DefinePlugin 中 process.env.NODE_ENV 的值設(shè)置為 development. 為模塊和 chunk 啟用有效的名。
production:會將 DefinePlugin 中 process.env.NODE_ENV 的值設(shè)置為 production坊夫。為模塊和 chunk 啟用確定性的混淆名稱砖第,F(xiàn)lagDependencyUsagePlugin撤卢,F(xiàn)lagIncludedChunksPlugin,ModuleConcatenationPlugin梧兼,NoEmitOnErrorsPlugin 和 TerserPlugin
none:不使用任何默認優(yōu)化選項
如果沒有設(shè)置放吩,webpack的mode的默認值是production

6.output

6-1.asyncChunks:創(chuàng)建按需加載的異步chunk
例:

module.exports={
 output:{
  asyncChunks:true
 }
}

6-2.filename控制輸出資源的文件名,也可以是個相對路徑羽杰,文件夾不存在會在輸出時創(chuàng)建
例:

module.exports={
  entry:'/src/main.js',
  output:{
    filename:'bundle.js
  }
}

6-3.path(指定資源輸出的位置渡紫,在webpack4之后,output.path默認為dist目錄考赛,除非我們想更改它惕澎,否則不必單獨配置,不需要寫)

const path=require('path')
module.exports={
  entry:'./src/main.js',
  output:{
    filename:'bundle.js',
    //將資源輸出位置設(shè)置為該項目的dist目錄
    path: path.resolve(__dirname, 'dist')
  },
}

多入口的情況下欲虚,我們需要對產(chǎn)生的每個bundle指定不同的名字集灌,Webpack支持使用一種類似模板語言的形式動態(tài)地生成文件名

module.exports = {
entry:{
main:'./src/main.js',
vender:'./src/vender.js'
},
output: {
filename: '[name].js',
},
};
filename中的[name]會被替換為chunk name即main和vender悔雹。因此最后會生成vendor.js與main.js

模板變量
可在編譯層面進行替換的內(nèi)容

[fullhash]:指代Webpack此次打包所有資源生成的hash
[hash]:指代Webpack此次打包所有資源生成的hash复哆,已棄用

可在chunk層面進行替換的內(nèi)容

[id]:指代當前chunk的id
[name]:設(shè)置則設(shè)置的值為此chunk的名稱,否則使用chunk的id
[chunkhash]:指代當前chunk內(nèi)容的hash腌零,包含該chunk的所有元素
[contenthash]:此 chunk 的 hash 值梯找,只包括該內(nèi)容類型的元素(受 optimization.realContentHash 影響)

可在模塊層面替換的內(nèi)容

[id]:模塊的 ID
[moduleid]:模塊的 ID,已棄用
[hash]:模塊的 Hash 值
[modulehash]:同上益涧,但已棄用
[contenthash]:模塊內(nèi)容的 Hash 值

可在文件層面替換的內(nèi)容

[file] : filename 和路徑锈锤,不含 query 或 fragment
[query] :帶前綴 ? 的 query
[fragment] :帶前綴 # 的 fragment
[base]:只有 filename(包含擴展名),不含 path
[filebase]:同上闲询,但已棄用
[path]:只有 path久免,不含 filename
[name]:只有 filename,不含擴展名或 path
[ext]: 帶前綴 . 的擴展名(對 output.filename不可用)

可在 URL 層面替換的內(nèi)容

[url]:URL
6-4.publicPath
publicPath是一個非常重要的配置項扭弧,用來指定資源的請求位置

原本圖片請求的地址是./img.jpg阎姥,而在配置上加上publicPath后,實際路徑就變成了了./dist/static/img/img.jpg鸽捻,這樣就能從打包后的資源中獲取圖片了
6-5.HtmlWebpackPlugin

npm install --save-dev html-webpack-plugin
//添加插件 plugins:[ new HtmlWebpackPlugin({ title:'output management' }) ],
打包完成后你會發(fā)現(xiàn)dist中出現(xiàn)了一個新的index.html,上面自動幫我們添加所生成的資源呼巴,打開后會發(fā)現(xiàn)瀏覽器會展示出內(nèi)容

6-6. assetModuleFilename配置圖片打包

圖片打包,webpack通過配置assetModuleFilename可以打包css里面的圖片。js import的圖片默認是不能失敗的御蒲。webpack5通過內(nèi)置配置可以實現(xiàn)衣赶,也可以安裝url-loader或者file-loader模塊。

6-7.auxiliaryComment模塊化導出技術(shù)的注釋屬性(需要output.library和output.libraryTarget一起使用厚满,如果想要注釋更細粒度的控制府瞄,可以傳入一個對象)
例:

module.exports = {
//...
 output: {
  library: 'someLibName',
  libraryTarget: 'umd',
  filename: 'someLibName.js',
  auxiliaryComment: 'Test Comment',
 },
};

將會生成:
(function webpackUniversalModuleDefinition(root, factory) {
// Test Comment
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require('lodash'));
// Test Comment
else if (typeof define === 'function' && define.amd)
define(['lodash'], factory);
// Test Comment
else if (typeof exports === 'object')
exports['someLibName'] = factory(require('lodash'));
// Test Comment
else root['someLibName'] = factory(root['_']);
})(this, function (WEBPACK_EXTERNAL_MODULE_1) {
// ...
});
例2:

module.exports = {
 //...
  output: {
  //...
    auxiliaryComment: {
      root: 'Root Comment',
      commonjs: 'CommonJS Comment',
      commonjs2: 'CommonJS2 Comment',
      amd: 'AMD Comment',
    },
  },
};

6-8.charset(告訴webpack為html的script的標簽添加)
6-9.chunkFilename
當你的代碼中使用了動態(tài)import時,webpack會將動態(tài)import的包碘箍,單獨打包遵馆, 這樣子實現(xiàn)按需載入续崖,但是打包后的文件名可能是一個隨機串。
所以為了識別這些bundle塊团搞,使用的時候需要傳入name严望,如下所示

document.getElementById('btn').onclick = function() {
import( /* webpackChunkName: "test123123" */ './test').then((res) => {
    console.log(res)
    console.log(res.default())
})
}

import調(diào)用的時候在括號里傳入注釋,如上所示逻恐,注釋是/* webpackChunkName: "test123123" */像吻,后面跟個空格,接上路徑地址复隆,意思是打包出來的bundle文件名叫test123123.js拨匆,webpack的output需要配置成 chunkFilename: 'static/js/[name].js',,這個[name]就能取到test123123

6-10.chunkLoadTimeout
chunk 請求到期之前的毫秒數(shù)挽拂,默認為 120000

6-11.chunkLoadingGlobal
webpack用于加載春看到·全局變量
例:

module.exports = {
//...
  output: {
  //...
    chunkLoadingGlobal: 'myCustomFunc',
  },
};

6-12.chunkLoading加載chunk方法
'jsonp' (web)惭每、'import' (ESM)、'importScripts' (WebWorker)亏栈、'require' (sync node.js)台腥、'async-node' (async node.js)
6-13.clean
例:

module.exports={
 output:{
  clean:true//在生成文件之前清空output目錄
 }
}

例2:

module.exports={
 output:{
  clean:{
   dry:true//打印而不是刪除應(yīng)該移除的靜態(tài)資源
  }
 }
}

例3:

module.exports={
output:{
clean:{
keep:/ignored/dir//, //保留ignored/dir下的靜態(tài)資源
}
}
}
6-14.compareBeforeEmit(告訴webpack在寫入到輸出文件系統(tǒng)時檢查輸出的文件是否已經(jīng)存在并且擁有相同內(nèi)容)
6-15.crossOriginLoading(告訴webpack啟用cross-origin屬性加載chunk,僅在target設(shè)置為web時生效绒北,通過使用JSONP來添加腳本標簽黎侈,實現(xiàn)按需加載模塊)
'anonymous'-不帶憑據(jù)(credential)啟用跨域加載
'use-credentials'-攜帶憑據(jù)(credential)啟用跨域加載
6-16.library(輸出一個庫,為你的入口做導出)

module.exports = {
  // …
  entry: './src/index.js',
  output: {
    library: 'MyLibrary',
  },
};

library.export(指定哪一個導出應(yīng)該被暴露為一個庫)

7.module

7-1.generator(在一個地方配置所有生成器的選項)

module.exports = {
module: {
generator: {
  asset: {
    // asseet 模塊的 generator 選項

    // 自定義 asset 模塊的 publicPath闷游,自 webpack 5.28.0 起可用
    publicPath: 'assets/',

    // 將靜態(tài)資源輸出到相對于 'output.path' 的指定文件夾中峻汉,webpack 5.67.0 后可用
    outputPath: 'cdn-assets/',
  },
  'asset/inline': {
    // asset/內(nèi)聯(lián)模塊的 generator 選項
  },
  'asset/resource': {
    // asset/資源模塊的 generator 選項

    // 自定義 asset/resource 模塊的 publicPath,自 webpack 5.28.0 起可用
    publicPath: 'assets/',

    // 將靜態(tài)資源輸出到相對于 'output.path' 的指定文件夾中脐往,webpack 5.67.0 后可用
    outputPath: 'cdn-assets/',
  },
  javascript: {
    // 該模塊類型尚不支持 generator 選項
  },
  'javascript/auto': {
    // 同上
  },
  'javascript/dynamic': {
    // 同上
  },
  'javascript/esm': {
    // 同上
  },
  // 其他...
 },
},
};

7-2.parser(類似于module.generator休吠,你可以用 module.parser 在一個地方配置所有解析器的選項)
7-3.noParse(防止 webpack 解析那些任何與給定正則表達式相匹配的文件。忽略的文件中 不應(yīng)該含有 import, require, define 的調(diào)用业簿,或任何其他導入機制瘤礁。忽略大型的 library 可以提高構(gòu)建性能)
例:

module.exports = {
 //...
 module: {
  noParse: /jquery|lodash/,
 },

};
7-4.unsafeCache(緩存模塊請求的解析)
包含如下幾個默認值
如果cache未被啟用,則默認值為false
如果cache被啟用辖源,并且此模塊的來自于node_modules則值為true蔚携,否則為false

module.exports = {
//...
 module: {
  unsafeCache: false,
 },
};

7-5.rules
創(chuàng)建模塊時,匹配請求的規(guī)則數(shù)組克饶,這些規(guī)則能夠修改模塊的創(chuàng)建方式酝蜒。 這些規(guī)則能夠?qū)δK(module)應(yīng)用 loader,或者修改解析器(parser)矾湃。

7-5-1.rule:每個規(guī)則可以分為三部分 - 條件(condition)亡脑,結(jié)果(result)和嵌套規(guī)則(nested rule)
7-5-1-1.rule條件
條件有兩種輸入值

  • 1.resource:資源文件的絕對路徑,它根據(jù)resolve規(guī)則解析
  • 2.issuer:請求者的文件絕對路徑,是導入時的位置
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末霉咨,一起剝皮案震驚了整個濱河市蛙紫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌途戒,老刑警劉巖坑傅,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喷斋,居然都是意外死亡唁毒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門星爪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浆西,“玉大人,你說我怎么就攤上這事顽腾〗悖” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵抄肖,是天一觀的道長久信。 經(jīng)常有香客問我,道長憎瘸,這世上最難降的妖魔是什么入篮? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任陈瘦,我火速辦了婚禮幌甘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痊项。我一直安慰自己锅风,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布鞍泉。 她就那樣靜靜地躺著皱埠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咖驮。 梳的紋絲不亂的頭發(fā)上边器,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音托修,去河邊找鬼忘巧。 笑死,一個胖子當著我的面吹牛睦刃,可吹牛的內(nèi)容都是我干的砚嘴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼际长!你這毒婦竟也來了耸采?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤工育,失蹤者是張志新(化名)和其女友劉穎虾宇,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體如绸,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡文留,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竭沫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燥翅。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜕提,靈堂內(nèi)的尸體忽然破棺而出森书,到底是詐尸還是另有隱情,我是刑警寧澤谎势,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布凛膏,位于F島的核電站,受9級特大地震影響脏榆,放射性物質(zhì)發(fā)生泄漏猖毫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一须喂、第九天 我趴在偏房一處隱蔽的房頂上張望吁断。 院中可真熱鬧,春花似錦坞生、人聲如沸仔役。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽又兵。三九已至,卻和暖如春卒废,著一層夾襖步出監(jiān)牢的瞬間沛厨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工摔认, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逆皮,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓级野,卻偏偏與公主長得像页屠,于是被迫代替她去往敵國和親粹胯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

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