關於React版本升級可行性的考察


項目背景:項目初期為了兼容IE8,采用react版本較低(0.14),本文針對兼容性要求調整到IE9及以上,后對React升級可行性的考察

 

一、React瀏覽器支持

官方說明

https://react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/react-dom.html#browser-support

1.瀏覽器支持

React 支持所有的現代瀏覽器,包括 IE9 及以上版本,但是需要為舊版瀏覽器比如 IE9 和 IE10 引入相關的 polyfills 依賴

注意:

我們不支持那些不兼容 ES5 方法的舊版瀏覽器(IE8基本不支持ES5),但如果你的應用包含了 polyfill,例如 es5-shim 和 es5-sham 你可能會發現你的應用仍然可以在這些瀏覽器中正常運行。但是如果你選擇這種方法,你便需要孤軍奮戰了。

https://react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/javascript-environment-requirements.html

JavaScript 環境要求

React 16 依賴集合類型 Map 和 Set 。如果你要支持無法原生提供這些能力(例如 IE < 11)或實現不規范(例如 IE 11)的舊瀏覽器與設備,考慮在你的應用庫中包含一個全局的 polyfill ,例如 core-js 或 babel-polyfill 。

React 同時還依賴於 requestAnimationFrame(甚至包括測試環境)。 你可以使用 raf 的 package 增添 requestAnimationFrame 的 shim

 

參考:

ES6 + Webpack + React + Babel 如何在低版本瀏覽器上愉快的玩耍(下) https://segmentfault.com/a/1190000006930013

ES6 + Webpack + React + Babel 如何在低版本瀏覽器上愉快的玩耍(上) https://segmentfault.com/a/1190000006929961

 

二、升級環境准備

1.babel-loader使用7.0版本

2.安裝npm-check-updates 模塊升級插件

npm install -g npm-check-updates // 或者 cnpm install -g npm-check-updates
// 查看所有更新
ncu
// 更新package.json文件
ncu –u
// 安裝更新
npm install

npm update,只能按照package.json中標注的版本號進行更新,升級后不會修改package.json中的版本號,需要自己手動修改,比較麻煩。

npm-check-updates 升級插件升級后會自動修改package.json里的版本號,簡單方便。

官網:https://www.npmjs.com/package/npm-check-updates

3.IE低版本支持相關包去掉

export-from-ie8

es3ify-loader

三、升級修改

1.webpack升級修改

官方文檔:

https://www.webpackjs.com/guides/migrating/#resolve-root-resolve-fallback-resolve-modulesdirectories

主要內容:

(1)    安裝webpack-cli

(2)    module.loaders 改為 module.rules

(3)    webpack v4 中extract-text-webpack-plugin 改為mini-css-extract-plugin instead

2.react升級變更

(1) React. PropTypes  改為 import PropTypes from 'prop-types';

量很大

(2) componentWillReceiveProps 更名

報錯內容

Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.

修改原則

  1. 如果你需要執行副作用(例如,數據提取或動畫)以響應 props 中的更改,請改用 componentDidUpdate 生命周期。
  2. 如果你使用 componentWillReceiveProps 僅在 prop 更改時重新計算某些數據,請使用 memoization helper 代替。
  3. 如果你使用 componentWillReceiveProps 是為了在 prop 更改時“重置”某些 state,請考慮使組件完全受控或使用 key 使組件完全不受控 代替。

說明

有使用該方法處理邏輯的地方,需要詳細處理方案

可以使用 rename-unsafe-lifecycles自動更新組件。具體修改方式見官網說明:

https://react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/react-component.html#unsafe_componentwillreceiveprops

(3) componentWillMount更名

報錯內容

react-dom.development.js:11494 Warning: componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.

修改原則

  1. 使用 constructor() 來初始化 state。
  2. 避免在此方法中引入任何副作用或訂閱。如遇此種情況,請改用 componentDidMount()。

現狀

       有接口調用獲取數據等處理

具體修改方式見官網說明:

https://react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/react-component.html#unsafe_componentwillmount

(4) 自定義的事件被忽略

Warning: Unknown event handler property `onInputChange`. It will be ignored.

(5) 不要將組件的屬性, 傳給DOM節點

