IM跨平臺(tái)技術(shù)學(xué)習(xí)(二):Electron初體驗(yàn)(快速開始啊易、跨進(jìn)程通信茴晋、打包为流、踩坑等)

本文由蘑菇街前端技術(shù)團(tuán)隊(duì)分享蛮原,原題“Electron 從零到一”允懂,有修訂和改動(dòng)微峰。

1、引言

在上篇《快速了解新一代跨平臺(tái)桌面技術(shù)——Electron》只泼,我們已經(jīng)對(duì)Electron跨端框架有了基本的認(rèn)識(shí)遇汞。

本篇將帶你簡單上手Electron框架開發(fā)跨平臺(tái)桌面端,內(nèi)容包括一個(gè)快速開始例子呻逆、跨進(jìn)程通信原理夸赫、打包和分發(fā)、以及一些典型的技術(shù)踩坑等咖城。希望能帶給你啟發(fā)茬腿。

(本文已同步發(fā)布于:http://www.52im.net/thread-4039-1-1.html)

2、系列文章

本文是系列文章中的第2篇酒繁,本系列總目錄如下:

IM跨平臺(tái)技術(shù)學(xué)習(xí)(一):快速了解新一代跨平臺(tái)桌面技術(shù)——Electron

IM跨平臺(tái)技術(shù)學(xué)習(xí)(二):Electron初體驗(yàn)(快速開始滓彰、跨進(jìn)程通信、打包州袒、踩坑等)》(* 本文

《IM跨平臺(tái)技術(shù)學(xué)習(xí)(三):vivo的Electron詳細(xì)技術(shù)棧選型揭绑、踩坑總結(jié)等? ?》(稍后發(fā)布..?)

《IM跨平臺(tái)技術(shù)學(xué)習(xí)(四):蘑菇街基于Electron開發(fā)IM客戶端的技術(shù)實(shí)踐》(稍后發(fā)布..?)

《IM跨平臺(tái)技術(shù)學(xué)習(xí)(五):融云基于Electron的IM跨平臺(tái)SDK改造實(shí)踐總結(jié)》(稍后發(fā)布..?)

《IM跨平臺(tái)技術(shù)學(xué)習(xí)(六):網(wǎng)易云信基于Electron的IM消息全文檢索技術(shù)實(shí)踐》(稍后發(fā)布..?)

3、Electron簡介

Electron 是一個(gè)賦力前端進(jìn)行跨平臺(tái)開發(fā)的框架郎哭,讓開發(fā)人員使用 JavaScript他匪、HTML 和 CSS 等前端技術(shù)構(gòu)建跨平臺(tái)的桌面應(yīng)用。

Electron 通過將?Chromium(所有類Chrome的瀏覽器都是基于這個(gè)開源工程而來) 和?Node.js?合并到同一個(gè)運(yùn)行時(shí)環(huán)境中(見下圖)夸研,并將其打包為 Mac邦蜜,Windows 和 Linux 系統(tǒng)下的應(yīng)用,而開發(fā)人員只需關(guān)注前端代碼的開發(fā)亥至。

▲ 上圖引用自《快速了解新一代跨平臺(tái)桌面技術(shù)——Electron

Chromium悼沈、Node.js、Native API這三者的作用分別是:

1)Chromium?:為Electron提供了強(qiáng)大的UI能力姐扮,可以不考慮傳統(tǒng)瀏覽器兼容性的情況下絮供,利用強(qiáng)大的Web生態(tài)來開發(fā)界面;

2)Node.js:讓Electron有了底層的操作能力(比如文件的讀寫茶敏,甚至是集成C++等等操作)壤靶,并可以使用大量開源的npm包來完成開發(fā)需求。

3)Native API:Native API讓Electron有了跨平臺(tái)和桌面端的原生能力(比如說它有統(tǒng)一的原生界面惊搏,窗口贮乳、托盤、消息通知這些)恬惯。

Electron就是通過這三者的巧妙組合向拆,讓我們開發(fā)跨平臺(tái)應(yīng)用變的十分高效。

本質(zhì)上就是chromium(chrome開源版本)瀏覽器酪耳,有最新的東西都會(huì)在chromium測(cè)試亲铡,所以electron可以體驗(yàn)最新的api,這也是好處之一。

有關(guān)Electron的基本介紹等奖蔓,這里就不再贅述赞草,如果您還不曾了解,可以先閱讀本文的上篇吆鹤。

4厨疙、快速開始

4.1 資料準(zhǔn)備

Electron 官方提供了一個(gè)名為electron-quick-start?的項(xiàng)目,可以 clone 下來當(dāng)成模版使用疑务,本文使用 create-react-app 來一步一步學(xué)習(xí)沾凄。

其它重要的Electron開發(fā)資源:

1)Electron官網(wǎng):https://electronjs.org

2)Electron Github:https://github.com/electron知允;

3)Electron開發(fā)手冊(cè):https://www.electronjs.org/zh/docs/latest/撒蟀。

4.2 創(chuàng)建一個(gè) react 項(xiàng)目

# 安裝 create-react-app 命令,如果已將安裝請(qǐng)忽略

npm install -g create-react-app

# 創(chuàng)建 electron-react 項(xiàng)目

create-react-app electron-react

# 啟動(dòng)項(xiàng)目

cd electron-react && npm start

4.3 配置 Electron 環(huán)境

1)在 public 文件夾下新建 index.html,隨便寫點(diǎn)內(nèi)容:

...

<div>hello world</div>

...

2)接下來創(chuàng)建 electron 主線程文件(public/main.js)温鸽,建議寫在 public 路徑下面:

const{app, BrowserWindow} = require('electron')

// 創(chuàng)建全局變量并在下面引用保屯,避免被GC

let win

function createWindow () {

????// 創(chuàng)建瀏覽器窗口并設(shè)置寬高

????win = newBrowserWindow({ width: 800, height: 600 })

????// 加載頁面

????win.loadFile('./index.html')

????// 打開開發(fā)者工具

????win.webContents.openDevTools()

????// 添加window關(guān)閉觸發(fā)事件

????win.on('closed', () => {

????????win = null// 取消引用

????})

}

// 初始化后 調(diào)用函數(shù)

app.on('ready', createWindow)?

// 當(dāng)全部窗口關(guān)閉時(shí)退出。

app.on('window-all-closed', () => {

???// 在 macOS 上涤垫,除非用戶用 Cmd + Q 確定地退出姑尺,

???// 否則絕大部分應(yīng)用及其菜單欄會(huì)保持激活。

???if(process.platform !== 'darwin') {

????????app.quit()

???}

})

app.on('activate', () => {

// 在macOS上蝠猬,當(dāng)單擊dock圖標(biāo)并且沒有其他窗口打開時(shí)切蟋,

// 通常在應(yīng)用程序中重新創(chuàng)建一個(gè)窗口。

????if(win === null) {

??????createWindow()

????}

})

3)接著再修改?package.json?中的?main?字段對(duì)應(yīng)的路徑, 并添加?start?命令:

{

????...

????"main": "main.js",

????"scripts": "electron ."

}

4)執(zhí)行?npm start榆芦,就會(huì)彈出如下運(yùn)行界面:

以上就是我簡單寫的一個(gè)頁面柄粹,大家也可以寫一寫自己感興趣的東西。

真如上面演示的這樣匆绣,一個(gè)簡單的Electron跨平臺(tái)桌面應(yīng)用就開發(fā)好了驻右,真的 so easy!

5犬绒、進(jìn)程詳解

5.1 基本認(rèn)知

Electron 架構(gòu)和 Chromium 架構(gòu)類似旺入,也是具有1個(gè)主進(jìn)程和多個(gè)渲染進(jìn)程(如下圖所示)兑凿。

但是也有區(qū)別:

1)在各個(gè)進(jìn)程中暴露了 Native API 凯力,提供了 Native 能力;

2)引入了 Node.js礼华,所以可以使用 Node 的能力咐鹤;

3)但是渲染進(jìn)程使用node 需要配置。

可以簡單的理解為:Electron為web項(xiàng)目套上了Node.js環(huán)境的殼圣絮,使得我們可以調(diào)用Node.js的豐富的API祈惶。這樣我們可以用JavaScript來寫桌面應(yīng)用,拓展很多我們?cè)趙eb端不能做的事情。

下面這張圖捧请,技術(shù)原理更容易理解一點(diǎn):

5.2 主進(jìn)程的主要特點(diǎn)

Electron 運(yùn)行?package.json?的?main?腳本的進(jìn)程被稱為主進(jìn)程 (主進(jìn)程只有一個(gè))凡涩。涉及到具體代碼的講解,將在下一節(jié)中展開疹蛉,本節(jié)就不作過多闡述了活箕。

Electron主進(jìn)程的具體職責(zé):

1)主進(jìn)程連接著操作系統(tǒng)和渲染進(jìn)程,可以把她看做頁面和計(jì)算機(jī)溝通的橋梁可款;

2)進(jìn)程間通信育韩、窗口管理

3)全局通用服務(wù);

4)一些只能或適合在主進(jìn)程做的事情(例如瀏覽器下載闺鲸、全局快捷鍵處理筋讨、托盤、session)摸恍;

5)維護(hù)一些必要的全局狀態(tài)悉罕。

5.3 渲染進(jìn)程的主要特點(diǎn)

渲染進(jìn)程就是我們所熟悉前端環(huán)境了,只是載體改變了误墓,從瀏覽器變成了window.

注意:出于安全考慮蛮粮,渲染進(jìn)程是不能直接訪問本地資源的,因此都需要在主進(jìn)程完成谜慌。

Electron渲染進(jìn)程主要特點(diǎn):

1)Electron 使用了 Chromium 來展示 web 頁面然想,所以 Chromium 的多進(jìn)程架構(gòu)也被使用到;

2)每個(gè)web頁面運(yùn)行在它自己的渲染進(jìn)程中(每個(gè)渲染進(jìn)程都是相互獨(dú)立的欣范,并且只關(guān)心他們自己的網(wǎng)頁)变泄;

3)使用BrowserWindow類開啟一個(gè)渲染進(jìn)程并將這個(gè)實(shí)例運(yùn)行在該進(jìn)程中,當(dāng)一個(gè)BrowserWindow實(shí)例被銷毀后恼琼,相應(yīng)的渲染進(jìn)程也會(huì)被終止妨蛹;

4)渲染進(jìn)程中不能調(diào)用原生資源,但是渲染進(jìn)程中同樣包含Node.js環(huán)境晴竞,所以可以引入Node.js蛙卤。

5.4 主進(jìn)程與渲染進(jìn)程的關(guān)系

主進(jìn)程與渲染進(jìn)程的關(guān)系主要是這樣:

1)主進(jìn)程使用 BrowserWindow 實(shí)例創(chuàng)建網(wǎng)頁;

2)每個(gè) BrowserWindow 實(shí)例都在自己的渲染進(jìn)程里運(yùn)行著一個(gè)網(wǎng)頁(當(dāng)一個(gè) BrowserWindow 實(shí)例被銷毀后噩死,相應(yīng)的渲染進(jìn)程也會(huì)被終止)颤难;

3)主進(jìn)程管理所有頁面和與之對(duì)應(yīng)的渲染進(jìn)程;

4)由于在網(wǎng)頁里管理原生 GUI 資源是非常危險(xiǎn)而且容易造成資源泄露已维,所以在網(wǎng)頁面調(diào)用 GUI 相關(guān)的 APIs 是不被允許的(如果你想在網(wǎng)頁里使用 GUI 操作行嗤,其對(duì)應(yīng)的渲染進(jìn)程必須與主進(jìn)程進(jìn)行通訊,請(qǐng)求主進(jìn)程進(jìn)行相關(guān)的 GUI 操作)垛耳。

具體關(guān)系如下圖所示:

把它們想象成這樣:

即Chrome(或其他瀏覽器)的每個(gè)標(biāo)簽頁(tab)及其頁面栅屏,就好比 Electron 中的一個(gè)單獨(dú)渲染進(jìn)程飘千。即使關(guān)閉所有標(biāo)簽頁,Chrome 依然存在栈雳。這好比 Electron 的主進(jìn)程护奈,能打開新的窗口或關(guān)閉這個(gè)應(yīng)用。就像下圖這樣哥纫。

6逆济、從代碼角度理解進(jìn)程

6.1 主進(jìn)程和渲染進(jìn)程

先來看看 electron 項(xiàng)目基本目錄結(jié)構(gòu):

app

└─public

????└─index.html---------------入口文件

├─main.js----------------------程序啟動(dòng)入口,主進(jìn)程

