iOS 開發(fā)者的 Weex 偽最佳實(shí)踐指北

引子

這篇文章是筆者近期關(guān)于Weex在iOS端的一些研究和實(shí)踐心得,和大家一起分享分享,也算是對(duì)學(xué)習(xí)成果的總結(jié)。文章里面提到的做法也許不是最佳實(shí)踐,也許里面的方法稱不算是一份標(biāo)準(zhǔn)的指南手冊(cè),所以標(biāo)題就只好叫“偽最佳實(shí)踐指北”了。有更好的方法歡迎大家一起留言討論,一起學(xué)習(xí)。

由于筆者不太了解Android,所以以下的文章不會(huì)涉及到Android。

一. React Native 和 Weex

自從Weex出生的那一天起,就無法擺脫和React Native相互比較的命運(yùn)。React Native宣稱“Learn once, write anywhere”,而Weex宣稱“Write Once, Run Everywhere”。Weex從出生那天起,就被給予了一統(tǒng)三端的厚望。React Native可以支持iOS、Android,而Weex可以支持iOS、Android、HTML5。

在Native端,兩者的最大的區(qū)別可能就是在對(duì)JSBundle是否分包。React Native官方只允許將React Native基礎(chǔ)JS庫和業(yè)務(wù)JS一起打成一個(gè)JS bundle,沒有提供分包的功能,所以如果想節(jié)約流量就必須制作分包打包工具。而Weex默認(rèn)打的JS bundle只包含業(yè)務(wù)JS代碼,體積小很多,基礎(chǔ)JS庫包含在Weex SDK中,這一點(diǎn)Weex與Facebook的React Native和微軟的Cordova相比,Weex更加輕量,體積小巧。

在JS端,Weex又被人稱為Vue Native,所以 React Native 和 Weex 的區(qū)別就在 React 和 Vue 兩者上了。

筆者沒有寫過React Native,所以也沒法客觀的去比較兩者。不過知乎上有一個(gè)關(guān)于Weex 和 React Native很好的對(duì)比文章《weex&React Native對(duì)比》,推薦大家閱讀。

前兩天@Allen 許帥也在Glow 技術(shù)團(tuán)隊(duì)博客上面發(fā)布了一篇《React Native 在 Glow 的實(shí)踐》這篇文章里面也談了很多關(guān)于React Native實(shí)踐相關(guān)的點(diǎn),也強(qiáng)烈推薦大家去閱讀。

二. 入門基礎(chǔ)

關(guān)于小白想入門Weex,當(dāng)然最基礎(chǔ)的還是要通讀文檔,文檔是官方最好的學(xué)習(xí)資料。官方的基礎(chǔ)文檔有兩份:

教程文檔
手冊(cè)文檔

在文檔手冊(cè)里面包含了Weex所有目前有的組件,模塊,每個(gè)組件和模塊的用法和屬性。遇到問題可以先過來翻翻。很有可能有些組件和模塊沒有那些屬性。

1. Weex全家桶和腳手架

看完官方文檔以后,就可以開始上手構(gòu)建工程項(xiàng)目了。

我司在知乎上面寫了4篇關(guān)于《Weex入坑指南的》。這四篇文章還是很值得看的。

Weex也和前端項(xiàng)目一樣,擁有它自己的腳手架全家桶。weex-toolkit + weexpack + playground + code snippets + weex-devtool。

weex-toolkit是用來初始化項(xiàng)目,編譯,運(yùn)行,debug所有工具。

weexpack是用來打包JSBundle的,實(shí)際也是對(duì)Webpack的封裝。

playground是一個(gè)上架的App,這個(gè)可以用來通過掃碼實(shí)時(shí)在手機(jī)上顯示出實(shí)際的頁面。

code snippets這個(gè)是一個(gè)在線的playground。

我相信大家應(yīng)該都有Native的App,如果真的App都沒有,那就用weexpack命令初始化一個(gè)新的項(xiàng)目。如果已經(jīng)有App項(xiàng)目了,那么weex命令就只是用來運(yùn)行和調(diào)試的。