Warning: React does not recognize the `errorInfos` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `errorinfos` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

本條改完,(4)中大部分可同時消除

3.antd升級

(1) 全局公共樣式

比如,下列樣式去掉

article, aside, blockquote, body, button, code, dd, details, div, dl, dt,
fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, 
header, hgroup, hr, input, legend, li, menu, nav, ol, p, pre, section, td, textarea, th, ul{
    margin: 0;
    padding: 0;
}

4.參考文章

react技術棧升級的過程https://segmentfault.com/a/1190000016357380

第一階段:

react15+react-router2+redux3+webpack1

升級到

react16+react-router3+redux4+webpack4

1.react15升級到16 遇到的坑:

在react16中去除contextTypes ,導致this.context.router.push('/*') 需要替換成this.props.router.push('/*') 。

2.webpack1升級到4遇到的坑:

(1)webpack4 中建議使用min-css-extract-plugin 分離css,sass等文件,取代插件extract-text-webpack-plugin 效率更高

(2)html-webpack-plugin 要升級到2.22.0及以上

(3)webpack4將webpack.optimize.CommonsChunkPlugin移除,使用和entry平級的optimization里的屬性splitChunks來把提取出來的樣式和common.js會自動添加進發布模式的html文件中,原來的html文件中沒有,前提必須是mode=prodution 才生效。

(4)webpack4中把內置的webpack.DefinePlugin({'process.env':{NODE_ENV:JSON.stringify("development")}})去掉,添加了和entry平級的mode屬性,來區分環境。mode的value有none/development/production 這3中屬性,若要在系統中使用,則用"process.env.NODE_ENV"變量來獲取,比較奇葩。

(5)entry的路徑原來path.resolve(path.resolve(path.resolve(path.resolve(__dirname)),'src'),'app')應替換為相對路徑的'./src/App.jsx'。

(6)output的路徑原來的path.resolve(path.resolve(__dirname),"dist")應替換為path.join(path.join(__dirname),"dist")。

四、     兼容

1.IE11

a) babel-polyfill

安裝

npm i babel-polyfill --save-dev

引用

在./src/index.js中加入

import 'babel-polyfill';

webpack配置

entry: {

        app: [

            'babel-polyfill',

            path.join(__dirname, '../src/index.js')

        ]

    },

2.IE9

特別注意文件上傳等功能

 

React16和Antd如何在IE9環境下忍辱偷生 https://blog.csdn.net/Napoleonxxx/article/details/80426678

IE9引發的血案-如何處理webpack打包后體積依然過大的css文件 https://blog.csdn.net/napoleonxxx/article/details/80292006

IE10、IE9在線兼容工具  https://www.browserling.com/

 

五、項目關聯

公共組件需要升級版本

1.webpack4中的mode

公共組件始終使用production

 

六、組件文檔

1.react-docgen

基礎庫,將組件注釋轉化為json數據  https://github.com/reactjs/react-docgen

2.react-styleguidist

帶樣式和界面的文檔工具  https://github.com/styleguidist/react-styleguidist

七、組件開發測試工具

1.Carte Blanche

只有beta版本,2016年后停止維護

官網:https://github.com/carteb/carte-blanche

2.react-storybook

官網:https://storybook.js.org/docs/guides/guide-react/

https://storybook.js.org/docs/basics/introduction/

b) 添加依賴項

npm install @storybook/react --save-dev

注意:安裝前需要確保項目包含reactreact-dom@babel/core,和babel-loader依賴,如果項目中沒有,需要額外安裝

c) 添加npm腳本

將以下NPM腳本添加到package.json,以便啟動storybook:

{
"scripts": {
      "storybook": "start-storybook"
   }
}

d) 配置文件

創建一個.storybook/config.js(windows下輸入”.storybook.”創建名為.storybook的目錄)包含以下內容的文件:

import { configure } from '@storybook/react';

configure(require.context('../src', true, /\.stories\.js$/), module);

這將加載../src目錄下與模式匹配的所有故事*.stories.js。我們建議您將故事與源文件放在同一位置,但是您可以將它們放置在任意位置。

e) 寫用戶故事

創建./src/index.stories.js文件,並寫下您的第一個故事:

import React from 'react';
import { Button } from '@storybook/react/demo';

export default { title: 'Button' };

export const withText = () => <Button>Hello Button</Button>;
export const withEmoji = () => (
  <Button><span role="img" aria-label="so cool">aaaaa</span></Button>
);

f) 運行

執行以下命令啟動storybook

npm run storybook

g) 問題

組件中文件引入路徑使用webpack中alias的無法識別

八、附錄

1. 組件化思考

前端 UI組件化的一些思考https://zhuanlan.zhihu.com/p/25820838

2. ucWeb中package.json

{
  "name": "glodon-jf",
  "version": "1.0.0",
  "description": "glodon-jf",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev-build": "webpack --config build/webpack.dev.config.js",
    "start": "webpack-dev-server --config build/webpack.dev.config.js --color --progress --hot",
    "test-build": "webpack --config build/webpack.test.config.js --progress",
    "release-build": "webpack --config build/webpack.release.config.js --progress",
    "product-build": "webpack --config build/webpack.product.config.js --progress"
  },
  "keywords": [
    "react",
    "react-router",
    "webpack",
    "es6",
    "react-family",
    "ie8"
  ],
  "browserslist": [
    "last 2 versions",
    "> 0.01%",
    "ie > 7"
  ],
  "author": "brickspert",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.6.1",
    "babel-core": "^6.26.3",
    "babel-eslint": "^10.0.3",
    "babel-loader": "^7.0.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "bower-webpack-plugin": "^0.1.9",
    "bundle-loader": "^0.5.6",
    "clean-webpack-plugin": "^3.0.0",
    "console-polyfill": "^0.3.0",
    "css-loader": "^3.2.0",
    "eslint": "^6.4.0",
    "eslint-loader": "^3.0.0",
    "eslint-plugin-react": "^7.14.3",
    "eventsource-polyfill": "^0.9.6",
    "extract-text-webpack-plugin": "3.0.2",
    "fetch-ie8": "^1.5.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "html-withimg-loader": "^0.1.16",
    "less": "^3.10.3",
    "less-loader": "^5.0.0",
    "node-sass": "^4.12.0",
    "open-browser-webpack-plugin": "^0.0.5",
    "postcss-cssnext": "^3.1.0",
    "postcss-loader": "^3.0.0",
    "react-hot-loader": "^4.12.13",
    "redux-devtools": "^3.5.0",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.3.0",
    "sass-loader": "^8.0.0",
    "style-loader": "^1.0.0",
    "styled-jsx": "^3.2.2",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^2.1.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.8",
    "webpack-dev-server": "^3.8.0",
    "webpack-merge": "^4.2.2"
  },

  "dependencies": {
    "antd": "3.23.2",
    "axios": "^0.19.0",
    "babel-plugin-import": "^1.12.1",
    "es3ify-webpack-plugin": "^0.1.0",
    "http-proxy-middleware": "^0.20.0",
    "js-cookie": "^2.2.1",
    "moment": "*",
    "prop-types": "^15.7.2",
    "react": "16.9.0",
    "react-dom": "16.x.x",
    "react-redux": "^7.1.1",
    "react-router-dom": "^5.0.1",
    "redux": "*"
  }
}

3. commonUI中package.json

{
  "name": "gcf-common-component",
  "version": "1.1.0",
  "description": "A common component library of gcf",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build-func": "webpack --config build/webpack.func.config.js",
    "build-comp": "webpack --config build/webpack.comp.config.js"
  },
  "author": "zhangs",
  "license": "ISC",
  "dependencies": {},
  "peerDependencies": {
    "react": "16.9.0",
    "react-dom": "16.x.x"
  },
  "devDependencies": {
    "antd": "3.23.2",
    "assets-webpack-plugin": "^3.9.10",
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3",
    "babel-eslint": "^10.0.3",
    "babel-loader": "7.0.0",
    "babel-plugin-import": "^1.12.1",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "^3.2.0",
    "eslint": "^6.4.0",
    "glob": "^7.1.4",
    "mini-css-extract-plugin": "^0.8.0",
    "style-loader": "^1.0.0",
    "styled-jsx": "^3.2.2",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^2.1.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.8"
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM