webpack 之 Chunk

module、chunk、bundle 的概念

webpack 術(shù)語(yǔ)表 中有名詞解釋:

  • Module: Module 是離散功能塊,相比于完整程序提供了更小的接觸面。精心編寫的模塊提供了可靠的抽象和封裝界限,使得應(yīng)用程序中每個(gè)模塊都具有條理清楚的設(shè)計(jì)和明確的目的。
  • Chunk: 此 webpack 特定術(shù)語(yǔ)在內(nèi)部用于管理捆綁過(guò)程趁桃。輸出束(bundle)由 chunk 組成,其中有幾種類型(例如 entry 和 child )肄鸽。通常卫病,chunk 直接與 bundle 相對(duì)應(yīng),但是有些配置不會(huì)產(chǎn)生一對(duì)一的關(guān)系典徘。
  • Bundle:由許多不同的模塊生成蟀苛,包含已經(jīng)經(jīng)過(guò)加載和編譯過(guò)程的源文件的最終版本。
  • Entry Point: 入口起點(diǎn)告訴 webpack 從哪里開始逮诲,并遵循著依賴圖知道要打包哪些文件帜平∮母妫可以將應(yīng)用程序的入口起點(diǎn)視為要捆綁的內(nèi)容的 根上下文

以我自身的理解來(lái)闡述:

在模塊化編程中裆甩,對(duì)于module(模塊)廣義的認(rèn)知是所有通過(guò)import/require等方式引入的代碼(*.mjs冗锁、*.js文件)。而在萬(wàn)物皆模塊的 webpack嗤栓,項(xiàng)目中使用的任何一個(gè)資源(如css冻河、圖片)也都被視作模塊來(lái)處理。在 webpack 的編譯過(guò)程中茉帅,module 的角色是資源的映射對(duì)象叨叙,儲(chǔ)存了當(dāng)前文件所有信息,包含資源的路徑堪澎、上下文擂错、依賴、內(nèi)容等樱蛤。
原始的資源模塊以 Module 對(duì)象形式存在钮呀、流轉(zhuǎn)、解析處理刹悴。

chunk(代碼塊)是一些模塊 (module) 的封裝單元行楞。于 webpack 運(yùn)行時(shí)的 seal 封包階段生成攒暇,且直到資源構(gòu)建階段都會(huì)持續(xù)發(fā)生變化的代碼塊土匀,在此期間插件通過(guò)各種鉤子事件侵入各個(gè)編譯階段對(duì) chunk 進(jìn)行優(yōu)化處理。
webpack 在 make 階段解析所有模塊資源形用,構(gòu)建出完整的 Dependency Graph (從 Entry 入口起點(diǎn)開始遞歸收集所有模塊之間的依賴關(guān)系)就轧。然后在 seal 階段會(huì)根據(jù)配置及模塊依賴圖內(nèi)容構(gòu)建出一個(gè)或多個(gè) chunk 實(shí)例,再由 SplitChunksPlugin 插件根據(jù)規(guī)則與 ChunkGraph 對(duì) Chunk 做一系列的變化田度、拆解妒御、合并操作,重新組織成一批性能更高的 Chunks镇饺。后續(xù)再為它們做排序和生成hash等一系列優(yōu)化處理乎莉,直到 Compiler.compile 執(zhí)行完成作為資源輸出(emitAssets)。

bundle(包) 是 webpack 進(jìn)程執(zhí)行完畢后輸出的最終結(jié)果奸笤,是對(duì) chunk 進(jìn)行編譯壓縮打包等處理后的產(chǎn)出惋啃。通常與構(gòu)建完成的 chunk 為一對(duì)一的關(guān)系。但也有例外监右,比如:

  1. 當(dāng)我們給 webpack 配置了生成 SourceMap 的選項(xiàng) (devtool: 'source-map'):
// webpack 配置
module.exports = {
  entry: {
    app: './src/index.js',
  },
  mode: 'development',
  devtool: 'source-map',
  output: {
    path: __dirname + '/dist',
    filename: '[name].[contenthash:6].js',
    chunkFilename: '[name].[contenthash:8].js',
  },
  // ...
}

可以看到同一個(gè) chunk 產(chǎn)生了兩個(gè) bundle边灭,app.js 和與它對(duì)應(yīng)的 app.js.map。

打包結(jié)果
  1. MiniCssExtractPlugin 在 seal 的資源生成階段 - chunk 獲取 Manifest 清單文件的時(shí)候抽離出 CssModule 到單獨(dú)的文件健盒,這時(shí) chunk 關(guān)聯(lián)的css也算一個(gè) bundle 了绒瘦。
    【mini-css-extract-plugin源碼解析】

