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

凹凸實驗室發表於2022-05-20

編譯速度一直是困擾開發者的頭等問題,現階段大型 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 推出了更清晰的參與機制和榮譽激勵機制,歡迎更多的同學參與進來~

相關文章