前后端分離

前后端分離的歷史

軟件開發(fā)早期是沒(méi)有前后端分離的概念的,為什么?因?yàn)楫?dāng)時(shí)壓根兒就沒(méi)有前端工程師砸王,專門的前端工程師大約是在2005年。在此之前前端是不受重視的峦阁。這其實(shí)和軟件的發(fā)展有關(guān)谦铃,說(shuō)到這里又不得不提到j(luò)s的發(fā)展歷史。JavaScript誕生于1995年榔昔。起初它的主要目的是處理以前由服務(wù)器端負(fù)責(zé)的一些表單驗(yàn)證驹闰。后來(lái)大家對(duì)頁(yè)面的要求越來(lái)越高,js又給web多了一些動(dòng)態(tài)功能撒会。大家對(duì)前端的需求就是展示靜態(tài)內(nèi)容或者簡(jiǎn)單的動(dòng)態(tài)內(nèi)容(比如CGI返回?cái)?shù)據(jù)拼接輸出“動(dòng)態(tài)”內(nèi)容)

前后端分離

1998年ajax技術(shù)的出現(xiàn)嘹朗,允許客戶端腳本發(fā)送HTTP請(qǐng)求(XMLHTTP),并且局部刷新頁(yè)面诵肛,這種突破性的創(chuàng)新使得web高速發(fā)展屹培,推動(dòng)了web的發(fā)展。隨著HTML5怔檩,CSS3惫谤,ES6(簡(jiǎn)稱356)的出現(xiàn),web正以前所未有的速度前進(jìn)珠洗,web工程師從無(wú)到有,再到現(xiàn)在web工程師被賦予了很多花環(huán)若专,機(jī)遇和挑戰(zhàn)许蓖。也因此前后端不得不逐漸的分離。

前后端合并

正所謂合久必分调衰,分久必合膊爪。 前幾年被熱炒的全棧工程師,以及前后端同構(gòu)技術(shù)都反映了前端端在分離之后又逐漸合并的跡象嚎莉。為什么會(huì)這樣呢米酬?前后端分離雖然減少了后端開發(fā)的工作(最初前端都是后端寫的,比如.net 的 aspx java的jsp等)趋箩。但前后端分離地不干凈導(dǎo)致一些溝通問(wèn)題反而不如一個(gè)人來(lái)做赃额。為了解決這個(gè)問(wèn)題,主要又兩種方式:

  • 全棧工程師叫确。 將所有工作交給一個(gè)人跳芳,或者有著前后端知識(shí)的一群人,這樣溝通起來(lái)成本比較低竹勉。
  • 稍后講飞盆。

那還又必要分離嗎?

上面講述了前后端合并,那么還有必要分離嗎吓歇? 非常又必要D跛!城看!

剛才說(shuō)為了解決前后端溝通問(wèn)題主要又兩種方式女气,下面說(shuō)下第二種。

  • 建立中間層析命。 前后端問(wèn)題產(chǎn)生的原因主要是兩個(gè)主卫,一個(gè)是知識(shí)背景,技術(shù)棧不同鹃愤,難以互相理解簇搅。二是 前后端是一個(gè)依賴的關(guān)系,前端需要依賴后端的數(shù)據(jù)接口软吐,因此存在工作上的先后關(guān)系瘩将。 建立中間層可以有效減少上述的問(wèn)題。 目前淘寶凹耙,挖財(cái)姿现,51,有贊肖抱,二維火都在嘗試這種方式备典。這也是我將會(huì)在后面重點(diǎn)描述的方式。

最近出現(xiàn)的docker容器技術(shù)等有效地減少了后端的工作量意述,讓后端更加專注業(yè)務(wù)邏輯的編寫提佣。我覺得node的出現(xiàn)也大概如此吧,它的出現(xiàn)不是用來(lái)替代apache成為下一個(gè)web容器荤崇,我覺得他更是擴(kuò)展了前端的領(lǐng)域拌屏,使得可以將一部分后端無(wú)法做(比如ssr)或者不好做(不愿意做)的東西(比如接口聚合),移交給前端术荤。