已經(jīng)有iOS項(xiàng)目的,可以通過cocospod直接安裝Weex的SDK,初始化SDK以后,Native就可以使用Weex了。加載的JS的地址改成自己公司服務(wù)器的IP。


#define CURRENT_IP @"your computer device ip"
// ...

// 修改端口號(hào)到你的端口號(hào)
#define DEMO_URL(path) [NSString stringWithFormat:@"http://%@:8080/%s", DEMO_HOST, #path]

// 修改 JS 文件路徑
#define HOME_URL [NSString stringWithFormat:@"http://%@:8080/app.weex.js", DEMO_HOST]


這樣整個(gè)項(xiàng)目就可以跑起來了。

這里還有一點(diǎn)需要說明的是,項(xiàng)目雖然跑起來了,但是每次運(yùn)行都需要啟動(dòng)npm,打開Weex的前端環(huán)境。這里有兩個(gè)做法。

第一種做法是直接Hook Xcode的run命令,在Xcode配置里面加入啟動(dòng)npm的腳本。比如下面這樣:

第二種做法就是每次運(yùn)行之前,自己手動(dòng)npm run dev。我個(gè)人還是喜歡這種方式,因?yàn)樵赬code運(yùn)行完成之前,一定可以在命令行上面打完這些命令。

再說說如何Debug,這塊使用的是weex-devtool。

這個(gè)工具和前端在Chrome里面調(diào)試的體驗(yàn)基本相同。

具體使用方法看這兩篇文章即可,這里不再贅述:

《Weex 入坑指南:Debug 調(diào)試是一門手藝活》
《Weex調(diào)試神器——Weex Devtools使用手冊(cè)》

2. Weex Market插件

在日常開發(fā)中,我們可以全部自己開發(fā)完所有的Weex界面,當(dāng)然還可以用一些已有的優(yōu)秀的輪子。Weex的所有優(yōu)秀的輪子都在Weex Market里面。

在這個(gè)Market里面有很多已經(jīng)寫好的輪子,直接拿來用,可以節(jié)約很多時(shí)間。

比如這里很火的weex-chart。weex-chart圖表插件是通過g2-mobile依賴gcanvas插件實(shí)現(xiàn)的

如果你想使用Weex Market的Plugin插件,你可以使用weex plugin 命令:


$ weex plugin add plugin_name

你只需要輸入插件的名稱就可以從遠(yuǎn)程添加插件到你本地的項(xiàng)目,比如添加 weex-chart,我們可以輸入命令:


$ weex plugin add weex-chart

我們可以使用plugin remove移除插件,比如移除安裝好的 weex-cahrt:


$ weex plugin remove weex-chart


這個(gè)插件庫里面我用過weex-router,還不錯(cuò),用它來做weex的路由管理。推薦使用。

3. iOS打包和發(fā)布

weex官方提供了weexpack命令。我覺得這個(gè)命令是提供給不懂iOS的前端的人用的。如果是Native來打包,依舊使用的Xcode的Archive打包。

完全不懂iOS的前端開發(fā)者可以使用weexpack build ios 打包,中間會(huì)要求輸入證書,開發(fā)者賬號(hào)等信息。都輸入正確以后就可以打出ipa文件了。全程傻瓜操作。如果不清楚的可以查看官方手冊(cè):
weexpack 官方手冊(cè) 《 如何用weexpack創(chuàng)建weex項(xiàng)目并構(gòu)建app 》

如果是iOS開發(fā)者,原來怎么打包現(xiàn)在還是怎么打包。只不多JS這塊要單獨(dú)進(jìn)行打包。建議是把Weex這塊單獨(dú)用一個(gè)git分支進(jìn)行管理,專門針對(duì)這個(gè)分支進(jìn)行weexpack或者Webpack進(jìn)行打包。webpack的具體配置由每個(gè)公司自己配置。

這里額外說一點(diǎn),這一點(diǎn)也是前端大神告訴我的。webpack打完包以后是可以通過webpack官方網(wǎng)站查看這個(gè)包里面究竟打入了哪些文件和依賴。雖然我打包都是一股腦的都打完,但是資深前端開發(fā)也許還會(huì)再去檢查一下是否有多的文件被打進(jìn)去了。極限壓縮包的體積,1KB的文件也不多放進(jìn)去。

