1. 程式人生 > >徹底解決前端開發在前後端分離過程中的跨域問題

徹底解決前端開發在前後端分離過程中的跨域問題

現在的web工程越來也大,傳統的開發模式已經顯得捉襟見肘了,不僅開發人員在開發過程中很痛苦,後期維護的人員也更痛苦。怎麼解決呢?前後端分離。在前後端開發過程中一直會伴隨我們的問題就是跨域問題,因為這時候前端和後端的程式碼是在不同機器上執行的,兩個地址不在一個域名下,這個時候前端指令碼在進行ajax訪問的時候瀏覽器就會報跨域相關的錯誤。這個時候怎樣解決呢?
最簡單的做法是通過設定瀏覽器允許瀏覽器跨域請求。但是今天我們這裡不講這種方式,有興趣的可以在度娘上搜“chrome瀏覽器跨域設定”教程非常詳細。這個方式是有侷限性的,因為不同瀏覽器的跨域設定不相同,甚至相同瀏覽器不同版本的設定都可能不同,我自己現在都只知道chrome的跨域設定,IE和firefox的看過,但是記不住了,總之,設定瀏覽器跨域,只適合臨時用一下。
下面我們介紹一種測地解決前端跨域訪問的方式,本地伺服器請求轉發的方式。
實現的過程就是在我們前端的本地起一個服務,然後我們前端的所有ajax訪問首選訪問我們本地的服務,本地的服務不會對來的請求做加工處理,只是將請求轉發到我們真實的後臺服務上去。我們本地的服務其實你就是一箇中轉站。這種解決方案就是利用後端之間訪問是不存在跨域的問題。
現在nodejs火的一塌糊塗,所以對於前端人員來說搭建一個本地轉發服務是相當簡單的。下面我們就利nodejs+express+http-proxy-middleware構建一個轉發服務:
1,安裝 nodejs
2,新建一個專案資料夾project
3,在該資料夾中開啟dos視窗,安裝express和http-proxy-middleware

 npm install express http-proxy-middleware --save-dev

4,新建server.js和public資料夾(用來存我們的前端專案)

var express = require('express');
var proxyMiddleWare = require("http-proxy-middleware");
var proxyPath = "http://xxx.xx.xx.xx:port";//目標後端服務地址
var proxyOption ={target:proxyPath,changeOrigoin:false}
var app = express();
    app.use
(express.static("./public"))//這段程式的作用是將我們的前端專案設定成靜態資源這樣我們在瀏覽器中就可以直接通過http://127.0.0.1:xxxx/xxx(所在頁面的目錄層級)訪問我們的頁面,做到邊開發邊除錯. app.use("/login",proxyMiddleWare(proxyOption))//這裡要注意"/login" 是匹配的路由,它會將匹配的路由進行轉發,沒匹配到的就不會轉發。 app.listen(8080);

5,運server.js 在server.js所在的目錄開啟dos視窗 run server.js.
就這麼簡單,一個簡單的前後端分離的可以跨域的前端開發環境就搭建起來了我們只需要將我們的專案建在public資料夾中就行了。然後proxyPath配置成我們要訪問的真實後端服務地址就行了。
現在流行的前端框架vue其實他的webpack配置檔案/build/dev-server.js已經實現了請求代理:

require('./check-versions')()

var config = require('../config')
if (!process.env.NODE_ENV) {
  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}

var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')

// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable

var app = express()
var compiler = webpack(webpackConfig)

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  quiet: true
})

var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = { target: options }
  }
  app.use(proxyMiddleware(options.filter || context, options)) //代理請求
})

// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)

// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))//這是靜態資源

var uri = 'http://localhost:' + port

devMiddleware.waitUntilValid(function () {
  console.log('> Listening at ' + uri + '\n')
})

module.exports = app.listen(port, function (err) {
  if (err) {
    console.log(err)
    return
  }

  // when env is testing, don't need open it
  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
    opn(uri)
  }
})

在進行vue前端開發中我們在npm run dev 後其實就是相當在本地啟動了一個靜態伺服器。
這樣我們就可以跨域請求了。