reactjs重構(gòu)java vm方案

起因

目前媽媽送房采用的是經(jīng)典的MVC架構(gòu),前端模版使用vm,對于即會java又懂前端的人來說,這種方式?jīng)]有什么不好,反而開發(fā)會很快。

但是,現(xiàn)在的互聯(lián)網(wǎng)是分工協(xié)作的,我們現(xiàn)在的方式是前端開發(fā)人員負責靜態(tài)頁面樣式及交互的開發(fā),后端人員拿到靜態(tài)頁面進行數(shù)據(jù)的綁定,如果一次能搞定,那當然沒什么問題,但是一旦涉及到bug的修改,功能的調(diào)整,那就是折磨了。再加上幾經(jīng)人手,前端代碼已經(jīng)丑陋不堪。所以,我萌生出了對項目進行重構(gòu)并進行前后端分離的想法。為什么要前后端分離,這篇文章講得不錯

剛好最近學(xué)習(xí)了react,實戰(zhàn)中也嘗試了下,并且我們的這個項目特別適合做成一個SPA(single page application,單頁面應(yīng)用),所以就決定利用其進行逐步重構(gòu)。

項目路徑規(guī)劃

因為SPA的代碼最后都需要編譯打包成一個文件,所以我把我的前端工程跟java工程放在一起,方便文件直接生成到j(luò)ava工程中

project.png

webpack打包路徑設(shè)置

...
var staticPath = '../../webapp/assets'; // java工程靜態(tài)文件路徑
var viewFilename= '../../webapp/view/main/mmsf/mmsfIndex.vm' // java工程試圖文件路徑
...
// 文件打包后直接生成到j(luò)ava工程下
    entry: {
      bundle:path.resolve(__dirname, 'app/main.js')
  },
  output: {
    path: path.resolve(__dirname ,staticPath ),
    publicPath: '/',
    filename: '/js/mmsf/[name].js'
  },
...
// 圖片
  module: {
    loaders:[
      ...
      { test: /\.(png|jpg)$/, loader: 'file-loader?limit=8192&name=i/mmsf/[name].[ext]'},
    ]
  },
...
// html文件及配置文件處理
plugins: [
    ...
    new CopyWebpackPlugin([
      { from: './app/mmsfIndex.html', to: path.resolve(__dirname, viewFilename) },
      { from: './app/config.js', to: path.resolve(__dirname ,staticPath + '/js/mmsf/config.js') },
    ]),
  ]

如何方便的與后端進行接口聯(lián)調(diào)

前后端分離時,數(shù)據(jù)交換一般采取http的方式。開發(fā)時由于前后端不在同一個域,需要進行一些處理,以解決js跨越的限制。
常見的方法有:

  • 瀏覽器設(shè)置(chrome),原來確實是一個最方便的方式,在新版的chrome瀏覽器上試過,但是沒成功
  • jsonp的方式,有點麻煩,放棄
  • 后端設(shè)置http頭(Access-Allow-Control-Origin),本公司后端不會,懶得去求他們,還是自己想辦法吧。
  • ngix,最后決定用這個

ngix配置

如果我將ngix配置成如下所示:

#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  logs/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        #access_log  logs/host.access.log  main;
        location /api {
                  proxy_connect_timeout   3;  
            proxy_send_timeout      30;  
            proxy_read_timeout      30;
                  #rewrite (.*) site-web-personal/$1 permanent;
                  proxy_set_header   Host    $host;
            proxy_set_header   Remote_Addr    $remote_addr;
            proxy_set_header   X-Real-IP    $remote_addr;
            proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_pass http://192.168.10.171:8282/api;
        }       
        location / {
                  proxy_connect_timeout   3;  
            proxy_send_timeout      30;  
            proxy_read_timeout      30;
                  #rewrite (.*) site-web-personal/$1 permanent;
                  proxy_set_header   Host    $host;
            proxy_set_header   Remote_Addr    $remote_addr;
            proxy_set_header   X-Real-IP    $remote_addr;
            proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_pass http://192.168.10.169:8888/;  
        }       
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