再談?wù)劙l(fā)布的問題。由于有了Weex以后,每次發(fā)布都會(huì)把上個(gè)版本累計(jì)到這個(gè)版本的hotPatch都累計(jì)修復(fù)掉,并在新版里面直接內(nèi)置最新的JSBundle文件。內(nèi)置JS的目的也是為了首屏加載秒開。

4. 熱更新

關(guān)于熱更新的作用大家都明白,不然用Weex的意義就少了好多。不過這里還有一點(diǎn)需要說明的是——熱更新的策略。

在日常開發(fā)過程中,我們?cè)跒g覽器上面連著手機(jī)調(diào)試,也并不是實(shí)時(shí)刷新的。(不過通過在手機(jī)上掃描二維碼,并且手機(jī)和電腦在同一個(gè)局域網(wǎng)之內(nèi),可以做到實(shí)時(shí)更新)

所以在實(shí)際生產(chǎn)環(huán)境中,熱更新的策略應(yīng)該是這樣:有新的HotPatch就下發(fā)到客戶端,然后客戶端在下次啟動(dòng)的時(shí)候,先比對(duì)版本信息,如果是新版本,就去加載這個(gè)最新的HotPatch,然后渲染在屏幕上。

曾經(jīng)我幻想著能實(shí)時(shí)在線更新,就是線上一發(fā)布,所有用戶在聯(lián)網(wǎng)的情況下,下發(fā)HotPatch完畢以后直接加載,聯(lián)網(wǎng)的用戶可以實(shí)現(xiàn)秒級(jí)別的熱更新。這種雖然可以做到,但是意義不大。做法是專門維護(hù)一套Websocket,直連服務(wù)器,下發(fā)完畢以后可以通過調(diào)用Native的通知,Native客戶端自己刷新頁面即可。(目前應(yīng)該沒有多少公司是這樣做的吧?)

5. JSBundle版本管理與部署

關(guān)于JSBundle的版本管理這塊是應(yīng)該交給前端來管理。前端可能會(huì)用版本號(hào)來管理各個(gè)包的版本。部署也會(huì)牽扯到每個(gè)公司前端部署的流程。他們會(huì)更加了解。部署一般也會(huì)放到CDN上加速。

6. 踩坑和避坑

如果說Weex一點(diǎn)坑都沒有,那是不可能的。

比如說在某些界面連續(xù)Push的時(shí)候,頁面邊緣會(huì)有一些線條從屏幕上掃過。還有捕捉JS錯(cuò)誤或者異常的時(shí)候,Weex并不能可靠的捕捉到異常,這點(diǎn)需要靠Native來做,Native捕捉到異常以后再傳遞事件給JS Runtime去處理。

計(jì)算頁面寬高尺寸這點(diǎn)是最需要注意的。Weex進(jìn)行界面適配的時(shí)候是用750為標(biāo)準(zhǔn)的,所以需要根據(jù)750去換算。還有一點(diǎn)是Weex里面有四舍五入的操作,是會(huì)丟失一點(diǎn)精度的。具體這塊請(qǐng)看《Weex 事件傳遞的那些事兒》這篇文章里面的源碼分析。

Weex JS 引擎也不支持 HTML DOM APIs 和 HTML5 JS APIs,這包括 document, setTimeout 等。

Weex關(guān)于Web標(biāo)準(zhǔn)的實(shí)現(xiàn)現(xiàn)在還沒有達(dá)到100%,所以用Vue來寫Weex的話,有些是不支持的。

比如說一些CSS樣式,最令人想不到的就是不支持
,還不支持<form>,<table>,<tr>,<td>,不支持CSS percentage 單位,不支持類似 em,rem,pt 這樣的 CSS 標(biāo)準(zhǔn)中的其他長度單位。不支持 hsl(), hsla(), currentColor, 8個(gè)字符的十六進(jìn)制顏色。

Weex對(duì)W3C上的FlexBox的規(guī)范也沒有支持完全,暫不支持inline,也不支持Z軸上面的變化,不過移動(dòng)端在Z軸上的需求真的沒有。Weex的Layout是用的Yoga之前的某個(gè)版本,解決問題的方式也比較直接,后期升級(jí)到最新版的Yoga,便可以支持更多的Flex的標(biāo)準(zhǔn)了。