我不喜歡被冠以前端工程師倚喂,后端工程師的帽子。 我喜歡工程師這個(gè)稱呼瓣戚,我覺得我是以工程化的方式解決問(wèn)題的角色端圈,而不應(yīng)該限定于某一部分職責(zé)。這個(gè)我主張前后端分離不矛盾子库,每個(gè)角色都自己的分工枫笛,都有自己精細(xì)化的一面。我們不試圖取代后端刚照,我們只是專注做好自己罷了刑巧。

前后端耦合

我有幸在我的職業(yè)生涯中經(jīng)歷了前后端耦合喧兄,前后端開發(fā)分離,部署分離的“分離階段”啊楚, 以及大廠(alibaba)在這些方面的解決方案吠冤,所以非常榮幸能夠?qū)⒆约旱慕?jīng)驗(yàn)和心得與大家分享。

最初在百世做前端的時(shí)候恭理,我經(jīng)歷了前后端極度耦合的方式前后端雖然由不同的人來(lái)書寫拯辙,那恰好也是我的領(lǐng)導(dǎo)首次嘗試前后端分離模式,在此之前前后端通常都是一名后端人員來(lái)寫的颜价。這種模式雖然將前后端工作進(jìn)行了切分涯保,但是其耦合的成分還是非常大。

首先我們來(lái)看下我們的具體做法周伦。

  1. 前后端約定接口夕春。
  2. 前端根據(jù)后端接口進(jìn)行開發(fā)。
  3. 后端進(jìn)行開發(fā)专挪。(2與3基本并行)
  4. 前端打包代碼及志,并將代碼發(fā)送給后端。后端放到war包下寨腔。

tomcat/conf/web.xml配置如下:

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

將war文件直接復(fù)制到tomcat/webapps下

我們后端使用的是java速侈,具體做法:

  • 如果是Intellij Idea,在導(dǎo)入前端項(xiàng)目之后,右鍵項(xiàng)目 add framework support --> web application迫卢,這時(shí)將會(huì)把前端項(xiàng)目轉(zhuǎn)換為一個(gè)javaweb項(xiàng)目倚搬,然后將靜態(tài)資源放在生成的web目錄下即可。
  • 如果是eclipse乾蛤,可以新建一個(gè)javaweb項(xiàng)目然后將靜態(tài)資源放入web或者webcontent目錄下每界,或者直接先導(dǎo)入前端項(xiàng)目,然后通過(guò) project facts 將項(xiàng)目轉(zhuǎn)換為dynamic web項(xiàng)目并勾選 js等相關(guān)配置幻捏。
    然后,運(yùn)行項(xiàng)目時(shí)把后端的war包和前端的war包一同添加到 deployment中運(yùn)行即可

這一階段我們實(shí)現(xiàn)了初步的前后端分離命咐。 但是上述做法有兩個(gè)問(wèn)題篡九。

  1. 由于上述的做法存在嚴(yán)重的問(wèn)題在于前端對(duì)于發(fā)布控制力明顯不足,比如版本控制不好做醋奠。 另外由于發(fā)布通常需要兩個(gè)編譯環(huán)境榛臼,即jdk編譯后端代碼,node環(huán)境編譯前端代碼窜司。前端通常需要安裝后端環(huán)境如jdk沛善,后端也需要安裝前端環(huán)境如node。不管是學(xué)習(xí)成本還是溝通成本都是一個(gè)問(wèn)題塞祈。

  2. 前端通常需要等待后端給出測(cè)試數(shù)據(jù)后才能開工金刁。所以我上面說(shuō)“基本并行”

由于存在上面的兩個(gè)問(wèn)題,我們進(jìn)一步探索出了下面的前后端”分離“模式。

前后端“分離”