├─ipc--------------------------進(jìn)程間模塊

├─appNetwork-------------------應(yīng)用通信模塊

└─src--------------------------窗口管理磺箕,渲染進(jìn)程

????├─components---------------通用組件模塊

????├─store--------------------數(shù)據(jù)共享模塊

????├─statics------------------靜態(tài)資源模塊

????└─pages----------------------窗口業(yè)務(wù)模塊

??????├─窗口A----------------窗口

??????└─窗口B----------------窗口

如上所示:package.json?中的?main?字段對(duì)應(yīng)的文件的進(jìn)程是主進(jìn)程奖慌。Electron集成了Chromium來展示窗口界面,窗口中所看到的內(nèi)容使用的都是HTML渲染出來的松靡。

Chromium本身是多進(jìn)程渲染頁面的架構(gòu)(在默認(rèn)情況下简僧,Chromium的默認(rèn)策略是對(duì)每一個(gè)tab新開一個(gè)進(jìn)程,以確保每個(gè)頁面是獨(dú)立且互不影響的雕欺,避免一個(gè)頁面的崩潰導(dǎo)致全部頁面無法使用)岛马,所以Electron在展示窗口時(shí),也會(huì)使用到Chromium的多進(jìn)程架構(gòu)屠列。而這種多進(jìn)程渲染架構(gòu)在Electron中啦逆,也就被是渲染進(jìn)程(render process)啦。

6.2 進(jìn)程間通信

在 Electron 中笛洛,GUI 相關(guān)的模塊(如 dialog,menu 等)僅在主進(jìn)程可用夏志,在渲染進(jìn)程中不可用。

為了在渲染進(jìn)程中使用它們苛让,需要使用 ipc 模塊向主進(jìn)程發(fā)送消息沟蔑,下面是幾種進(jìn)程間通訊的方法。

1)ipcMain & ipcRenderer:

從主進(jìn)程到渲染進(jìn)程的異步通信狱杰,也可以將消息從主進(jìn)程發(fā)送到渲染進(jìn)程(參考文檔)瘦材。

發(fā)送消息時(shí),事件名稱為 channel仿畸∈匙兀回復(fù)同步消息時(shí),需要設(shè)置 event.returnValue错沽。

將異步消息發(fā)送回發(fā)送方簿晓,可以使用 event.reply(...),這個(gè)輔助方法將自動(dòng)處理來自渲染進(jìn)程的消息甥捺,然而 event.sender.send(...) 這個(gè)方法則始終將消息發(fā)送給主進(jìn)程抢蚀。

下面是在渲染和主進(jìn)程之間發(fā)送和處理消息的一個(gè)例子:

// 在主進(jìn)程中

const { ipcMain } = require('electron')

ipcMain.on('asynchronous-message', (event, arg) => {

????console.log(arg); // 輸出 'ping'

????event.reply('asynchronous-reply', 'pong');

})

ipcMain.on('synchronous-message', (event, arg) => {

????console.log(arg) // 輸出 ‘ping’

????event.returnValue = 'pong'

})

// 在渲染進(jìn)程(網(wǎng)頁)中

const { ipcRenderer } = require('electron')

console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // 輸出 'pong'

ipcRenderer.on('asynchronous-reply', (event, arg) => {

????console.log(arg); // 輸出 'pong'

})

ipcRenderer.send('asynchronous-message', 'ping')

2)remote 模塊:

remote 為渲染進(jìn)程和主進(jìn)程通信提供了一種簡單的方法镀层。你可以調(diào)用 main 進(jìn)程對(duì)象的方法镰禾,而不必顯式發(fā)送進(jìn)程間消息皿曲。

例如:從渲染進(jìn)程創(chuàng)建瀏覽器窗口

const { BrowserWindow } = require('electron').remote

let win = newBrowserWindow({ width: 800, height: 600 })

win.loadUrl('https://www.mogu.com')

注意: 反過來,如果需要從主進(jìn)程訪問渲染進(jìn)程吴侦,可以使用?webContents.executeJavascript屋休。

3)webContents

即通過 channel 向渲染進(jìn)程發(fā)送異步消息,可以發(fā)送任意參數(shù)备韧。在內(nèi)部劫樟,參數(shù)會(huì)被序列化為 JSON,因此參數(shù)對(duì)象傷的函數(shù)和原型鏈不會(huì)被發(fā)送织堂。