具體還有不支持的就要多翻翻文檔,比如這里的《Weex 目前不支持的Web 標(biāo)準(zhǔn)有哪些》。這些最好先看看,心里有個(gè)數(shù),以免開發(fā)時(shí)候遇到一些莫名的bug,殊不知最終是因?yàn)椴恢С謱?dǎo)致的。

然后還有一些是組件暫時(shí)還不支持同步方法。這里是Vue 2.0還不支持,官方預(yù)計(jì)是在 0.12 版本支持。

額外提醒一點(diǎn),由于蘋果前段時(shí)間對(duì)JSPatch的封殺,所以導(dǎo)致Weex官方對(duì)自定義模塊給出了一個(gè)警告:

Weex 所有暴露給 JS 的內(nèi)置 module 或 component API 都是安全和可控的, 它們不會(huì)去訪問系統(tǒng)的私有 API ,也不會(huì)去做任何 runtime 上的 hack 更不會(huì)去改變應(yīng)用原有的功能定位。

如果需要擴(kuò)展自定義的 module 或者 component ,一定注意不要將 OC 的 runtime 暴露給 JS , 不要將一些諸如 dlopen(), dlsym(), respondsToSelector:,performSelector:,method_exchangeImplementations() 的動(dòng)態(tài)和不可控的方法暴露給JS, 也不要將系統(tǒng)的私有API暴露給JS

上述警告特別強(qiáng)調(diào)了不要用dlopen(), dlsym(), respondsToSelector:,performSelector:,method_exchangeImplementations()這幾個(gè)函數(shù)。這也是為什么同樣是用Weex有些人沒有通過審核,有些人卻能通過審核的原因。

聽說安卓上有Refresh Control的一些bug,安卓在Weex上的表現(xiàn)我沒有怎么了解過,不過這塊如果出現(xiàn)在iOS上,我覺得可以直接用Native來替換掉這塊,有bug的地方都用原生來做。

總之Weex還是多多少少有一些問題,但是目前使用來看,不影響使用,只要懂得靈活變通,遇到實(shí)在過不去的坎,或者是真的一時(shí)hold不住的bug,那么多考慮用原生來替代。

三. 更多高級(jí)的玩法

接下來說一下稍微高級(jí)的玩法。以下這些即使沒有做,也不影響Weex正常上線。

1.頁面降級(jí)

Weex默認(rèn)是支持頁面降級(jí)的。比如出現(xiàn)了錯(cuò)誤,就會(huì)降級(jí)到H5。這里建議最好做一個(gè)線上的開關(guān)。我司在處理頁面降級(jí)的問題上采取了兩種級(jí)別的開關(guān):

  1. App級(jí)的開關(guān)。這個(gè)開關(guān)是管理用戶App是否使用Weex SDK的,這塊是可以在線配置的。
  2. 頁面級(jí)的開關(guān)。這個(gè)開關(guān)是管理某個(gè)頁面是否開啟Weex的。如果不開啟就降級(jí)成H5頁面。

除了降級(jí)以后,還對(duì)應(yīng)采取了灰度的策略,這樣保證線上bug降低到最低。

比如在用戶量低峰期的時(shí)候開啟開關(guān)進(jìn)行灰度。還有一級(jí)灰度就通過線上實(shí)時(shí)錯(cuò)誤監(jiān)控平臺(tái)來控制,如果因?yàn)橥话l(fā)事件導(dǎo)致Crash率陡升,那么就立即關(guān)閉Weex的開關(guān),立即進(jìn)行降級(jí)處理。

2. 性能監(jiān)控和埋點(diǎn)

在Weex給的官方Demo里面有一個(gè)M的小圓點(diǎn)浮框,點(diǎn)開會(huì)看到如下的界面:

在這里我們點(diǎn)開性能的按鈕:

在這里我們可以看到監(jiān)控了CPU,幀率,內(nèi)存,電量,流量等數(shù)據(jù),這些數(shù)據(jù)也是我們?cè)贜ative APM中監(jiān)控的常見數(shù)據(jù)。當(dāng)然,這個(gè)M圓點(diǎn)并不沒有開源。所以這塊需要各個(gè)公司自己做一套自己的監(jiān)控系統(tǒng)。這塊可能每個(gè)公司的前端已經(jīng)做好了,所以Weex需要接入到前端的性能監(jiān)控里。

如果我們?cè)冱c(diǎn)開工具的界面,就會(huì)看到如下的選項(xiàng):

這里就有埋點(diǎn)監(jiān)控。在初期可能Weex埋點(diǎn)還是由Native進(jìn)行埋點(diǎn),因?yàn)楦骷叶加凶约业腘ative完整的埋點(diǎn)系統(tǒng)了。后期埋點(diǎn)這塊也可以交給前端在前端埋點(diǎn)。

3. 增量更新和全量更新

暫時(shí)筆者還沒有實(shí)踐過Weex的增量更新,所以這里就不提增量更新了。全量更新就比較簡單,下發(fā)整個(gè)JSBundle,App在下次啟動(dòng)的時(shí)候再加載即可。Weex的包比RN的包小很多,一般就100-200K左右。阿里的一次Weex分享里面提到他們gzip壓縮以后能達(dá)到60-80K。

4. 首屏加載時(shí)間極致優(yōu)化

上圖是阿里在Weex Conf大會(huì)上提出的一個(gè)挑戰(zhàn),網(wǎng)絡(luò)請(qǐng)求加上首屏渲染的時(shí)間加起來小于1秒。

這里面涉及到3方面的因素,網(wǎng)絡(luò)下載耗時(shí),JS和Native通信耗時(shí),還有渲染耗時(shí)。

網(wǎng)絡(luò)下載耗時(shí)可以通過支持HTTP / 2,配置Spdy協(xié)議,域名收斂,支持http-cache,極致壓縮JSBundle的大小,JSBundle預(yù)加載。

JSBundle預(yù)加載的時(shí)候可以在App啟動(dòng)時(shí)候預(yù)先下載JS。遠(yuǎn)程服務(wù)器推包的時(shí)候通過長連通道Push,這里可以是全量 / 增量,被動(dòng) / 強(qiáng)制更新相互結(jié)合。

阿里關(guān)于JS和Native通信耗時(shí),渲染耗時(shí)的相關(guān)優(yōu)化見上圖。這兩方面筆者也沒有相關(guān)的實(shí)踐。

5. Vue全家桶

雖然Weex有屬于它自己的全家桶,但是在支持了Vue 2.0以后,它的全家桶完全可以換成Vue的全家桶。Vue,Vue-Router,Vuex,原來還有Vue-resource,不過尤大后來去掉了這個(gè)Vue-resource,更加推薦axios了。所以全家桶里面就是Vue,Vue-Router,Vuex,axios。

如果全部都換成了Vue以后,那么前端首屏渲染的速度就需要Vue來解決了。為了提高首屏渲染速度,wns緩存+直出 是必不可少的。在Vue 1. x 時(shí)代,沒有 server-side-render 方案,直出需要專門給寫一份首屏非Vue語法的模板。Vue2.0 server-side-render(簡稱Vue SSR)的推出,成功地讓前后端渲染模板代碼同構(gòu)。

如果只用了Vue-Router以后,當(dāng)打包構(gòu)建應(yīng)用時(shí),JSBundle 包會(huì)變得非常大,影響頁面加載。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)組件,這樣就更加高效了。
結(jié)合 Vue 的 異步組件 和 Webpack 的 code splitting feature, 輕松實(shí)現(xiàn)路由組件的懶加載。減少JSBundle的體積。

還有一點(diǎn)需要注意的是,Vue-Router 提供了三種運(yùn)行模式:
hash : 使用 URL hash 值來作路由。默認(rèn)模式。
history : 依賴 HTML5 History API 和服務(wù)器配置。
abstract: 支持所有 JavaScript 運(yùn)行環(huán)境,如 Node.js 服務(wù)器端。

不過Weex 環(huán)境中只支持使用 abstract 模式!