這一階段我們通過(guò)nginx將前后端部署分離尤蛮,通過(guò)mock服務(wù)器將前后端時(shí)間上的耦合給減少了媳友。
下面是我們的具體做法:

  1. 前后端約定接口
  2. 前端開發(fā)
  3. 后端開發(fā)(2和3完全并行)
  4. 前端打包,并將代碼通過(guò)ftp上傳到文件服務(wù)器产捞。
  5. 配置nginx將靜態(tài)請(qǐng)求代理到上面發(fā)布文件的文件服務(wù)器醇锚,后臺(tái)接口代理到apache web server。

nginx 配置 通常是這樣的:

server {
        listen       80;
        server_name  example.com;

        charset utf-8;

        #access_log  logs/host.access.log  main;
        
        location / {
              proxy_pass http://tomcat_pool;
              proxy_redirect off;  
              proxy_set_header HOST $host;  
              proxy_set_header X-Real-IP $remote_addr;  
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
              client_max_body_size 10m;  
              client_body_buffer_size 128k;  
              proxy_connect_timeout 90;  
              proxy_send_timeout 90;  
              proxy_read_timeout 90;  
              proxy_buffer_size 4k;  
              proxy_buffers 4 32k;  
              proxy_busy_buffers_size 64k;  
              proxy_temp_file_write_size 64k;  
        }
        
        location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css|woff|woff2|ttf|eot|map)$  {     
             root D:\Workspaces\front-end;
             index index.html;
        }

大廠的方案

這里主要介紹下阿里巴巴-釘釘?shù)那昂蠖朔蛛x解決方案坯临。阿里這樣的大廠通常有著自己內(nèi)部的成熟系統(tǒng)支撐業(yè)務(wù)焊唬,比如阿里的持續(xù)集成系統(tǒng)aone,配置服務(wù)diamond看靠,分布式服務(wù)系統(tǒng)hsf等等赶促。 小公司通常沒(méi)有經(jīng)濟(jì)實(shí)力去搭建自己的內(nèi)部系統(tǒng),我有幸接觸到了這些業(yè)界較為頂級(jí)的系統(tǒng)衷笋,對(duì)它們的運(yùn)作方式有了一定的了解芳杏。這里簡(jiǎn)單介紹下阿里巴巴-釘釘?shù)那昂蠖朔蛛x解決方案。
釘釘?shù)木唧w做法如下:

  1. 前后端約定接口
  2. 約定接口上dip(一個(gè)mock服務(wù)器)
  3. 前端開發(fā)
  4. 后端開發(fā)(2和3完全并行)
  5. 前端打包辟宗,push觸發(fā)測(cè)試環(huán)境和預(yù)發(fā)環(huán)境的云構(gòu)建爵赵,
    打tag觸發(fā)線上環(huán)境云構(gòu)建自動(dòng)發(fā)布靜態(tài)資源到cdn。
  6. 需要發(fā)布只需要負(fù)責(zé)人修改diamond 配置即可泊脐,版本控制變得簡(jiǎn)單空幻。

可以發(fā)現(xiàn)這種方式其實(shí)就是比上面多了兩個(gè)點(diǎn),一是云構(gòu)建自動(dòng)化容客,二是diamond配置秕铛。 云構(gòu)建其實(shí)屬于自動(dòng)化,我將在流程自動(dòng)化里面詳細(xì)描述缩挑,云構(gòu)建本身和
前后端分離沒(méi)有關(guān)系但两。 其實(shí)兩者的區(qū)別在于diamond配置。那么為什么配置diamond是前后端分離的工作呢供置?作為一個(gè)配置服務(wù)谨湘,diamond將專業(yè)性比較強(qiáng)的東西抽離出來(lái),將包括但不限于版本管理的內(nèi)容可以交給沒(méi)有任何前端背景的人來(lái)做芥丧。

前后端分離的理想方式