除了以上這些方法叠艳,也可以使用?localStorage、sessionStorage?等易阳。

7附较、打包發(fā)布

開發(fā)完成后,還需要將應(yīng)用打包成可執(zhí)行文件潦俺,這一環(huán)節(jié)的坑還是學(xué)習(xí) electron 到現(xiàn)在踩的最多的拒课。

目前主流的打包工具有?electron-packager和?electron-builder

7.1 electron-packager

1)安裝依賴:

npm i electron-packager --save-dev

2)打包:

electron-packager --platform= --arch= [optional flags...]

也可以直接運(yùn)行?npm run electron-packager?打包。

7.2 electron-builder

官方解釋

A complete solution to package and build a ready for distribution Electron, Proton Native or Muon app for macOS, Windows and Linux with “auto update” support out of the box.

簡單的說:electron-builder 有比 electron-packager 更豐富的功能事示,支持更多的平臺(tái)早像,同時(shí)也支持了自動(dòng)更新。除了這幾點(diǎn)外肖爵,electron-builder 打出的包更為輕量卢鹦,并且可以打包出不暴露源碼的 setup 安裝程序。

另外使用下來感覺比?electron-packager?的坑要少一點(diǎn)劝堪。

1)安裝依賴:

npm i electron-builder --save-dev

2)打包(在項(xiàng)目的 package.json 文件中定義 build 字段):

{

????"build": {

????????"appId": "com.xxx.app",

????????"extends": null,

????????"files": [

????????????"build/**/*"

????????],

????????"mac": {

????????????"icon": "icons/icon.icns"

????????},

????????"win": {

????????????"target": "nsis",

????????????"icon": "icons/icon.png"

????????}

????}

}

這是最基礎(chǔ)的配置法挨,當(dāng)然打包過程中可能會(huì)碰到其他的問題需要修改配置。通常 files 配置只寫一個(gè) build 文件夾是不夠的幅聘,要根據(jù)項(xiàng)目結(jié)構(gòu)和打包情況添加其他路徑凡纳。

添加 scripts 命令

{

????"scripts": {

????????"pack": "electron-builder"

????}

}

運(yùn)行?npm run pack?打包。

打包完成后在?dist?目錄下有可執(zhí)行文件帝蒿,打開后如果沒有報(bào)錯(cuò)荐糜,則說明打包成功。

8葛超、踩坑總結(jié)

我所遇到的大部分都是打包遇到的坑暴氏,以下列舉幾個(gè)典型的坑。

8.1 使用 electron-packager 打包報(bào)錯(cuò)

Generated checksum for"electron-v6.0.2-darwin-x64.zip"did not match expected checksum绣张。

解決方法:node 版本升級(jí)到 8.x 以上就好答渔。

8.2 打開打包生成的可執(zhí)行文件報(bào)錯(cuò)

出現(xiàn)這種問題可能有以下幾個(gè)原因。

1)項(xiàng)目中可能直接訪問了本地路徑, 瀏覽器為了安全考慮不允許訪問侥涵。

2)package.json 中的 build 配置問題沼撕,假如 main.js 在一個(gè)很深的路徑中宋雏,需要在下面單獨(dú)添加 main.js 的路徑:

"build": {

????...

+?? "public/main.js"

????...

}

3)webpack 配置中的路徑直接使用了 __dirname, 可以使用 remote 模塊的 getAppPath 方法取得路徑:

const remote = require('remote')

const app = remote.require('app')

console.log(app.getAppPath());

參考資料:https://github.com/electron/electron/issues/5107

8.3 dependencies & devDependencies

在 Electron 打包時(shí),一定要分清哪些是生產(chǎn)環(huán)境依賴务豺,哪些是開發(fā)環(huán)境依賴磨总,避免出現(xiàn)此類錯(cuò)誤:

8.4 關(guān)于打包慢的問題(npm & cnpm)

cnpm 裝的各種?node_modules,這種方式下所有的包都是扁平化的安裝笼沥,一下子 node_modules 展開就有非常多的文件蚪燕,導(dǎo)致打包的過程非常慢。

