前端自動(dòng)化構(gòu)建(一)

背景

互聯(lián)網(wǎng)的發(fā)展推動(dòng)了整個(gè)web前端技術(shù)快速的向前,各種前端庫(kù)/框架百花齊放。在多樣化的同時(shí)對(duì)于web開(kāi)發(fā)人員來(lái)說(shuō)變得更復(fù)雜了帕涌。
在這種背景下噩茄,我們需要了解新的知識(shí)下面,使用新的工具來(lái)降低這種復(fù)雜度。
本文重點(diǎn)總結(jié)前端自動(dòng)化構(gòu)建在前端workflow的作用绩聘。初入前端半年沥割,總結(jié)不到位的地方請(qǐng)各位大神多多提點(diǎn)。


前端自動(dòng)化

前端自動(dòng)化范圍非常廣凿菩,是很復(fù)雜的工程問(wèn)題,我將其分為三類(lèi):

  • 自動(dòng)化構(gòu)建(開(kāi)發(fā))
  • 自動(dòng)化測(cè)試(開(kāi)發(fā)&測(cè)試)
  • 自動(dòng)化發(fā)布

其中机杜,自動(dòng)化構(gòu)建是將源代碼利用工具自動(dòng)轉(zhuǎn)換成用戶(hù)可以使用的目標(biāo)的過(guò)程。'目標(biāo)'在這里指的是js,css,html的集合衅谷。'用戶(hù)'可以是你椒拗、測(cè)試或者真正的用戶(hù)。

這些工具使我們能夠在更高層次上工作获黔,并自動(dòng)化重復(fù)性任務(wù)陡叠,從而節(jié)省時(shí)間;工具簡(jiǎn)化了我們的工作流程(workflow)肢执,使我們可以專(zhuān)注于創(chuàng)造性的工作枉阵,而不是花費(fèi)數(shù)小時(shí)的時(shí)間浪費(fèi)在繁瑣的任務(wù)上。例如通過(guò)gulp,我們可以讓它監(jiān)聽(tīng)每個(gè)源文件的變化,一旦你按下ctrl+s之后,它會(huì)自動(dòng)將新變化內(nèi)容顯示在瀏覽器中预茄。

這些工具構(gòu)成的系統(tǒng)兴溜,可以稱(chēng)之為構(gòu)建系統(tǒng)(build system);并且這些工具可以叫做自動(dòng)化構(gòu)建工具,其本質(zhì)是插件或者腳本程序,能代替人去執(zhí)行繁瑣又容易出錯(cuò)的任務(wù)。


前端workflow

在開(kāi)始介紹自動(dòng)化構(gòu)建前耻陕,我們先從前端的基礎(chǔ)workflow開(kāi)始拙徽,一步一步引入自動(dòng)化構(gòu)建,逐步完成我們的workflow诗宣。

base workflow.jpg

如圖是很常見(jiàn)的前端基礎(chǔ)工作流程,這邊有幾個(gè)明顯的問(wèn)題

  1. 文件大小—都是源碼發(fā)布,所有文件都沒(méi)有經(jīng)過(guò)壓縮合并處理膘怕,客戶(hù)端訪(fǎng)問(wèn)需要逐個(gè)建立http會(huì)話(huà)下載資源,會(huì)很慢。

  2. 一致性—沒(méi)有版本管理,假設(shè)果客戶(hù)端已經(jīng)緩存a.jpg文件,而事實(shí)上你新的發(fā)布已經(jīng)修改了a.jpg,客戶(hù)端需要手動(dòng)刷新緩存才能看到新的內(nèi)容召庞。

  3. 效率—你每次修改新的內(nèi)容都需要重新推送到webSrv并且手動(dòng)刷新瀏覽器岛心。

如果你的工作流跟上圖不一致也沒(méi)有關(guān)系,因?yàn)槲抑皇浅槌隽嘶A(chǔ)的部分篮灼。