順便說(shuō)明下上面的output.filenameoutput.chunkFilename

  • filename 是給每個(gè)輸出的 bundle 命名的(最終的 chunk)称簿,[name]取值為 chunk 的名稱。入口 chunk 的[name]entry 配置的入口對(duì)象的 key惰帽,如上面的app (但只有當(dāng)給 entry 傳遞對(duì)象才成立憨降,否則都是默認(rèn)的main)。runtime chunk 則是optimization.runtimeChunk 配置的名字该酗。
  • 如果配置了chunkFilename券册,則除了包含運(yùn)行時(shí)代碼的那個(gè) bundle,其余 bundle 的命名都應(yīng)用chunkFilename
    如單獨(dú)抽出 runtime chunk垂涯,那么 runtime 應(yīng)用 output.filename烁焙,其余都應(yīng)用output.chunkFilename;否則就是包含入口模塊的 chunk 應(yīng)用 output.filename耕赘,其余用output.chunkFilename骄蝇。

原理:看了源碼就是 chunk 資源構(gòu)建階段觸發(fā)了template.hooks:renderManifest,會(huì)執(zhí)行插件 JavascriptModulesPlugin 的相關(guān)方法操骡。根據(jù)模版的不同執(zhí)行的方法也不同九火,mainTemplate負(fù)責(zé)生成包含 runtime 的 chunk 資源,應(yīng)用的文件名模版是outputOptions.filename册招;chunkTemplate負(fù)責(zé)其他 chunk岔激,應(yīng)用的文件名模版是outputOptions.chunkFilename。后面 TemplatedPathPlugin 插件在監(jiān)聽到 assetPath hook 時(shí)根據(jù)這個(gè)名字模版是掰,把文件名中的占位符如[chunkhash:8]虑鼎,替換成 chunk hash 值。這個(gè) hash 值存在當(dāng)前 chunk 的 清單文件數(shù)據(jù)(通過(guò) template.getRenderManifest 得到)中键痛,而 hash 是 chunk 創(chuàng)建后的優(yōu)化階段生成的 (我真能bb??)

總結(jié):我們開發(fā)的時(shí)候是 module炫彩,webpack 處理時(shí)是 chunk,最后生成瀏覽器可以直接運(yùn)行的 bundle絮短。Chunk是過(guò)程中的代碼塊江兢,Bundle是結(jié)果的代碼塊。
Module 主要作用在 webpack 編譯過(guò)程的前半段丁频,解決原始資源「如何讀」的問(wèn)題杉允;而 Chunk 則主要作用在編譯的后半段,解決編譯產(chǎn)物「如何寫」的問(wèn)題席里,兩者合作搭建起 webpack 搭建主流程叔磷。

chunk 的默認(rèn)分包規(guī)則有:

  1. 同一個(gè) entry 入口模塊與它的同步依賴(直接/間接) 組織成一個(gè) chunk,還包含 runtime (webpackBootstrap 自執(zhí)行函數(shù)的形式)胁勺。
  2. 每一個(gè)異步模塊與它的同步依賴單獨(dú)組成一個(gè) chunk世澜。其中只會(huì)包含入口 chunk 中不存在的同步依賴;若存在同步第三方包署穗,也會(huì)被單獨(dú)打包成一個(gè) chunk寥裂。

seal階段開始后嵌洼,遍歷入口對(duì)象_preparedEntrypoints,為每一個(gè)入口初始化生成 chunk 和 entryPoint封恰,入口 chunk 此時(shí)只有入口模塊本身麻养,與它的依賴真正建立聯(lián)系要在后面生成chunk graph時(shí)。
在生成入口 chunk 后诺舔,會(huì)執(zhí)行buildChunkGraph方法鳖昌,借助ModuleDependencyGraph中存儲(chǔ)的依賴關(guān)系,生成 chunk graph (chunk 依賴圖)低飒。
chunk graph 是 webpack 輸出最終 chunk 的依據(jù)许昨,它的構(gòu)建有兩個(gè)階段,生成 basic chunk graph優(yōu)化 chunk graph褥赊。