上面的這種方法是非常高效的一種方式紧阔,但仍然不是我認(rèn)為的理想的前后端分離方式。
我認(rèn)為理想的前后端分離方式是后端提供純粹的接口续担,只需要提供數(shù)據(jù)-系統(tǒng)的數(shù)據(jù)或者根據(jù)根據(jù)二方庫(kù)獲取數(shù)據(jù)返回前端擅耽,剩下的邏輯前端做。
這樣由于后端提供元數(shù)據(jù)物遇,前端只需要組合乖仇,前后端在邏輯和時(shí)間上沒(méi)有了耦合憾儒。先來(lái)一張圖來(lái)描述下:
[圖片上傳失敗...(image-171853-1512354045077)]

如圖,后端只是提供原子數(shù)據(jù)这敬,保證數(shù)據(jù)穩(wěn)定輸出就可以了航夺,事實(shí)上保證系統(tǒng)穩(wěn)定很多已經(jīng)是運(yùn)維再做的事了。前端需要根據(jù)需要進(jìn)行接口整合崔涂,服務(wù)端渲染阳掐,mock數(shù)據(jù)等工作。
那么整個(gè)流程具體是怎么工作的呢冷蚂? 可以下面這張圖:
[圖片上傳失敗...(image-3c747a-1512354045077)]

可以看出請(qǐng)求首先留到ngxin(反向代理)缭保,nginx判斷是否是靜態(tài)請(qǐng)求(html),如果是則轉(zhuǎn)發(fā)到node服務(wù)器蝙茶,node服務(wù)器會(huì)判斷是否需要進(jìn)行ssr艺骂,如果需要?jiǎng)t調(diào)用后臺(tái)接口拼裝html,將html和應(yīng)用狀態(tài)一起返回給前端隆夯。 否過(guò)不需要ssr钳恕,則直接返回靜態(tài)資源,并設(shè)置緩存信息蹄衷。
如果不是靜態(tài)資源忧额,判斷頭部信息(比如有一個(gè)自定義字段reselect: 'node' | ''),是否需要請(qǐng)求合并愧口,如果需要?jiǎng)t請(qǐng)求到node端睦番,如果不需要直接轉(zhuǎn)發(fā)給后端服務(wù)器。
ngxin配置大概是這樣:

map $reselect/node $reselect {
  default "";
  "node" "reselect/node";
}

server {
  listen                    80;
  server_name               demo.io;

  charset                   utf-8;
  autoindex                 off;

  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Ssl on;

    if ($reselect="reselect/node"){
      proxy_pass      http://node-demo.io;
      break;
    }

    proxy_pass      http://java-demo.io;
  }
  location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css|woff|woff2|ttf|eot|map)$  {     
       root D:\Workspaces\front-end;
       index index.html;
  }
}

中間層可以做的事情非常多耍属,除了我剛才說(shuō)的服務(wù)端渲染托嚣,接口組合,mock數(shù)據(jù)厚骗,還可以做很多別的事示启。我在這里不會(huì)講述ssr,接口組合领舰,mock如何具體做夫嗓,因?yàn)檫@不是本章的重點(diǎn),而且也有很多最佳實(shí)踐提揍,我要說(shuō)的是如何將這些“最佳實(shí)踐“ 組合起來(lái)啤月,如何在我們工作中將其應(yīng)用起來(lái)煮仇,并且具有良好的擴(kuò)展性劳跃。
那么中間層拿到請(qǐng)求具體流程上面已經(jīng)講過(guò)了,現(xiàn)在我們以實(shí)戰(zhàn)的角度浙垫,講下代碼該怎么組織刨仑。
但是為了方便大家理解郑诺,我簡(jiǎn)單介紹下。 首先是服務(wù)端渲染杉武,我以react+redux做服務(wù)端渲染講解辙诞,為了簡(jiǎn)單起見,沒(méi)有引入react-router轻抱,大家直接看代碼理解:

服務(wù)端:

<body>
    <div id="container"><%- html %></div>
    <script>
        window.__INITIAL_STATE__ = <%- JSON.stringify(initState) %>
    </script>