為了解決上面的workflow提到的幾個(gè)問(wèn)題忘古,我們需要對(duì)源碼進(jìn)行一些操作。下面是改進(jìn)后的流程:

優(yōu)化后的workflow.jpg

將html诅诱、css和js進(jìn)行minify操作不會(huì)對(duì)它們影響它們的功能髓堪,minify之后將多個(gè)css合并成1個(gè)css,同理將多個(gè)js合并成1個(gè)js。這樣在加載他們的時(shí)候會(huì)更快,不需要建立多個(gè)http連接干旁。

在上面的流程圖中驶沼,作為輸入資源的是我們?cè)创a(css、js争群、html)商乎,進(jìn)行minify,concat的處理輸出到目的的區(qū)域。

實(shí)際對(duì)照我們的開(kāi)發(fā)環(huán)境中祭阀,通常本地IDE的項(xiàng)目架構(gòu)會(huì)有兩個(gè)頂級(jí)的目錄鹉戚,一個(gè)是/src—目錄存儲(chǔ)著你所編寫(xiě)的項(xiàng)目源碼;另一個(gè)是/build—源碼經(jīng)處理后可用于交付的代碼存放處专控,即目的區(qū)域抹凳。

也有人喜歡用dist(distribution的縮寫(xiě))來(lái)命名目的區(qū)域,這個(gè)跟開(kāi)發(fā)規(guī)范和習(xí)慣有關(guān)系,我一般將用于測(cè)試的構(gòu)建版本放在build,將用于生產(chǎn)的構(gòu)建版本放在dist中伦腐。

我們來(lái)看一個(gè)表格:

目錄 Linux Window
src /home/kikupotter/myweb/src D:/myweb/src
build /home/kikupotter/myweb/build D:/myweb/src

在項(xiàng)目開(kāi)始的時(shí)候赢底,強(qiáng)烈建議將src和build獨(dú)立分開(kāi),剛開(kāi)始寫(xiě)前端代買(mǎi)的時(shí)候時(shí)候柏蘑,將所有內(nèi)容都放在src中幸冻,特別不規(guī)范。以下總結(jié)了關(guān)于build的注意事項(xiàng):

  1. 禁止修改build(dist)目錄中構(gòu)建好的內(nèi)容!!!一旦文件被修改就會(huì)導(dǎo)致src和build里頭的內(nèi)容不一致咳焚,如果遇到問(wèn)題很難被定位

  2. 盡可能在build版本中進(jìn)行測(cè)試洽损,而不是src中。因?yàn)閎uild是最終的在客戶(hù)端運(yùn)行的版本革半,這樣不僅可以測(cè)試功能碑定,還能發(fā)現(xiàn)構(gòu)建后的一些潛在的問(wèn)題。

  3. 如果你正在使用git(gitlab/github)作為項(xiàng)目版本管理又官,務(wù)必將build添加到ignore file中,一般情況下只要保證src的版本就能完整構(gòu)建出功能一致的build版本延刘。

經(jīng)過(guò)以上步驟,我們來(lái)看現(xiàn)在的實(shí)際工作流向:


workflow-src-build.png

在此基礎(chǔ)上六敬,假設(shè)我們有兩個(gè)js文件:src/js/a.js,src/js/b.js碘赖,我們將它minify之后,合并成build/js/all.min.js外构;同理普泡,有兩個(gè)css文件:src/css/first.css,src/css/second.css,我們將它minify之后典勇,合并成build/css/all.min.css劫哼。

最后還需要處理一個(gè)明顯的問(wèn)題,一般情況下你的src/index.html會(huì)引用了上面的a.js割笙、b.js、first.css、second.css.

<head>
  <script src="/js/a.js"></script>
  <script src="/js/b.js"></script>
  <link rel="stylesheet" media="all" href="/css/first.css">
  <link rel="stylesheet" media="all" href="/css/second.css">
</head>