我們從buildChunkGraph的三個(gè)子方法按順序來(lái)詳解:
1.visitModules
遍歷compilation.modules建立起基本的 Module Graph (模塊依賴圖)糕档,為遍歷異步依賴(block)等所用。先處理入口 chunk 的所有同步依賴拌喉,遍歷時(shí)優(yōu)先將同步依賴嵌套的同步模塊添加完再去處理平級(jí)的同步依賴速那。然后按每個(gè)異步依賴的父模塊被處理的順序依次生成異步 chunk 和 chunkGroup。
然后遍歷 module graph尿背,為入口模塊和它所有(直接/間接)同步依賴形成一個(gè) EntryPoint(繼承自 ChunkGroup)端仰,入口 chunk此時(shí)才會(huì)建立起與其依賴模塊的聯(lián)系。為所有異步模塊和它的同步依賴生成一個(gè) chunk 和 chunkGroup(會(huì)重復(fù))田藐。如 chunk 的同步模塊已存在于入口 chunk荔烧,則不會(huì)再存入它的_modules中。此階段初始生成了 chunk graph(chunk 依賴圖)坞淮。
2.connectChunkGroups檢查入口 chunk 和 有異步依賴的異步 chunk, 如果它們的子 chunk 有它們未包含的新模塊茴晋,就建立它們各自所屬 chunkGroup 的 父子關(guān)系陪捷。
3.cleanupUnconnectedGroups找到?jīng)]有父 chunkgroup 的 chunkgroup回窘,刪除它里面的 chunk,并解除與相關(guān) module市袖、chunk啡直、chunkGroup 的關(guān)系。
2苍碟、3 階段對(duì) chunk graph 進(jìn)行了優(yōu)化酒觅,去除了 由已存在于入口 chunk 中的 模塊創(chuàng)建的異步 chunk。

buildChunkGraph也可以說(shuō)是 chunk 生成階段微峰,compilation.hooks.afterChunks觸發(fā)之后就進(jìn)入 chunk 優(yōu)化階段
暴露很多 chunk 優(yōu)化相關(guān)鉤子:觸發(fā) optimize 相關(guān) hook 移除空 chunk 和 重復(fù) chunk舷丹,如配置了SplitChunksPlugin也會(huì)在此時(shí)再對(duì) chunk 進(jìn)行組合/分割;
然后觸發(fā)其他 hook 分別設(shè)置 module.id蜓肆、chunk.id 并對(duì)它們進(jìn)行排序颜凯。以及各類 hash 的創(chuàng)建谋币。

下面我們來(lái)具體舉例說(shuō)明。比如我們有一個(gè)入口 index症概,全部關(guān)聯(lián)文件如下:
注:@是 src/ 目錄的別名

// a.js 入口文件
// src/a.js
import { add } from '@/b'
import('@/c').then(c => c.sub(2, 1))
const a = 1
add(3, 2 + a)
console.log(e)

// src/b.js
import mul from '@/d'
import('@/f').then(({f}) => console.log(f)) 

export function add(n1, n2) {
  return n1 + n2 + mul(10, 5)
}
export function unusedAdd(n1, n2) {
  return n1 + n2 * n2
}

// src/d.js
export default function mul(n1, n2) {
  const x = 10000
  return n1 * n2 + x
}

// src/c.js
import mul from '@/d'
import e from '@/e'
import('@/b').then(b => b.add(200, 100))
console.log(e)

export function sub(n1, n2) {
  return n1 - n2 + mul(100, 50)
}

// src/e.js
export default 'e'

// src/f.js
import { sub } from '@/c'
sub(6,8)
export const f = 'f'

webpack 配置:

// webpack.config.js
module.exports = {
  entry: {
    index: "./src/a",
  }
  // 省略上面相同的 output 蕾额、mode 等配置
};

先看結(jié)果,a彼城、b诅蝶、d打包進(jìn)入口 chunk (index.js),c和它同步依賴e組成 chunk[1]募壕、f和它同步依賴c调炬、e組成 chunk[0]

根據(jù)默認(rèn)分包規(guī)則為何輸出這幾個(gè) chunk 不難理解,可能唯一需要捋的是
(1)c的同步依賴d(2) 異步依賴b webpack 是怎么處理的舱馅?(3)還有c作為入口的異步依賴筐眷,又被異步模塊同步引入的情況。

再回去看我們上面大段 chunk 生成/優(yōu)化流程:生成初始 chunk graph 階段c的同步依賴d時(shí)發(fā)現(xiàn)d已經(jīng)存在于入口 chunk习柠,故不會(huì)再存入c所在的 chunk 中匀谣,疑問(wèn)(1)解決。b在此時(shí)會(huì)生成一個(gè)異步 chunk 和 一個(gè) chunkGroup资溃。

初步的basic chunk 依賴圖

此時(shí) chunk 的順序 和 圖示 chunkGroup 一致武翎。

接著對(duì) chunk graph 進(jìn)行優(yōu)化,去除了 由已存在于入口 chunk 中的b模塊創(chuàng)建的異步 chunk溶锭。疑問(wèn)(2)解決宝恶。