就在7天前,Vue 發(fā)布了v2.3.0版本,官方支持了SSR。所以在支持了SSR以后,可以大幅提升SEO,也可以做到首屏秒開。所以為了性能,SSR必做!

四. 頂級(jí)玩法

最后的最后,還有一些“前瞻性”的玩法。

1. 強(qiáng)大的JSService

JS service 和 Weex 實(shí)例在 JS runtime 中并行運(yùn)行。Weex 實(shí)例的生命周期可調(diào)用 JS Service 生命周期。目前提供創(chuàng)建、刷新、銷毀生命周期。

這塊我在官方的Demo里面也沒有找到相關(guān)的例子。在官方的文檔里面有相關(guān)的例子。在官方手冊(cè)里面有這樣一句話:

重要提醒: JS Service 非常強(qiáng)大但也很危險(xiǎn),請(qǐng)小心使用!

可見,這塊非常強(qiáng)大,也許可以做很多“神奇的”事情。

2. Weex可能有更大的“野心”

在官方手冊(cè)《拓展JS framework》這一章節(jié)里面,提到了可以橫向拓展JS framework。這個(gè)功能可能一般公司都不會(huì)去擴(kuò)展。

Weex 希望能夠尊重盡可能多的開發(fā)者的使用習(xí)慣,所以除了 Weex 官方支持的 Vue 2.0 之外,開發(fā)者還可以定制并橫向擴(kuò)展自己的或自己喜歡的 JS Framework。

定制完自己的JS Framework以后,就可能出現(xiàn)下面的代碼:


import * as Vue from '...'  
import * as React from '...'  
import * as Angular from '...'  
export default { Vue, React, Angular };


這樣還可以橫向擴(kuò)展支持Vue,React,Angular。

如果在 JS Bundle 在文件開頭帶有如下格式的注釋:


// { "framework": "Vue" }
...

這樣 Weex JS 引擎就會(huì)識(shí)別出這個(gè) JS bundle 需要用 Vue 框架來解析。并分發(fā)給 Vue 框架處理。

所以,Weex 支持同時(shí)多種框架在一個(gè)移動(dòng)應(yīng)用中共存并各自解析基于不同框架的 JS bundle。

可以支持多種框架并存這點(diǎn)非常強(qiáng)大,當(dāng)然還沒有完,one more thing……

如果正常使用API,看官方文檔,不開源碼,是不會(huì)發(fā)現(xiàn)Rax的身影的。官方文檔絲毫沒有提及到它。

Rax是什么呢?

《淘寶雙促中的 Rax》這篇文章里面介紹了Rax:

Rax 是一個(gè)基于 React 方式的跨容器的 JS 框架。

Rax 經(jīng)過 gzip 以后的大小 8k,與 Angular、React、Vue 相比更加輕量。相比React的43.7kb,小了太多。

Rax 在設(shè)計(jì)上抽象出 Driver 的概念,用來支持在不同容器中渲染,比如目前所支持的:Web, Weex, Node.js 都是基于 Driver 的概念,未來即使出現(xiàn)更多的容器(如 VR ,AR等),Rax 也可以從容應(yīng)對(duì)。Rax 在設(shè)計(jì)上盡量抹平各個(gè)端的差異性,這也使得開發(fā)者在差異性和兼容性方面再也不需要投入太多精力了。

如果說RN和Weex這些技術(shù)是用來跨端的技術(shù),那Rax是用來跨容器的:Browser、Weex、Node.js等。

那么Weex里面加了Rax能干些什么事情呢?值得期待!

GitHub Repo:Halfrost-Field

Follow: halfrost · GitHub

Source: https://halfrost.com/weex_best_practice_guidelines/


Weex 源碼解析系列文章:

Weex 是如何在 iOS 客戶端上跑起來的
由 FlexBox 算法強(qiáng)力驅(qū)動(dòng)的 Weex 布局引擎
Weex 事件傳遞的那些事兒
Weex 中別具匠心的 JS Framework
iOS 開發(fā)者的 Weex 偽最佳實(shí)踐指北


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,860評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,025評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,421評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,642評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,177評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,970評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,157評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,410評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評(píng)論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,896評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,157評(píng)論 2 375

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