經(jīng)處理的靜態(tài)資源名稱(chēng)都變了(a.js/b.js->all.min.js ,first.css/second.js->all.min.css)伤溉,這樣會(huì)導(dǎo)致build發(fā)布后般码,加載index.html時(shí)出現(xiàn)404。所以我們?cè)谟泻喜⒉僮鲿r(shí)乱顾,需要同步修改build/index.html的引用(其他引用的地方也需要修改)

<head><script src="/js/all.min.js"></script><link rel="stylesheet" media="all" href="/css/all.min.css"></head>

到這里為止板祝,我們將build目錄的內(nèi)容開(kāi)心的push到遠(yuǎn)程websrv,打開(kāi)瀏覽器查看你最新更改的內(nèi)容走净。你可能會(huì)好奇券时,我們是如何來(lái)管理src到build這個(gè)構(gòu)建的過(guò)程,并且如何保證構(gòu)建后的build代碼跟src功能一致?我們不可能靠手工方式來(lái)進(jìn)行構(gòu)建或者保證他們的一致性伏伯,這樣效率太低而且容易出錯(cuò)橘洞。所以下面就引出我們的自動(dòng)化構(gòu)建工具。


使用工具實(shí)現(xiàn)自動(dòng)化構(gòu)建流程

構(gòu)建工具是一個(gè)能將前端源碼轉(zhuǎn)換成可交付代碼過(guò)程,并且這個(gè)轉(zhuǎn)換過(guò)程是可以是完全不用人工干預(yù)说搅,即所謂的自動(dòng)化構(gòu)建炸枣。

任何時(shí)候,只要你的源代碼有變動(dòng)弄唧,構(gòu)建工具就能自動(dòng)的將源碼轉(zhuǎn)換成最新的構(gòu)建版本适肠,并且自動(dòng)在瀏覽器中顯示剛才的變更。

可用的自動(dòng)化構(gòu)建工具

目前的主流的自動(dòng)化構(gòu)建工具很多候引,其核心的理念都是一致的侯养,讓機(jī)器去做哪些枯燥的重復(fù)性的勞動(dòng),你只需要編寫(xiě)好構(gòu)建工具(build tool)的配置文檔澄干,這些小機(jī)器人就能按照你的預(yù)定任務(wù)將源碼進(jìn)行構(gòu)建沸毁,最終呈現(xiàn)在你面前的是一個(gè)可交付的代碼,它可能正在交付給測(cè)試傻寂,或者已經(jīng)通過(guò)測(cè)試具備上線(xiàn)條件的代碼息尺。

常用的構(gòu)建工具有:
1. grunt
2. gulp

我平常使用的是gulp,原因:
1.我熟悉Linux,gulp的工作原理跟linux的管道|非常類(lèi)似疾掰,容易理解搂誉。
2.gulp使用js語(yǔ)法,插件式比較好管理,學(xué)習(xí)成本低静檬,并且能解決我大部分的構(gòu)建問(wèn)題炭懊。

準(zhǔn)備構(gòu)建工具配置文件

配置文件描述所有的構(gòu)建細(xì)節(jié),文件中的內(nèi)容實(shí)際上是定義構(gòu)建工具的task集合拂檩。每個(gè)task執(zhí)行特定的構(gòu)建任務(wù)侮腹,task之前有依賴(lài)關(guān)系,并且多個(gè)task可以組合起來(lái)實(shí)現(xiàn)完整的構(gòu)建工作稻励。
在gulp中這個(gè)文件通常為gulpfile.js,如果是grunt這個(gè)文件通常為gruntfile.js:

目錄 Linux Window
src /home/kikupotter/myweb/src D:/myweb/src
build /home/kikupotter/myweb/build D:/myweb/src
gulp /home/kikupotter/myweb/gulpfile.js D:/myweb/gulpfile.js
grunt /home/kikupotter/myweb/gruntfile.js D:/myweb/gruntfile.js

定義構(gòu)建文件中的task

