Taro 3.5 beta 編譯提速,支持 Webpack5、React 18...

編譯速度一直是困擾開發者的頭等問題,現階段大型 Taro 項目即使在增加了 cache-loaderthread-loader 等優化手段後,編譯耗時仍高居不下。因此在 v3.5 版本中 Taro 重點對編譯系統進行了重構,引入對 Webpack5 的支持,改善小程序 & H5 編譯時的性能與體驗。(除此之外,Taro 也正在落地對於 Vite 的支持,屆時開發者將可以自由地選擇編譯工具。)

同時,Taro v3.5 還帶來了兼容 React 18、H5 MPA 等新特性,歡迎各位同學升級試用~

一、編譯提速

爲了改善編譯性能,Taro 主要做了以下事情:

  • 支持 Webpack5
  • 基於模塊聯邦的依賴預編譯
  • 支持使用 esbuild 壓縮 JS,使用 esbuild@parcel/css 壓縮 CSS
  • 使用 @swc/register 代替 @babel/register

接下來將簡單聊聊 Webpack5 與依賴預編譯,關於編譯提速的完整實現細節請參閱 RFC 文檔

1. Webpack5

Webpack5 發佈已有兩年時間,功能足夠穩定,同時其持久化緩存、模塊聯綁、更優的 Tree Shaking 等特性都爲項目的編譯流程提供了更好的解決方案。

其中的持久化緩存功能是最重要的特性之一,能極大提升再次編譯時的速度。但同時也引入瞭如何使緩存失效的問題。

Taro 遵循 Webpack “編譯安全比編譯速度重要” 的理念,默認不開啓持久化緩存。當開發者設計好緩存策略後,強烈建議開啓持久化緩存。詳細配置請參考 mini.cache

2. 依賴預編譯

Webpack5 另一個重要的特性要數模塊聯邦(Module Federation)。受 UmiJS mfsu 特性的啓發,可以預先把項目的 node_modules 依賴打包爲一個模塊聯邦 remote 應用,再次編譯時 Webpack 則無需再對依賴進行編譯,從而提升編譯速度。

依賴預編譯可以分爲三步:

  1. 收集依賴
  2. 打包依賴
  3. 打包 Module Federation Remote 應用

Taro 參考 Vite 使用了 esbuild 收集用戶使用到的第三方依賴,並分別進行打包。打包後的模塊會作爲 Webpack 的 entry,最終打包爲模塊聯邦 Remote 應用,供主應用(Host)消費。實現細節請參考 RFC 文檔

Taro 會在小程序環境的 dev 模式下默認開啓依賴預編譯功能。首次編譯時,因爲使用了 esbuild 打包第三方依賴,所以會比普通編譯稍快。二次編譯時,Taro 能直接複用 Remote App,Webpack 只需編譯業務代碼,因此根據不同項目會有不同的編譯提速效果。

依賴預編譯的流程圖:

https://storage.360buyimg.com/cjj-pub-images/prebundle.png

3. 提速效果

NutUI 組件示例庫爲例,分別測試 dev 與 prod 環境下編譯微信小程序的編譯提速效果:

https://storage.jd.com/cjj-pub-images/compile-speed_dev.png

https://storage.jd.com/cjj-pub-images/compile-speed_prod.png

可以看出:

  1. 在 dev 環境下因爲 Taro 默認開啓了依賴預編譯,因此 Webpack5 首次編譯速度比 Webpack4 稍快。而 prod 環境沒有默認開啓依賴預編譯,因此兩者速度相當(而且 Webpack5 需要寫入緩存,可能會比 Webpack4 稍慢)。
  2. 無論是 dev 還是 prod 環境,在完全命中緩存的最優情況下,Webpack5 的編譯速度都能得到極大提升。即使是修改源碼導致了部分緩存失效時,編譯速度仍然比首次編譯快得多。

4. 使用

舊項目升級後需要安裝 Webpack5 的相關依賴才能正常編譯,詳情請參考下文的【升級指南】部分。

簡單修改 Taro 的編譯配置即可開啓 Webpack5、持久化緩存、依賴預編譯等功能:

/** config/index.js */
const config = {  
	// 自定義編譯工具,可選 'Webpack4' 或 'Webpack5' 
	compiler: {       
		type: 'webpack5',   
		// 依賴預編譯配置     
		prebundle: {
			enable: true    
		}  
	},  
	// 持久化緩存配置  
	cache: {
		enable: true  
	}
}

二、兼容 React18

React 官方正式發佈了 react v18版本,帶來了 Automatic Batching、Transitions 和 Concurrent 等諸多新特性,提升了React性能。Taro 也在第一時間完成了對 React18 的兼容。

React目前存在兩種工作模式:legacyconcurrent 。在 concurrent 模式下,會使用 New Client API 來渲染組件。

默認情況下,Taro react 仍會在 legacy 模式下運行。簡單修改 @tarojs/plugin-framework-react 插件的配置即可啓用 concurrent 模式:

/** config/index.js */
const config = {
  plugins: [
    ['@tarojs/plugin-framework-react', { reactMode: 'concurrent' }]
  ]
}

不要忘記將項目的 react 版本升級到 v18 哦

詳細內容請參考 discussions

三、支持服務端渲染(SSR)

1. 動機

與 SPA(單頁應用程序,Single-Page Application)相比,服務器端渲染(SSR)能帶來帶來更快的首屏渲染速度更好的 SEO,因此 SSR 功能是大家期望 Taro 支持的特性之一。

2. 實現原理

Taro 在 3.1 版本提出了開放式架構的思想,讓開發者可以通過編寫插件來讓 Taro 支持一個新的平臺。

通過 Taro 插件,將 React 生態中知名的 Next.js 框架作爲 Taro 的一個新的目標平臺,以此讓 Taro 能夠支持服務端渲染(SSR)。

目前這個插件項目的地址位於:SyMind/tarojs-plugin-platform-nextjs

⚠️  插件目前處於早期建設中,不建議用於生產環境!

3. 安裝與使用

安裝插件和 Next.js 框架。

# 使用 npm 安裝插件與 next.js
npm install tarojs-plugin-platform-nextjs next

# 使用 pnpm 安裝插件與 next.js
pnpm install tarojs-plugin-platform-nextjs next

在 Taro 項目的編譯配置中添加本插件。

const config = {
  plugins: [
    'tarojs-plugin-platform-nextjs'
  ]
}

開始嘗試它吧!

npx taro build --type nextjs --watch

四、支持多頁應用(MPA)

很多同學通過閱讀 Taro 的源碼發現,Taro 曾在 1.x 支持過多頁面應用,通過配置 multi 模式就可以開啓該特性,但是由於並沒有很好支持,也沒有相應的業務場景測試,最終並沒有在文檔中呈現。

在 2.x 發佈時,由於各種原因我們回滾了該特性,儘管開發者們依舊可以通過插件或者在項目內自定義 webpack 配置實現類似的需求,不過這依舊會在一些細節上難以處理得盡善盡美。比如需要額外配置文件拆分規則避免冗餘的代碼,對於 MPA 也並不需要taro-router提供對於路由相關的事件方法的支持……

MPA 是不少社區開發者所追求的重要特性之一,爲此我們改寫了 taro-loadertaro-router 以適應該模式的個性化需求,應用該模式也只需要如下配置:

module.exports = {
  // ...
  h5: {
    // ...
    router: {
      mode: 'multi'
    }
  }
}

需要注意的是,有很多小程序事件和方法都是基於 SPA 模式設計使用的,在 MPA 模式並不適用,所以會存在一些問題,比如由於多頁面導致 TabBar 會重複加載,App 級的生命週期會重複觸發,不支持路由動畫,生產環也需要額外配置路由映射等等,開啓該模式前需要認真考量適用場景。

五、RN 相關依賴庫由 unimodules 升級至 expo

Expo 是 React Native 生態中的重要角色,提供了非常多優秀的模塊,在 Taro 中有較爲廣泛的使用,如 expo-av、expo-camera 等,將來我們還會持續接入新的模塊。Expo 的模塊系統,由 unimodules 變更爲 expo 已有一段時日,其架構變更原因可參考文章: What’s new in Expo modules infrastructure

Taro v3.5 及以後將使用新的模塊系統,可以通過 taro init 選擇 react-native 模板體驗。如果你使用的是 Taro 殼工程,可切換到 0.67.0-expo 分支體驗。

新老版本的 Taro 及殼工程之間混用的話,將存在不兼容情況,主要原因是存在多個版本原生依賴導致,可通過 resolution 進行版本鎖定解決,相應版本參考此處

後續殼的工程將不再包含 unimodules 版本。舊版本升級可參考此PR

注意:升級爲 expo 將不再支持 iOS 11,詳細內容請參考 discussions

六、升級指南

1. 安裝 v3.5.0-beta 的 CLI 工具:

npm i -g @tarojs/cli@beta

2. 更新項目依賴

如果安裝失敗或打開項目失敗,可以刪除 node_modules、yarn.lock、package-lock.json 後重新安裝依賴再嘗試。

2.1 把 package.json 文件中 Taro 相關依賴的版本修改爲 3.5.0@beta

2.2 Breakings

  • Vue2 項目需要添加 devDenpendencies:"@vue/babel-preset-jsx": "^1.2.4”

  • Vue3 項目需要添加 devDenpendencies:"@vue/babel-plugin-jsx": "^1.0.6"

  • React 項目需要添加 devDenpendencies:

    "@pmmmwh/react-refresh-webpack-plugin": "0.5.4",
    "react-refresh": "0.11.0"
    
  • PReact 項目需要添加 devDenpendencies:

    "@prefresh/webpack": "^3.2.3",
    "@prefresh/babel-plugin": "^0.4.1"
    

2.3 重新安裝依賴

3. 使用 Webpack5

新項目在創建項目時,選擇編譯工具爲 "webpack5" 即可。

舊項目升級後需要更新依賴:

  • 建議首先刪除 node_modulesyarn.lockpackage-lock.json
  • package.json 中刪除 @tarojs/mini-runner@tarojs/webpack-runner 依賴,添加 @tarojs/webpack5-runner 依賴。
  • 重新安裝依賴。
  • Taro 編譯配置添加 compiler: 'webpack5',最後開啓編譯。

最後

接下來我們會繼續對 v3.5 版本進行迭代,包括實現 H5 的依賴預編譯等。而在 v3.6 版本則會落地對 Vite 的支持,同時優化運行時的性能。

最後的最後,衷心各位感謝參與 Taro 開源共建的同學!爲了建立更加完善、更加可持續的 Taro 開源生態,突出貢獻者價值,Taro 推出了更清晰的參與機制和榮譽激勵機制,歡迎更多的同學參與進來~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章