基於webpack4搭建的react專案框架

cacao111發表於2018-07-10

介紹

框架介紹,使用webpac構建的react單頁面應用,整合antd。使用webpack-dev-server啟動本地服務,加入熱更新便於開發除錯。使用bundle-loader進行程式碼切割懶載入
手動搭建,不使用cli,大量註釋適合初學者對webpack的理解學習,對react專案的深入瞭解

啟動







git clone https://gitee.com/wjj0720/react-demo.git







cd react-demo







yarn







yarn start



打包

yarn build

目錄結構







+node_modules







-src







+asset







+Layout







+pages







+redux







+utils







+app.js







+index.html







+index.js







.babelrc







package.json







postcss.config.js







webpack.config.js //webpack 配置



bundle-loader 懶載入使用







// webpack.config.js 配置







module: {







rules: [







{







test: /.bundle.js$/,







use: {







loader: `bundle-loader`,







options: {







name: `[name]`,







lazy: true







}







}







}







]







}







// 頁面引入元件







import Home from "bundle-loader?lazy&name=[name]!./Home";













// 元件使用 因為元件懶載入 是通過非同步的形式引入 所以不能再頁面直接以標籤的形式使用 需要做使用封裝







import React, {Component} from `react`







import { withRouter } from `react-router-dom`







class LazyLoad extends Component {







state = {







LoadOver: null







}







componentWillMount() {







this.props.Loading(c => {







this.setState({







LoadOver: withRouter(c.default)







})







})







}













render() {







let {LoadOver} = this.state;







return (







LoadOver ? <LoadOver/> : <div>載入動畫</div>







)







}







}







export default LazyLoad













// 通過封裝的懶載入元件過度 增加載入動畫







<LazyLoad Loading={Home} />



路由配置

框架按照模組劃分,pages資料夾下具有route.js 即為一個模組







// 通過require.context讀取模組下路由檔案







const files = require.context(`./pages`, true, /route.js$/)







let routers = files.keys().reduce((routers, route) => {







let router = files(route).default







return routers.concat(router)







}, [])













// 模組路由檔案格式







import User from "bundle-loader?lazy&name=[name]!./User";







export default [







{







path: `/user`,







component: User







},







{







path: `/user/:id`,







component: User







}







]



redux 使用介紹







// ---------建立 --------







// 為了不免action、reducer 在不同檔案 來回切換 物件的形式建立













// createReducer 將書寫格式建立成rudex認識的reducer







export function createReducer({state: initState, reducer}) {







return (state = initState, action) => {







return reducer.hasOwnProperty(action.type) ? reducer[action.type](state, action) : state







}







}













// 建立頁面級別的store







const User_Info_fetch_Memo = `User_Info_fetch_Memo`







const store = {







// 初始化資料







state: {







memo: 9,







test: 0







},







action: {







async fetchMemo (params) {







return {







type: User_Info_fetch_Memo,







callAPI: {url: `http://stage-mapi.yimifudao.com/statistics/cc/kpi`, params, config: {}},







payload: params







}







},







...







},







reducer: {







[User_Info_fetch_Memo] (prevState = {}, {payload}) {







console.log(`reducer--->`,payload)







return {







...prevState,







memo: payload.memo







}







},







...







}







}













export default createReducer(store)







export const action = store.action













// 最終在模組界別組合 [當然模組也有公共的資料(見Home模組下的demo寫法)]







import {combineReducers} from `redux`







import info from `./Info/store`







export default combineReducers({







info,







。。。







})













// 最終rudex資料夾下的store.js 會去取所有模組下的store.js 組成一個大的store也就是我們最終倉庫













// --------使用------







// 首先在app.js中將store和app關聯







import { createStore } from `redux`







import { Provider } from `react-redux`







// reducer即我們最終







import reducer from `./redux/store.js`







// 使用者非同步action的中介軟體







import middleware from `./utils/middleware.js`







let store = createStore(reducer, middleware)







<Provider store={store}>







。。。







</Provider>



















// 然後元件呼叫 只需要在元件匯出時候 使用connent連結即可







import React, {Component} from `react`







import {connect} from `react-redux`







// 從頁面級別的store中匯出action







import {action} from `./store`













class Demo extends Component {







const handle = () => {







// 觸發action







this.props.dispatch(action.fetchMemo({}))







}







render () {







console.log(this.props.test)







return <div onClick={this.handle}>ss</div>







}







}







export default connect(state => ({







test: state.user.memo.test







}) )(demo)









關於redux中介軟體







// 與其說redux中介軟體不如說action中介軟體







// 中介軟體執行時機 即每個action觸發之前執行













//







import { applyMiddleware } from `redux`







import fetchProxy from `./fetchProxy`;













// 中介軟體 是三個巢狀的函式 第一個入參為整個store 第二個為store.dispatch 第三個為本次觸發的action







// 簡單封裝的中介軟體 沒有對請求失敗做過多處理 目的在與項錯誤處理機制給到頁面處理







const middleware = ({getState}) => next => async action => {







// 此時的aciton還沒有被執行







const {type, callAPI, payload} = await action







// 沒有非同步請求直接返回action







if (!callAPI) return next({type, payload})







// 請求資料







const res = await fetchProxy(callAPI)







// 請求資料失敗 提示







if (res.status !== 200) return console.log(`網路錯誤!`)







// 請求成功 返回data







return next({type, payload: res.data})







}







export default applyMiddleware(middleware)



原文釋出時間:2018年06月30日

作者:前端棧開發

本文來源:CSDN  如需轉載請聯絡原作者


相關文章