構(gòu)建工具是根據(jù)構(gòu)建文件中定義的task來(lái)執(zhí)行的父阻,如gulpfile.js里定義的gulp.task('copyfile',fn)愈涩,其功能時(shí)將src內(nèi)容拷貝到build中;通臣用可以在命令行中運(yùn)行:

bash#gulp copyfile

構(gòu)建任務(wù)可以組合履婉,也可以被其他任務(wù)調(diào)用,這就意味著任務(wù)之間有依賴(lài)關(guān)系。我們通常會(huì)定義clean任務(wù)斟览,其功能是每次開(kāi)始構(gòu)建時(shí)都將build目錄清空毁腿,保證新的構(gòu)建不會(huì)有歷史記錄的影響。所以新的構(gòu)建應(yīng)該是這樣:


//定義clean任務(wù)

task('clean',fn)

//定義copyfine任務(wù)

task('copyfile',fn)

//bulid任務(wù)將clean和copyfile組合在一起苛茂,每次運(yùn)行build都會(huì)先執(zhí)行clean后copyfile已烤,他們之前有依賴(lài)關(guān)系

task('build',['clean','copyfile'])

綜上,一個(gè)task需要定義需要如下信息:

  1. taskname — 一個(gè)有意義的task名稱(chēng)妓羊,切記不要取task('a',fn1),task('b',fn2)胯究,無(wú)法確認(rèn)具體是干啥的。

  2. 注釋?zhuān)üδ苊枋觯?— 寫(xiě)注釋或者功能描述侍瑟,目的是讓團(tuán)隊(duì)其他人知道你定義task的功能唐片。

  3. 依賴(lài) — 任務(wù)組合在一起時(shí)需要關(guān)注任務(wù)之間的依賴(lài)關(guān)系,你不可能將clean放到copyfile之后運(yùn)行涨颜,這樣你會(huì)得不到任何東西(我就這么愚蠢過(guò)T T)费韭。

  4. 功能(fn)—通常是一段代碼或是配置,用來(lái)實(shí)現(xiàn)task具體的功能庭瑰。


編寫(xiě)配置文件定義構(gòu)建流程

本文不會(huì)實(shí)際的編寫(xiě)gulpfile.js星持,每種工具的配置語(yǔ)法和表現(xiàn)形式不一樣。通過(guò)偽代碼的方式表達(dá)弹灭,主要是體現(xiàn)思路督暂,也好理解。
簡(jiǎn)單執(zhí)行構(gòu)建任務(wù):

base-build.jpg
task clean說(shuō)明

刪除build構(gòu)建目錄中的所有內(nèi)容穷吮。

task build說(shuō)明

build有4應(yīng)該有4個(gè)任務(wù)task-scripts,task-css,task-images,task-html逻翁,分別對(duì)應(yīng)處理4種靜態(tài)資源,并且將處理完的文件移動(dòng)到build的4個(gè)目錄捡鱼。在這一步中可以有兩種運(yùn)行方式(選擇具體的執(zhí)行方式可以查看相應(yīng)工具的文檔說(shuō)明):

1. 異步執(zhí)行,4個(gè)任務(wù)同時(shí)跑八回,互補(bǔ)影響。

2. 同步執(zhí)行驾诈,依次執(zhí)行缠诅。

不管是那種運(yùn)行方式,這里結(jié)果是一樣的乍迄,并且異步會(huì)更快管引。

task-scripts

將src/js/a.js,src/js/b.js:minify->合并->移動(dòng)到build/script/all.min.js

task-css

將src/js/first.js,src/js/second.js minify->合并->移動(dòng)到build/script/all.min.css

task-images

將src/images圖片:逐個(gè)壓縮->移動(dòng)到build/images目錄。

task-html

將src/index.html :修改index.html中靜態(tài)資源引用指到build**->minify->移動(dòng)到build/index.html

task執(zhí)行完成

