從 React 到 Preact 遷移指南

作者 | 劉凱

專註 Web 前端技術,崇尚一目了然的設計。

為什麼選 Preact

Fast 3kB alternative to React with the same ES6 API.

React 的 3kb 輕量化方案,擁有同樣的 ES6 API

  • 體積小。React v15.6.1 有 49.8kb,最新的 React v16.0 小了很多,有 34.8kb。而 Preact 官網聲稱只有 3kb,實測 v8.2.5 版本有4.1kb,但這已經比 React 小了至少 30kb,在移動端網頁開發中佔了不少優勢。
  • 性能高。是最快的虛擬 DOM 框架之一,具體可以查看 Results for js web frameworks benchmark – round 6。
  • 生態好。官方提供 preact-compat,可以無縫使用 React 生態系統中的各類組件。
  • 更方便。相比 React,Preact 添加了幾個更為便捷的特性,包括可以直接使用標準的 HTML 屬性(如 classfor),propsstatecontext 作為參數傳進了 render() 等。

除了 Preact,React-like 中比較出名的還有 Inferno,它大小在9kb左右。它和前面兩者相比,還加了一個新的特性就是無狀態組件(stateless components)也支持生命周期事件,從而可以減少 class 的使用,做到更加輕量。性能比 React 和 Preact 都要好,其它方面和 Preact 差不多。但是有個問題是 Inferno 用了一些相對較新的特性,比如 PromiseMapSetWeakMap 等,所以瀏覽器兼容性比 Preact 要差點。

遷移指南

官方文檔

  • 用 Preact 替換 React

官方文檔提供了2種途徑,都是在原項目上把 React 替換成 Preact,我們為了保持項目乾淨採用創建新項目的方式來做。

準備

1. 創建項目

Preact 官方提供了2種方式來創建項目:

  1. preact-cli
  2. Preact Boilerplate / Starter Kit

官方推薦用方式一,但我們為了方便定製採用了方式二來創建,去掉了 preact-compat 等暫時沒用到庫。

2. 複製代碼

創建完項目,把原項目中 src 目錄下的代碼(index.js、組件等)拷貝到新項目src 目錄下就可以了。

這樣準備工作就做好了,當然現在項目還是跑不起來,會各種報錯,接下來我們需要修改代碼。

修改代碼

react

react 替換成 preact

import React from react;n// =>nimport { h } from preact;n

Preact 的 h() 相當於 React 中的 createElement(),可以閱讀 WTF is JSX 了解更多。

import { render } from react-dom;n// =>nimport { render } from preact;nimport { Component } from react;n// =>nimport { Component } from preact;n

redux

直接替換成 preact-redux 就可以,其它都一樣:

import { Provider } from react-redux;n// =>nimport { Provider } from preact-redux;n

router

我們原項目採用的是 React Router v3,Preact 官方提供了 preact-router,它並不是 React Router 的 preact 兼容版本,而是另一種輕量級的路由方案。如果你還是想用 React Router,可以它的 v4 版本,因為 v4 版本可以直接和 Preact 一起使用,而不需要 preact-compat 來做兼容。

所以如果你有比較複雜的需求的話,比如路由嵌套、視圖合成等等,可以考慮用 React Router v4;如果只是想要比較基本的路由需求的話,那就用 preact-router 好了。我們項目路由需求不複雜,為了追求輕量,就採用了 preact-router,畢竟 React Router 比 preact-router 大了很多。

因為不兼容,所以改動也是比較大的:

import { Router, Route, IndexRoute } from react-router;n// =>nimport Router from preact-router;nimport { hashHistory } from react-router;n// =>nimport createHashHistory from history/createHashHistory;nconst hashHistory = createHashHistory();nconst routes = (n <Router history={hashHistory}>n <IndexRoute component={Home} />n <Route path="about" component={About} />n <Route path="inbox" component={Inbox} />n </Router>n);n// =>nconst routes = (n <Router history={hashHistory}>n <Home path="/" />n <About path="/about" />n <Inbox path="/inbox" />n </Router>n);n

<Route/>onEnter/onLeave 鉤子也沒了,不過沒關係,因為用組件的生命周期才是更合理的。

這樣做完路由配置之後,組件中用到路由的部分也不一樣了。原先取當前頁面的 URL 或者 query 是這樣的:

class Home extends Component {ncomponentWillMount() {n const { router } = this.context;n const { params } = this.props;n const url = router.location.pathname;n const { id } = params;n }}n

現在就只需要:

class Home extends Component {ncomponentWillMount() {n const { url, id } = this.props;n }}n

是不是更簡單了。preact-router 引入了更少的 API,語法也更加簡潔。

有了路由,當然也少不了鏈接。原先我們會寫成這樣:

import { Link } from react-router;n<Link to="/about">關於</Link>n

現在只需要寫成普通的 <a/> 標籤就可以了,因為 preact-router 會自動匹配<a/> 標籤到路由:

<a href="/about">關於</a>n

當然如果你要修改激活狀態樣式的話還是可以用 <Link/>,但注意這裡用的是href="/" 而不是 to="/"

import { Link } from preact-router/match;n<Link activeClassName="active" href="/">Home</Link>n

總結

上面只是梳理了我們在做遷移時需要改動的地方,因為之前並沒有用第三方的 React 組件,所以也沒有用 preact-compat,除了 router 改得比之前更簡單了,其它基本不需要怎麼改動,整體來說遷移成本不高。

遷移後效果最明顯的就是編譯出來的 js 小了很多,基本是之前的1/3,所以移動端網頁開發推薦用 Preact 替換 React。

全文完


我們正在招聘 Java 工程師,歡迎有興趣的同學投遞簡歷到 rd-hr@xingren.com 。

歡迎搜索關注微信公眾號:杏仁技術站(微信號 xingren-tech)。


推薦閱讀:

看沃爾瑪如何玩轉 React Native
如果Vue.js作者不上知乎,vue還會在中國這麼火嗎?
比如說我想做的事情都早已經有人做過了,我再做的意義是什麼?比如學前端,有很多前端高手,我為什麼還要學?
如何評價阿里巴巴最近開源的ANT DESIGN PRO?

TAG:React | 前端框架 |