但是如果該用 npm 來安裝?node_modules?的話奔浅,所有的包都是樹狀結(jié)構(gòu)馆纳,層級(jí)變深。但是打包速度會(huì)快很多(具體資料參見:electron打包過了2小時(shí)都沒好汹桦?)厕诡。

9、Electron的優(yōu)缺點(diǎn)

文章的最后营勤,基于實(shí)踐體會(huì)灵嫌,總結(jié)一下Electron的優(yōu)缺點(diǎn)。

Electron優(yōu)點(diǎn)很明顯:

1)上手較簡單:HTML葛作、CSS寿羞、JS、Node 赂蠢、npm包绪穆、UI框架 ,方便高效虱岂,能很輕松的實(shí)現(xiàn)很好看的UI玖院;

2)可多端運(yùn)行:可以快速構(gòu)建“跨平臺(tái)”(Windows、MacOs第岖、Linux)的桌面級(jí)應(yīng)用难菌;

3)開發(fā)時(shí)間短:相對(duì)其他跨平臺(tái)方案(如:QT、GTK+ 等)蔑滓,更穩(wěn)定郊酒、bug少,畢竟只要瀏覽器外殼跑起來了就可以了(當(dāng)然坑是少不了的)键袱;

4)兼容性問題:再也不用兼容多瀏覽器(只針對(duì)谷歌燎窘,但要兼容mac、Linux)蹄咖。

Electron缺點(diǎn)也同樣顯而易見:

1)安裝包體積大:安裝包體積略大(打包了Chromium)褐健,至少包含了一個(gè)瀏覽器的體積 ,每裝一個(gè)app就相當(dāng)于裝一個(gè)chrome澜汤;

2)運(yùn)行性能稍差:性能不如原生應(yīng)用蚜迅,Mac系統(tǒng)下絲滑一些舵匾,Window系統(tǒng)就有點(diǎn)丟幀;

3)內(nèi)存占用較大:卡慢叨、啟動(dòng)慢,新開一個(gè)進(jìn)程务蝠,起步價(jià)就是一個(gè)NodeJS的內(nèi)存開銷拍谐;

4)網(wǎng)頁加載稍慢:loadURL加載遠(yuǎn)程頁面白屏?xí)r間長(優(yōu)化可采用 VSCode 骨架屏)。

10馏段、參考資料

[1]?Electron官方開發(fā)者手冊(cè)

[2]?Electron初體驗(yàn)(快速開始轩拨、跨進(jìn)程通信、打包院喜、踩坑等)

[3]?Electron 基礎(chǔ)入門 簡單明了亡蓉,看完啥都懂了

[4]?網(wǎng)易云信Web端IM的聊天消息全文檢索技術(shù)實(shí)踐

(本文已同步發(fā)布于:http://www.52im.net/thread-4039-1-1.html)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市喷舀,隨后出現(xiàn)的幾起案子砍濒,更是在濱河造成了極大的恐慌,老刑警劉巖硫麻,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爸邢,死亡現(xiàn)場離奇詭異,居然都是意外死亡拿愧,警方通過查閱死者的電腦和手機(jī)杠河,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浇辜,“玉大人券敌,你說我怎么就攤上這事×螅” “怎么了待诅?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長熊镣。 經(jīng)常有香客問我咱士,道長,這世上最難降的妖魔是什么轧钓? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任序厉,我火速辦了婚禮,結(jié)果婚禮上毕箍,老公的妹妹穿的比我還像新娘弛房。我一直安慰自己,他們只是感情好而柑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布文捶。 她就那樣靜靜地躺著荷逞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粹排。 梳的紋絲不亂的頭發(fā)上种远,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音顽耳,去河邊找鬼坠敷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛射富,可吹牛的內(nèi)容都是我干的膝迎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼胰耗,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼限次!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起柴灯,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤卖漫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后赠群,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懊亡,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年乎串,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了店枣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叹誉,死狀恐怖鸯两,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情长豁,我是刑警寧澤钧唐,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站匠襟,受9級(jí)特大地震影響钝侠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酸舍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一帅韧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啃勉,春花似錦忽舟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刁品。三九已至,卻和暖如春浩姥,著一層夾襖步出監(jiān)牢的瞬間挑随,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工勒叠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兜挨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓缴饭,卻偏偏與公主長得像暑劝,于是被迫代替她去往敵國和親骆莹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颗搂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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