task執(zhí)行完成闯两,所有處理完的資源都保存在build目錄中褥伴,可以給網(wǎng)站正常使用谅将。build的目錄結(jié)構(gòu)一般在task里定義,根據(jù)工程規(guī)范進(jìn)行命名噩翠。還有如下兩種常見(jiàn)的目錄結(jié)構(gòu):build/(libs,scripts,styles,images,html)
戏自、build/scripts|build/assets/(libs,css,images,html)


插件

一般每個(gè)任務(wù)都有對(duì)應(yīng)的插件來(lái)完成相應(yīng)的功能邦投,我們不需要額外寫(xiě)大量的代碼來(lái)處理伤锚,只需安裝所需功能的插件,進(jìn)行一些基礎(chǔ)的配置就能完成任務(wù)志衣。
下表對(duì)應(yīng)上小結(jié)中相關(guān)的插件:

Task gulp插件 grunt插件
clean gulp-clean grunt-contrib-clean
scripts gulp-uglify grunt-contrib-uglify
css gulp-minify-css grunt-contrib-cssmin
images gulp-imagemin grunt-contrib-imagemin
html gulp-htmlmin grunt-contrib-htmlmin

改善之后的workflow
優(yōu)化后的workflow.jpg

我們所需要關(guān)心的事情是如何高效編寫(xiě)源碼屯援,剩下的構(gòu)建工作都交給工具。PS(現(xiàn)在人工智能發(fā)展這么快念脯,哪天出個(gè)智能工具將設(shè)計(jì)直接能轉(zhuǎn)換成源碼狞洋,那真的就失業(yè)了,可怕绿店。吉懊。)

這個(gè)workflow還有幾個(gè)步驟(發(fā)布,刷新頁(yè)面等)假勿。我還想再懶一點(diǎn)借嗽,我不想手動(dòng)執(zhí)行構(gòu)建,我想的是每次修改完src的文件后转培,按下ctrl+s,構(gòu)建工具就能自動(dòng)運(yùn)行一個(gè)默認(rèn)的構(gòu)建任務(wù)恶导,在本地啟動(dòng)一個(gè)websrv而不是每次都推送到遠(yuǎn)程websrv,之后自動(dòng)打開(kāi)或者刷新瀏覽器,將新的變更顯示屏幕上浸须。

剩下可構(gòu)建的部分.jpg

我們還需要幾個(gè)task來(lái)完成上面提到的自動(dòng)化任務(wù)惨寿。

task watch

如果每次修改完內(nèi)容都需要手動(dòng)的執(zhí)行構(gòu)建任務(wù),這樣會(huì)非常繁瑣删窒。有可能因?yàn)榍缅e(cuò)參數(shù)導(dǎo)致構(gòu)建失敗裂垦。凡是需要手動(dòng)重復(fù)執(zhí)行的任務(wù)我們都要想辦法將它自動(dòng)化。

watch就能完美的處理這個(gè)問(wèn)題:

task-watch.jpg
task websrv

大部分時(shí)間構(gòu)建好的代碼都是拿來(lái)測(cè)試肌索,我們不需要每次都將build代碼push到遠(yuǎn)端websrv蕉拢。并且遠(yuǎn)端通常是linux服務(wù),對(duì)于不熟悉linux的開(kāi)發(fā)會(huì)帶來(lái)許多困擾驶社,如權(quán)限企量、啟停websrv等問(wèn)題,同時(shí)也節(jié)約推送的時(shí)間亡电。所以在本地啟動(dòng)一個(gè)websrv是非常明智的届巩,通過(guò)本地服務(wù)直接訪(fǎng)問(wèn)頁(yè)面。


task-localsrv.jpg
task refresh browser

每次修改src后份乒,最終都能自動(dòng)在本地瀏覽器中打開(kāi)恕汇,并且顯示最新的內(nèi)容腕唧。不需要再每次都ctrl+F5.

task-refresh.jpg

利用構(gòu)建工具能完成上述的幾個(gè)任務(wù),他們都有相應(yīng)的插件瘾英。

