react+mobx實現兼容IE9的CMS系統過程當中的經驗總結

前言

由於想要嘗試用 mobx 而且也想本身試着搭建腳手架,因此在開發此項目時並無使用比較成熟的腳手架如:ant-design-pro,因此在開發過程當中遇到了不少問題,在此記錄,但願能幫助到其它開發者。css

框架

通過此項目我將這個項目的腳手架開源,歡迎你們使用和提建議。
react-mobx-react-router-boilerplatehtml

技術選型

  • create-react-app@2.1.1
  • react@16.6.0
  • mobx@4.5.2(5.x版本不支持IE9)
  • mobx-react@5.3.6
  • react-router-dom@4.3.1
  • antd由@2.x到@3.18.1
  • superagent@4.0.0-beta.5(axios最新版本不支持IE9)

遇到的問題

瀏覽器兼容性

  • IE9 不支持 flex 佈局
  • create-react-app 提供的 react-app-polyfill 只是對某些 ES6 的 API 作了兼容,因此用 @babel/polyfill 替代了 react-app-polyfill
  • dev 環境不支持 IE9:在 IE9 上打開 dev 環境發現了不少問題,不只有 webpack-dev-server 存在的兼容性問題,還有一些其它第三方庫存在的兼容性問題,主要有如下問題(由於問題太多因此最後我放棄了IE9下的dev環境):
    • 首先是 bundle.js 文件裏報 const map 未定義是由於 webpack-dev-server 從 2.7.1 後不支持 IE9
    • 若是是 vendor.js 文件裏報 setPrototypeOf 未定義是由於 create-react-app 引入的 react-dev-utils/webpackHotDevClient 文件裏面有一個 chalk 的包使用了這個 ES6 的方法,而 @babel/polyfill 的編譯是基於__proto__,而 IE9 並不支持__proto__,所 以@babel/polyfill 無效
  • 調試的時候保證是 IE9 的標準模式
  • 線上的項目沒法在 IE9 上打開的緣由:IE9 默認採用的文檔模式是 IE7。解決方案:加入<meta http-equiv="X-UA-Compatible" content="IE=edge">,注意順序:

    The X-UA-Compatible header is not case sensitive; however, it must appear in the header of the webpage (the HEAD section) before all other elements except for the title element and other meta elements.react

  • IE9 Spin 元素包裹的內容沒法點擊 緣由:Spin 設置的 css 屬性 pointer-events 不兼容IE9。解決方案:升級 antd
  • IE9 設置 img height 爲百分比並不能像chrome瀏覽器裏同樣按比例縮放,只能設置 width
  • IE9 上 css 樣式沒有瀏覽器前綴致使樣式錯誤,緣由 autoprefixer 對應的 browserslist 沒寫對沒能將 IE9 包含進去
  • 默認使用 webkit 內核:<meta name="renderer" content="webkit" />

mobx

  • mobx-react observer 對傳入的props作了淺比較,因此傳遞相同的值會有問題
  • 爲了在生產環境不把 mock 文件打包進來,我是這麼作的
    • 首先添加了一個 npm script: "start:no-mock": "cross-env REACT_APP_MOCK=none npm start"
    • 其次在 index.js 文件裏面:
    if (process.env.NODE_ENV === 'development' && process.env.REACT_APP_MOCK !== 'none') {
      import('../mock')
    }
    複製代碼
  • HMR 致使修改以後 mobx 的數據都變成初始數據了:react-hot-loader 遇到更新的時候會 rerender 組件,以前的 hot 掛載在 App 上,App 裏面用了 provider 去傳遞數據,每次 rerender 都會從新傳數據,因此數據就變成初始的了,hot 方法包裹的組件應該不包括它

http

  • ajax 沒法截獲 302 狀態碼
  • 本地開發時的 cookie 校驗問題:由於登陸是用的服務器上現成的登陸頁面,權限校驗是經過 cookie 來實現的,因此我須要設法讓個人本地域名下也能保存到後臺返回的 cookie,這樣本地開發時才能校驗成功,因此我經過 http-proxy-middle 設置了 /login 頁面的代理,代理到測試服務器上的登陸頁面,這樣登陸成功後我本地域名下也有了 cookie。
    const proxy = require('http-proxy-middleware')
    
        module.exports = function(app) {
          // 代理api請求
          app.use(
            proxy('/api', {
              target: process.env.REACT_APP_DEV_SERVER,
              pathRewrite: { '^/api': '' },
              changeOrigin: true,
            })
          )
          // 代理登陸、退出頁面
          app.use(
            proxy([process.env.REACT_APP_LOGIN_URL, '/public', '/auth/check', '/logout'], {
              target: process.env.REACT_APP_DEV_SERVER,
            })
          )
        }
    複製代碼

antd

  • treeselect組件,指定 disableCheckbox 會有 bug,詳情見github.com/ant-design/…,解決方案:給須要禁用複選框的元素添加 class,而後用 css 來實現禁用效果

git

  • git revert 後合併致使代碼丟失的問題,這個我專門寫了一篇博客

webpack

  • 每次修改一個 chunk 若是和第三方庫有關的代碼,則會致使不少 chunk 打包的 hash 變化,這個是正常的,由於 webpack 的 splickChunk 結合 import() 的緣由致使的
  • hard-source-webpack-plugin 能夠提升再次編譯速度

其它

  • textarea 裏面輸入帶換行的文本在詳情頁裏面沒有體現出來,解決方案:一、替換'/r/n'爲<br/>,二、定義white-space: pre-wrap
  • 生產環境下出現樣式覆蓋的問題,由於動態加載致使,好比先訪問 a 頁面,加載 a.css,而後訪問 b 頁面,引入 b.css,b.css 後引入因此若是有重名的 class,就會覆蓋 a.css 裏面的樣式,解決方案經過修改 css 來解決
  • 新的頁面會記錄以前頁面的滾動位置,由於滾動的樣式定義在 route 外,因此 route 對應的組件即使卸載頁不會影響外面的滾動條的位置,解決方案:react-router.docschina.org/web/guides/…
  • hash 路由沒法用 hash 錨點,能夠用 scrollIntoView 方法,可是在某些場景下會有問題,好比你設置了 header,你想讓要顯示的元素在 header 下方顯示,可是因爲 scrollIntoView 是根據瀏覽器視窗去滾動的因此它會忽略 header 這時你滾動的元素的一部分就可能被 header 遮擋,因此我本身封裝了一個 react 組件react-anchor-without-hasn,能夠定義滾動的 offset
  • 搜索優化:通常咱們對於用戶輸入搜索都會採用 debounce 進行優化減小服務端請求,可是假如用戶輸入的比較慢兩次輸入的字符在你設置的延遲時間以外,好比延遲間隔 500 你輸入第一個字符 'k' 後隔了 500 再輸入 'w' 這時會發送兩條請求,咱們知道 http 請求的響應時長不是固定的,若是第一次請求的響應時長比第二次請求的響應時長長就有可能發送第一次搜索結果覆蓋第二次的搜索結果,這樣就會給用戶形成困擾。解決方法就是設置一個數組,存儲每次請求的 cancel 函數(這塊須要根據本身採用的 ajax 庫),在每次請求以前先判斷數組是否爲空,若是不爲空則先依次調用數組裏面的 cancel 方法終止以前的請求,再發送請求
相關文章
相關標籤/搜索