</body>
const store = buildStore(rootReducer, {});
Promise.all([
    store.dispatch(fetchUserInfo()),
    store.dispatch(fetchPosts())
])
.then(()=>{
    const html = renderToString(
        <Provider store={store}>
            <RouterContext {...renderProps}/>
        </Provider>
    )
    const initState = store.getState();
    res.render('index', html ,initState);
})

客戶端:

const initState = window.__INITIAL_STATE__;
const store = storeApp(initState);
ReactDOM.render(
    <Provider store={store}>
       <Router history={browserHistory}>
        {routesApp}
       </Router>
    </Provider>,
    document.getElementById('container'));

上面這是對(duì)服務(wù)端渲染的一個(gè)極簡(jiǎn)實(shí)現(xiàn)飞涂,那么接口聚合呢?mock呢祈搜? 加入其他功能呢较店? 是不是對(duì)我們express 本身侵入性太大。
在這里我借鑒了微服務(wù)的理念容燕,同時(shí)利用第二章節(jié)要講模塊化的思想梁呈,組織了中間層。
那么究竟我是怎么設(shè)計(jì)的呢蘸秘,請(qǐng)繼續(xù)往下看官卡。

[圖片上傳失敗...(image-120d20-1512354045077)]

我們的關(guān)注點(diǎn)就是服務(wù)集群,如果需要增加集群就直接修改配置即可醋虏。
下面基于docker + docker-compose + node + nginx 做一個(gè)中間層系統(tǒng)寻咒。

docker-compose.yml

version: '2'

services:
    

    nginx:
        build: ./nginx
        container_name: ms_nginx
        links:
            - posts
            - users
        ports:
            - "80:80"

    api:
        build: ./api
        container_name: ms_posts
        environment:
            - loglevel=none
       
        volumes:
            - "./posts:/src/app"
        working_dir: "/src/app"
        ports:
            - "8080:8080"
            - "5858:5858"
        # command: npm run start
        command: npm run start:dev

    sever-render:
        build: ./sever-render
        container_name: ms_sever-render
        
        volumes:
            - "./users:/src/app"
        working_dir: "/src/app"
        command: npm start

nginx的配置

worker_processes 4;

events { worker_connections 1024; }

http {

    server {
          listen 80;
          charset utf-8;

          location / {
            proxy_pass http://server-render:8080;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
          }

          location ~ ^/api {
            rewrite ^/api/(.*) /$1 break;
            proxy_pass http://users:8080;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
          }
    }
}

這樣我們實(shí)現(xiàn)了不同的系統(tǒng)分流,并且彼此之間接觸耦合灰粮,通過(guò)nginx 去 分發(fā)仔涩。這樣還存在一個(gè)問(wèn)題就是樣板代碼比較多,
有沒(méi)有一種方法粘舟,讓我們只關(guān)注業(yè)務(wù)本身熔脂,而不需要樣板代碼呢?大家可以關(guān)注下 faas, 這里不在贅述。
當(dāng)我們的業(yè)務(wù)逐漸復(fù)雜,系統(tǒng)逐漸增多痹栖,域名逐漸增多温峭,會(huì)發(fā)現(xiàn)很多東西都在nginx中,這時(shí)候需要將配置分開趟济,每一個(gè)子業(yè)務(wù)一個(gè)配置文件。

  1. 在nginx安裝目前下 新建 vhost 文件夾
  2. 在文件夾下創(chuàng)建 *.conf 的文件 ,如 a.example.com.conf 秽荞,命名規(guī)則大多以域名的方法來(lái)命名文件。
  3. 輯 conf 文件抚官,把我們平常放在 nginx.conf 里的 server{...} 段復(fù)制過(guò)來(lái)直接粘貼到 conf 里扬跋。
    在 nginx.conf 的 http{...} 段中加入 include E:/nginx-1.8.1/vhosts/.conf;

注:這里 include 需要用到全路徑,且文件后綴是用 conf**

這里介紹一個(gè)淘寶開源軟件tengine凌节,他是nginx的超集钦听。有很多強(qiáng)大的功能洒试,我之前的公司百世就是用的tengine