Task gulp插件 grunt插件
watch gulp-watch grunt-contrib-watch
local-websrv browser-sync grunt-contrib-connect
refresh-browser browser-sync grunt-contrib-watch

最后枣接,我們單獨(dú)的提取出所有可以自動(dòng)化的流程:

all-task.jpg
我們最終的構(gòu)建文件
task 依賴(lài) 描述
default build 默認(rèn)的task,不需要任何參數(shù)
build clean, scripts, styles, images, html 對(duì)源碼進(jìn)行minify,合并后拷到build目錄
watch local-websrv,refresh-browser 啟動(dòng)本地服務(wù),監(jiān)聽(tīng)src目錄缺谴,任何變化都會(huì)觸發(fā)default任務(wù)但惶,將最新的內(nèi)容在客戶(hù)端中展示。

構(gòu)建工具還能做什么

處理上面提到的內(nèi)容湿蛔,構(gòu)建工具還有其他方面的功能膀曾,這里我羅列出我有用過(guò)的,沒(méi)用過(guò)暫時(shí)不貼阳啥。

Linting

簡(jiǎn)單的說(shuō)Linintg就是對(duì)源碼文件進(jìn)行靜態(tài)分析添谊,語(yǔ)法檢查。省去大量的時(shí)間放在語(yǔ)法檢測(cè)上察迟。

  • JavaScript可以使用jshint的工具進(jìn)行自動(dòng)檢查

    1. 檢查js語(yǔ)法讓代碼更健壯

    2. 檢查js代碼風(fēng)格提高代碼質(zhì)量斩狱,易維護(hù)。

    3. 檢查安全和性能相關(guān)內(nèi)容

  • Css可以使用csslint工具進(jìn)行自動(dòng)檢查

    1. 檢查css語(yǔ)法

    2. 檢查css代碼風(fēng)格

  • Html可以使用htmlhint工具進(jìn)行自動(dòng)檢查

    1. 檢查css語(yǔ)法
    2. 檢查css代碼風(fēng)格

同樣他們有對(duì)應(yīng)的插件:

功能 gulp grunt
Lint css gulp-csslint grunt-contrib-csslint
Lint js gulp-jshint grunt-contrib-jshint
Lint html gulp-htmlhint grunt-htmlhint
發(fā)布

一般公司都會(huì)有前端發(fā)布系統(tǒng)扎瓶,我們只需要把git地址丟給發(fā)布系統(tǒng)剩下的工作就不需要關(guān)系了所踊。如果有個(gè)人博客,沒(méi)有時(shí)間去獨(dú)立整理一套發(fā)布系統(tǒng)栗弟,這個(gè)功能是你需要的污筷。

功能 gulp插件 grunt插件
FTP gulp-ftp grunt-ftp-deploy
Github pages gulp-git-pages grunt-gh-pages
rsync gulp-rsync grunt-rsync

同樣他們有對(duì)應(yīng)的插件:

功能 gulp插件 grunt插件
FTP gulp-ftp grunt-ftp-deploy
Github pages gulp-git-pages grunt-gh-pages
rsync gulp-rsync grunt-rsync

總結(jié)

構(gòu)建工具可以用來(lái)做很多事情,甚至可以自行開(kāi)發(fā)插件來(lái)實(shí)現(xiàn)你所需的功能乍赫,因此它容易被濫用瓣蛀。

所以這里有一些簡(jiǎn)單有效的原則可以幫助我們正確使用構(gòu)建工具。

  1. src是你的雷厂,build是構(gòu)建工具的惋增,互不侵犯

    • 不編輯build目錄的任何內(nèi)容。

    • 不用構(gòu)建工具對(duì)src目錄進(jìn)行修改操作改鲫。

  2. 每個(gè)tack盡可能小诈皿,并且可以被組合使用

  3. 日常workflow對(duì)應(yīng)到一個(gè)main(default)task.

  4. 不是常規(guī)工作流的任務(wù)獨(dú)立執(zhí)行,不放到main task中像棘。

    • main(default) task 常規(guī)開(kāi)發(fā),用戶(hù)本地環(huán)境

    • deploy task 常規(guī)發(fā)布稽亏,用于生產(chǎn)

  5. 不應(yīng)該在構(gòu)建文件中使用跟用戶(hù)鑒權(quán)相關(guān)的信息(例如賬號(hào)密碼)

  6. 引入source map,方便本地開(kāi)發(fā)調(diào)試