不從原理角度也很好理解b已經(jīng)存在于入口 chunk 了,項(xiàng)目運(yùn)行時(shí)入口 chunk 會(huì)先于其他異步 chunk 加載趴捅。屆時(shí)已經(jīng)能獲取到b垫毙,沒(méi)有必要再去異步獲取。

至于c為什么被重復(fù)打包進(jìn)f生成的異步 chunk 從原理也好理解了拱绑,因?yàn)橥揭蕾?strong>c不存在于入口 chunk综芥。疑問(wèn)(3)解決。

最終的 chunk graph

具體過(guò)程很復(fù)雜猎拨,可以看下這篇【webpack系列之六chunk graph圖生成】

另外膀藐,重復(fù)引入的異步塊,最終只會(huì)生成一個(gè)異步 chunk (本例沒(méi)有體現(xiàn))红省。在chunk graph 優(yōu)化完畢额各,chunk 優(yōu)化階段會(huì)借助訂閱 hook 的插件實(shí)現(xiàn) chunk 去重和 刪除空 chunk、給 chunk 排序等吧恃。

默認(rèn)打包規(guī)則存在的問(wèn)題

第一個(gè)缺點(diǎn):重復(fù)打包模塊

實(shí)際項(xiàng)目中公共模塊的數(shù)量和 size 和 demo 不是一個(gè)量級(jí)虾啦。像上例ce這樣重復(fù)打包的問(wèn)題就會(huì)尤其顯著。 雖然 SplitChunksPlugin 插件的默認(rèn)配置會(huì)起作用傲醉,比如不同 chunk 中大于20kb從屬于異步 chunk的公共模塊(公用 >= 2次)會(huì)被抽離出來(lái)针饥。但這明顯不足以適用所有情況。
多入口配置也會(huì)造成這個(gè)問(wèn)題需频,比如現(xiàn)在添加了一個(gè) admin 入口:

// webpack.config.js
module.exports = {
  entry: {
    index: "./src/a",
    admin: "./src/b"
  }
};

不同入口有相同的同步依賴會(huì)重復(fù)打包丁眼,有相同的異步依賴則不會(huì)(只單獨(dú)打包一次)。

看框出部分昭殉,兩個(gè)入口共同依賴bb苞七,bb就被重復(fù)打包在index.jsadmin.js里挪丢,因?yàn)椴煌肟?chunk 相互獨(dú)立蹂风。這會(huì)造成不必要的性能損耗。合理利用 SplitChunksPlugin 能夠更高效乾蓬、智能地實(shí)現(xiàn)「啟發(fā)式分包」惠啄,這里涉及的不在此展開,可移步另一篇【webpack SplitChunksPlugin 配置詳解】任内。

另外的不足:
  • 每次打包都會(huì)變動(dòng)的 runtime 包含在入口 chunk撵渡,會(huì)影響入口 chunk 文件的本地緩存
  • 第三方插件、UI庫(kù)這種變動(dòng)很少的模塊作為同步依賴和別的模塊打包在一個(gè) chunk 中死嗦,無(wú)法利用瀏覽器緩存
  • SplitChunksPlugin 代碼分割插件默認(rèn)只處理異步 chunk

runtime 分包

出于性能考慮通常會(huì)將入口 chunk 中的 runtime 單獨(dú)抽離趋距。
配置方法:entry.runtime (webpack5) 或 optimization.runtimeChunk

同樣是多入口情況,如果不抽離也會(huì)重復(fù)生成多份 runtime 代碼(在每個(gè)入口 chunk 中)越除,如果像下面這樣抽出节腐,兩個(gè)入口就可以共用一份運(yùn)行時(shí) chunk 了。

module.exports = {
  entry: {
    // 不同入口為 runtime 屬性設(shè)置同樣的名稱即可共享一個(gè) runtime chunk
    index: { import: "./src/index", runtime: "runtime" }, // webpack 5 支持
    admin: { import: "./src/admin", runtime: "runtime" }, 
  }
  // 或者
  // optimization: {
    // runtimeChunk: {
      // name: 'runtime',
    // },
  // }
};

runtime 呈現(xiàn)為一個(gè)自執(zhí)行函數(shù)摘盆,包含模塊交互時(shí)連接模塊所需的加載和解析邏輯的所有代碼翼雀。它負(fù)責(zé)項(xiàng)目的運(yùn)行,webpack 通過(guò)它來(lái)連接模塊化應(yīng)用程序孩擂。它不僅與業(yè)務(wù)代碼聯(lián)系緊密狼渊,還伴隨著 manifest 數(shù)據(jù)(chunks 映射關(guān)系的 list),每個(gè) chunk 的 id 都是基于內(nèi)容 hash 出來(lái)的肋殴,所以每次改動(dòng)都會(huì)影響它囤锉,如果打包進(jìn)入口 chunk 等于入口文件(如 index.js)的緩存每次都會(huì)失效,這顯然不是我們想要的护锤。