總結(jié)

本章介紹了四種前后端分離的方式和階段朴上,這里需要強(qiáng)調(diào)的是并不是越往后的方式越好垒棋,問(wèn)題的關(guān)鍵點(diǎn)還是選擇合適的
方式,根據(jù)當(dāng)前所處階段選擇合適的分離方式痪宰,提高單體和整體作戰(zhàn)效率才是明智之舉叼架。

以上內(nèi)容摘自github下自己在寫的一本書,大家可以關(guān)注一下衣撬,持續(xù)更新碉碉,地址https://github.com/azl397985856/automate-everything

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淮韭,一起剝皮案震驚了整個(gè)濱河市垢粮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌靠粪,老刑警劉巖蜡吧,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異占键,居然都是意外死亡昔善,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門畔乙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)君仆,“玉大人,你說(shuō)我怎么就攤上這事牲距》翟郏” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵牍鞠,是天一觀的道長(zhǎng)咖摹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)难述,這世上最難降的妖魔是什么萤晴? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮胁后,結(jié)果婚禮上店读,老公的妹妹穿的比我還像新娘。我一直安慰自己攀芯,他們只是感情好屯断,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般裹纳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上紧武,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天剃氧,我揣著相機(jī)與錄音,去河邊找鬼阻星。 笑死朋鞍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妥箕。 我是一名探鬼主播滥酥,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畦幢!你這毒婦竟也來(lái)了坎吻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宇葱,失蹤者是張志新(化名)和其女友劉穎瘦真,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體黍瞧,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诸尽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了印颤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您机。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖年局,靈堂內(nèi)的尸體忽然破棺而出际看,到底是詐尸還是另有隱情,我是刑警寧澤矢否,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布仿村,位于F島的核電站,受9級(jí)特大地震影響兴喂,放射性物質(zhì)發(fā)生泄漏蔼囊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一衣迷、第九天 我趴在偏房一處隱蔽的房頂上張望畏鼓。 院中可真熱鬧,春花似錦壶谒、人聲如沸云矫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)让禀。三九已至挑社,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巡揍,已是汗流浹背痛阻。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腮敌,地道東北人阱当。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像糜工,于是被迫代替她去往敵國(guó)和親弊添。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • 本文系轉(zhuǎn)載,原作者刨裆,普元免钻,敖顯奇 轉(zhuǎn)載本文需保留此處版權(quán)聲明:本文版權(quán)屬于EAII企業(yè)架構(gòu)創(chuàng)新研究院(微信號(hào):ea...
    普元云計(jì)算閱讀 4,973評(píng)論 8 96
  • 前端 前后端分離 這不是一篇純技術(shù)文章,而是一篇分享我個(gè)人在前后端分離路上收獲的點(diǎn)點(diǎn)滴滴的文章崔拥,以此來(lái)為準(zhǔn)備嘗試前...
    寒劍飄零閱讀 1,891評(píng)論 0 22
  • 前言 最近這一段時(shí)間由于Nodejs的逐漸成熟和日趨穩(wěn)定极舔,越來(lái)越多的公司中的前端團(tuán)隊(duì)開始嘗試使用Nodejs來(lái)練一...
    a3b267eac00f閱讀 3,326評(píng)論 3 26
  • 嘗試與改變 如果你沒(méi)有嘗試過(guò)前后端分離的工作流程,那么可以先試想一下這樣的流程改變:把流程從PM:“我要這個(gè)功能”...
    超人不會(huì)飛jjw閱讀 3,812評(píng)論 1 15
  • 一個(gè)學(xué)員說(shuō):“我怎么覺得越學(xué)習(xí)越痛苦呢?現(xiàn)在一有問(wèn)題慈俯,我就會(huì)想是我的問(wèn)題渤刃,是因?yàn)槲覍?duì)方才這樣的……我好痛苦√欤” 這...
    瑞敏談成長(zhǎng)閱讀 321評(píng)論 0 0