這樣當我訪問http://localhost/*時會轉(zhuǎn)發(fā)到我本地起的前端調(diào)試web服務(wù),當我訪問http://localhost/api時會轉(zhuǎn)發(fā)到后端接口服務(wù)。

但是,我們的后端一開始并沒有統(tǒng)一規(guī)劃,所以也就沒有區(qū)別接口的url地址和訪問頁面的url地址。

最后想到的辦法是,利用eclipse->server可以給工程配置一個統(tǒng)一的url根目錄來解決:

Paste_Image.png

然后ngix配置改成:

...
location /house-web-web {
    proxy_connect_timeout   3;  
    proxy_send_timeout      30;  
    proxy_read_timeout      30;
    #rewrite (.*) site-web-personal/$1 permanent;
    proxy_set_header   Host    $host;
    proxy_set_header   Remote_Addr    $remote_addr;
    proxy_set_header   X-Real-IP    $remote_addr;
    proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.10.171:8282/house-web-web;
}       
...

此時,訪問http://localhost/house-web-web的請求會轉(zhuǎn)發(fā)給后臺接口,當然前端也需要進行配置:

// 上線需要改這兩個參數(shù)
window.debug = true;

// baseurl
window.apiBase = window.debug ? '/house-web-web' : ''

// 前端路由
window.url = {
    'discoverIndex' : '/discover/index.htm', // 發(fā)現(xiàn)首頁
    'discoverDetail' :  '/discover/detail.htm', //  發(fā)現(xiàn)詳情
    'searchIndex' : '/search/index.htm', // 搜索首頁
    'searchDetail' : '/search/detail.htm' // 搜索詳情
}

// api
 window.api = {
    'discoverIndex': window.apiBase + '/discover/getIndexJson.htm', //發(fā)現(xiàn)首頁
    'discoverDetail': window.apiBase + '/discover/detailPage.htm', // 發(fā)現(xiàn)詳情
 }

這樣,此時在瀏覽器中訪問http://localhost/#/discover/index.htm則會到本地前端調(diào)試的服務(wù),在該頁面中訪問http://localhost/house-web-web/discover/getIndexJson.htm則會訪問后臺的接口

前端路由

react的前端路由有兩種方式hashHistorybrowserHistory
由于開發(fā)時webpack-dev-server啟動的服務(wù)不支持browserHistory,所以開發(fā)時用hashHistory,生產(chǎn)上用browserHistory

  <Router history={window.debug ? hashHistory : browserHistory}>
            <Route path="/">
                 <Route path={window.url.discoverIndex} component={DiscoverList}/>
                 <Route path={window.url.discoverDetail} component={DiscoverDetail}/>
                 <Route path={window.url.searchIndex} component={SearchIndex}/>
                  <Route path={window.url.searchDetail} component={SearchDetail}/>
            </Route>
          </Router>

圖片處理

圖片有點不好弄,因為react中引入圖片是相對于工程的路徑,而到瀏覽器中訪問時是相對于java靜態(tài)文件目錄的路徑,所以這里的處理方式是:

  • 對于小圖片,統(tǒng)一使用base64格式,這樣不僅優(yōu)化了訪問速度,也解決了圖片路徑問題
  • 對于大圖片,保證前端圖片路徑與java靜態(tài)文件圖片路徑一致,且圖片的訪問路徑用絕對路徑

例子:

background-image: url('/assets/i/mmsf/search-banner.png')

為了確保webpack對圖片進行處理,在react中對用到的圖片均import

// 這里引入只是為了使webpack將圖片拷貝到正確的路徑
import bannerElderly from '../../assets/i/mmsf/discover-detail-banner.png'
import iconShare from '../../assets/i/mmsf/icon-share.png'

后端url處理

由于生產(chǎn)上還是需要使用真實路徑,所以需要后端進行配合,所有用前端路由的url地址均渲染mmsfIndex.vm

Paste_Image.png

總結(jié)

總的下來,實現(xiàn)這一方案,用了很多非主流的方法,也讓我知道了做技術(shù)只要掌握了原理,是可以根據(jù)自己的需要進行變通的。接下來就是逐步把原來的頁面都遷移到新項目中來了,可以跟原來丑陋的代碼說拜拜咯。
代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容