原理:compilation.hooks: optimizeChunksAdvanced鉤子事件被觸發(fā)的時(shí)候RuntimeChunkPlugin 的監(jiān)聽事件會(huì)響應(yīng) (SplitChunksPlugin 插件也是這時(shí)處理的):這時(shí)候默認(rèn)規(guī)則的 chunk 已分包(組)完成 (入口 和 異步),如有配置 optimization.runtimeChunk酿傍,會(huì)在這此基礎(chǔ)上抽離出 runtime 代碼烙懦。

編譯時(shí),webpack 會(huì)根據(jù)業(yè)務(wù)代碼決定輸出哪些支撐特性的運(yùn)行時(shí)代碼(基于 Dependency 子類)赤炒,例如:

需要 webpack_require.f氯析、webpack_require.r 等方法實(shí)現(xiàn)最起碼的模塊化支持亏较;
如果有用到動(dòng)態(tài)加載特性,則需要寫入 webpack_require.e 函數(shù)掩缓;
如果用到 Module Federation 特性雪情,則需要寫入 webpack_require.o 函數(shù)
等...

在實(shí)際項(xiàng)目中,單獨(dú)的 runtimeChunk 只是用于驅(qū)動(dòng)不同頁(yè)面路由和組件的加載你辣,代碼量比較小巡通,而這個(gè)文件經(jīng)常改變,每次都需要重新請(qǐng)求它舍哄。它的 http 耗時(shí)遠(yuǎn)大于它的執(zhí)行時(shí)間了宴凉,所以通常的做法是將它抽出再內(nèi)聯(lián)到我們的 index.html 之中(index.html 本來(lái)每次打包都會(huì)變)。配置 optimization.runtimeChunk 抽離表悬,使用 script-ext-html-webpack-plugin 插件將其內(nèi)聯(lián)在 index.html 弥锄。

示例:vue-cli 項(xiàng)目在 vue.config.js 用 webpack-chain 配置:

chainWebpack(config) {
  config
    .plugin('ScriptExtHtmlWebpackPlugin')
    .after('html')
    .use('script-ext-html-webpack-plugin', [{
      // `runtime` must same as runtimeChunk name. default is `runtime`
      // 正則匹配 runtime 文件名
      inline: /runtime\..*\.js$/
     }])
    .end()
  
  config.optimization.runtimeChunk('single')
}

關(guān)于 chunk 更詳細(xì)的編譯步驟可以參考【淺析 webpack 打包流程(原理) 三 - 生成 chunk】【淺析 webpack 打包流程(原理) 四 - chunk 優(yōu)化】

有點(diǎn)難的知識(shí)點(diǎn): Webpack Chunk 分包規(guī)則詳解
Webpack 理解 Chunk
webpack系列之六chunk圖生成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蟆沫,一起剝皮案震驚了整個(gè)濱河市籽暇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饭庞,老刑警劉巖图仓,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異但绕,居然都是意外死亡救崔,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門捏顺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)六孵,“玉大人,你說(shuō)我怎么就攤上這事幅骄〗僦希” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵拆座,是天一觀的道長(zhǎng)主巍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)挪凑,這世上最難降的妖魔是什么孕索? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮躏碳,結(jié)果婚禮上搞旭,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好肄渗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布镇眷。 她就那樣靜靜地躺著,像睡著了一般翎嫡。 火紅的嫁衣襯著肌膚如雪欠动。 梳的紋絲不亂的頭發(fā)上抛虫,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天权均,我揣著相機(jī)與錄音,去河邊找鬼磕瓷。 笑死硝桩,一個(gè)胖子當(dāng)著我的面吹牛沿猜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碗脊,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼啼肩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了衙伶?” 一聲冷哼從身側(cè)響起祈坠,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矢劲,沒(méi)想到半個(gè)月后赦拘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芬沉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年躺同,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丸逸。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蹋艺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黄刚,到底是詐尸還是另有隱情捎谨,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布憔维,位于F島的核電站涛救,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏业扒。R本人自食惡果不足惜检吆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凶赁。 院中可真熱鬧咧栗,春花似錦逆甜、人聲如沸虱肄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咏窿。三九已至斟或,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間集嵌,已是汗流浹背萝挤。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留根欧,地道東北人怜珍。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凤粗,于是被迫代替她去往敵國(guó)和親酥泛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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