寫(xiě)在最后

筆者前端水平有限缕题,希望在日常工作中不斷學(xué)習(xí)總結(jié)截歉,提升自己。我自己本地其實(shí)有工作筆記烟零,記錄在有道云中瘪松。如今分享出來(lái)咸作,一是對(duì)自己工作的總結(jié)(云筆記比較零散),二是希望對(duì)也是剛?cè)肭岸说耐瑢W(xué)們有一些幫助(不要是誤導(dǎo)就行哈)宵睦,最后總結(jié)不對(duì)地方煩請(qǐng)各路大神指正记罚,謝謝大家!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伴栓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酵使,更是在濱河造成了極大的恐慌荐吉,老刑警劉巖焙糟,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異样屠,居然都是意外死亡穿撮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)痪欲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)悦穿,“玉大人,你說(shuō)我怎么就攤上這事业踢±跗猓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵知举,是天一觀(guān)的道長(zhǎng)瞬沦。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雇锡,這世上最難降的妖魔是什么逛钻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮锰提,結(jié)果婚禮上曙痘,老公的妹妹穿的比我還像新娘。我一直安慰自己立肘,他們只是感情好边坤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谅年,像睡著了一般茧痒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踢故,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天文黎,我揣著相機(jī)與錄音惹苗,去河邊找鬼。 笑死耸峭,一個(gè)胖子當(dāng)著我的面吹牛桩蓉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劳闹,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼院究,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了本涕?” 一聲冷哼從身側(cè)響起业汰,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菩颖,沒(méi)想到半個(gè)月后样漆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晦闰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年放祟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呻右。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡跪妥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出声滥,到底是詐尸還是另有隱情眉撵,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布落塑,位于F島的核電站纽疟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芜赌。R本人自食惡果不足惜仰挣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缠沈。 院中可真熱鬧膘壶,春花似錦、人聲如沸洲愤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柬赐。三九已至亡问,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背州藕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工束世, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人床玻。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓毁涉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親锈死。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贫堰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

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

  • gulpjs是一個(gè)前端構(gòu)建工具,與gruntjs相比待牵,gulpjs無(wú)需寫(xiě)一大堆繁雜的配置參數(shù)其屏,API也非常簡(jiǎn)單,學(xué)...
    井皮皮閱讀 1,297評(píng)論 0 10
  • gulpjs是一個(gè)前端構(gòu)建工具缨该,與gruntjs相比偎行,gulpjs無(wú)需寫(xiě)一大堆繁雜的配置參數(shù),API也非常簡(jiǎn)單压彭,學(xué)...
    依依玖玥閱讀 3,154評(píng)論 7 55
  • gulpjs是一個(gè)前端構(gòu)建工具睦优,與gruntjs相比,gulpjs無(wú)需寫(xiě)一大堆繁雜的配置參數(shù)壮不,API也非常簡(jiǎn)單,學(xué)...
    build1024閱讀 529評(píng)論 0 0
  • gulpjs是一個(gè)前端構(gòu)建工具皱碘,與gruntjs相比询一,gulpjs無(wú)需寫(xiě)一大堆繁雜的配置參數(shù),API也非常簡(jiǎn)單癌椿,學(xué)...
    小裁縫sun閱讀 928評(píng)論 0 3
  • 在現(xiàn)在的前端開(kāi)發(fā)中健蕊,前后端分離、模塊化開(kāi)發(fā)踢俄、版本控制缩功、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開(kāi)始...
    Charlot閱讀 5,440評(píng)論 1 32