nanachi是Qunar開發的多端小程序轉譯框架。使用React語法開發,實現一處編寫、多端運行,極大地提升了咱們的開發效率。目前Qunar已經使用該框架成功上線各大小程序、快應用平臺,nanachi成爲公司小程序開發標準技術框架。html
nanachi官網: rubylouvre.github.io/nanachi/ind…前端
npm install nanachi-cli -g # 全局安裝nanachi轉譯器
nanachi init your_project_name # 初始化模板項目
cd your_project_name && npm install
nanachi watch # 編譯項目,默認編譯微信,其餘平臺須要傳入對應參數,如watch:ali、watch:bu、watch:h5...
複製代碼
編譯分爲build和watch模式,watch模式會自動監聽代碼變化從新構建。webpack
H5編譯的watch模式會在本地啓動webpack-dev-server,方便實時調試。git
用nanachi的方式編寫React SPA應用,與傳統瀏覽器開發相比,有如下優點:github
若是已使用nanachi開發了小程序應用,H5方案適用於如下場景web
H5方案代碼編譯過程分爲三個階段:shell
React SPA應用源碼編譯出Webpack產物的過程大多數前端開發都很熟悉了,這裏咱們着重介紹從源碼到生成中間產物的過程。小程序中存在不少標籤,在瀏覽器端沒有對應的原生實現,咱們首先要對這些標籤進行轉譯。npm
對一些基礎標籤,會進行直接的標籤替換:小程序
對一些複雜的組件,咱們實現了一套組件庫,schnee-ui,用來抹平瀏覽器和微信原生標籤的差別。微信小程序
schnee-ui官網: qunarcorp.github.io/schnee-ui/i… 編譯時咱們會自動導入組件依賴:
開發太小程序的同窗知道,小程序分爲App、Page、Component三級結構,對於頁面(Page)組件,咱們對代碼進行以下處理:
dynamicPage是咱們內部實現的高階組件,負責每一個頁面的生命週期鉤子調用、標題欄、tab欄的渲染、下拉刷新功能的實現、過場動畫等等。對於App組件,代碼處理以下:
在App中掛載PageWrapper組件,這是咱們整個應用的容器,主要職責是渲染頁面棧。
咱們在瀏覽器端實現了一套和微信小程序兼容的API,而且同時支持Callback和Promise的方式接收回調信息。
組件的設計方面,咱們也保持和微信小程序寫法徹底一致。除了一些基礎的按鈕、選擇器、switch開關等,還包括了一些通用的複雜業務組件,好比城市選擇器、輪播圖、日曆等。
實現了瀏覽器端沒有的標題欄和tab欄:
React方案裏缺乏一些小程序端的生命週期,咱們會在瀏覽器端模擬實現,在特定的時機觸發對應的鉤子:
小程序的頁面堆棧行爲是各平臺管理的,到瀏覽器端咱們就須要本身維護一套頁面管理方案,同時要和微信端保持一致。 咱們會在內部定義一個__currentPages數組,用來存儲頁面的React實例,並實現本身的路由方法,管理這些實例。
同時模擬了小程序的最大頁面數概念,對微信來講目前能保持最多10個頁面。咱們每次調用navigateTo方法時會檢查當前頁面棧長度是否達到最大值,達到則先推出數組的第一個元素,再存入新頁面實例。
路由管理的實現過程主要遇到兩方面的問題:
如何更新地址欄
須要在調用路由方法時同時改變地址欄,對navigateTo咱們調用history.pushState,redirectTo調用history.replaceState方法,實現地址欄的更新
如何保證調用API返回與瀏覽器原生返回事件行爲一致
咱們知道瀏覽器原生返回操做會觸發popstate事件,因此能夠監聽這個事件而後調用咱們內部的API方法,達到行爲一致。設計方案以下:
小程序的樣式是自然具備局部做用域的,到瀏覽器端樣式會變爲全局樣式,必然出現樣式污染問題,解決方案有如下幾種:
咱們採起的是最後一種方案,計算樣式文件和它對應的js文件共同父級目錄的MD5值,做爲關聯二者的惟一hash,分別添加到jsx標籤和style文件的標籤選擇器上,實現局部樣式效果。
nanachi做爲多端轉譯框架,已經成爲Qunar小程序的開發標準,其跨端特性極大地提升了開發效率。對H5端的支持也讓咱們能夠快速上線與小程序功能一致的touch應用。相較傳統React開發,咱們維護了與微信高度一致的組件和API,開發者不用再去引入各類第三方組件庫來實現一些複雜功能;同時路由行爲也由框架層維護,進一步減輕開發負擔;最後能夠實現零配置打包上線,也支持業務自定義各類Webpack配置,簡單靈活。
最後歡迎你們試用nanachi,幫咱們提issue、PR,咱們會第一時間解決或提供支持。
項目地址: github.com/RubyLouvre/…