天天看點

webpack-dev-server與單頁應用路由

首先是三個使用React編寫的檔案:

index.js:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { BroswerRouter, Route } from 'react-router-dom';
import Home from './Home';
import List from './List';
class App extends Component {
    render(){
        return (
            <BroswerRouter>
                <Route path='/' component={Home}/>
                <Route path='/list' componnet={List}/>
            </BroswerRouter>
        );
    }
}
           

Home.js:

import React, { Component } from 'react';

class Home extends Component {
    render() {
        return (
            <div>
                HomePage
            </div>
        );
    }
}

export default Home;
           

List.js:

import React, { Component } from 'react';

class List extends Component {
    render() {
        return (
            <div>
                ListPage
            </div>
        );
    }
}

export default List;
           

從上面代碼可以看見,我實作了一個及其簡單的前端路由。

啟動

webpack-dev-server

的服務之後,可以通過

localhost:8080

通路到首頁,也就是

Home

子產品渲染出來的頁面:

webpack-dev-server與單頁應用路由

那麼按照預期,當我們在位址欄中輸入

localhost:8080/list

的時候便會顯示出

List

子產品所渲染的頁面,可是事與願違:

webpack-dev-server與單頁應用路由

會發現浏覽器提示找不到這個資源,原因在于,通過位址欄直接輸入位址,浏覽器會想後端也就是

webpack-dev-server

請求

list.html

這個資源,而我們并沒有,自然就會出現錯誤。

那怎麼解決這個問題呢?

需要設定在配置檔案中設定

devServer.historyApiFallback

{
   ...,
   devServer: {
       ...,
       historyApiFallback: true
   }
}
           

這個配置項的作用是,當産生任意的404響應都會被替代為

index.html

可以想見,當向

webpack-dev-server

請求

list.html

時,會産生404響應,于是就傳回了

index.html

,而目前位址欄中URL的路徑是

/list

,于是

React Router

根據我們寫的路由規則跳轉到

List

子產品。

(隻是通過在位址欄輸入URL來通路會出現這種問題,而在應用中則根本不會出現頁面的重新整理,也就不會産生向後端的請求,直接切換到List)

檢視官方文檔我們知道,這個功能的實作是使用了

connect-history-api-fallback

這個包。

而這個包還有其他的一些配置。

historyApiFallback: {
  rewrites: [
    { from: /\/soccer/, to: '/soccer.html'}
  ]
};
           

上面這樣的配置就是指,當請求路徑為

/soccer

時,就傳回

/scoccer.html

這個頁面。

而我們将

historyApiFallback

設定為

true

,則代表着請求路徑無論是什麼,都跳轉到

index.html

由前端路由決定跳轉。

historyApiFallback: {
  rewrites: [
     {
      from: /^\/libs\/.*$/,
      to: function(context) {
        return '/bower_components' + context.parsedUrl.pathname;
      }
    }
  ]
};
           

甚至還可以這麼寫,可以通過一個函數,來獲得請求路徑的相關資訊,再根據這些資訊傳回相關頁面。