Vue項目用於Ios和Android端開發
起因
前公司商城App項目使用的是H5開發,有微信公眾號、Ios和Android三個版本,H5版本是自己寫的一套框架,已經用了有些年頭了,承載不下不斷湧現出的新需求。而Ios和Android端通過webview加載h5文件顯示,App的原生功能和H5交互的代碼寫得有些淩亂,在我接手項目後老板完全沒給重構的時間,所以只能在做新功能的時候順手一點點的重構。後來要做一個與原先的商城相對獨立的新商城,而且新商城的入口放在老商城中。因為時間緊任務重,使用React Native或者weex的話需要將原項目重構後再引入,考慮到可能存在的各種各樣的坑,不太可能使用這些解決方案。使用vue或者react構建一個web項目再嵌入原有的app項目中是最穩妥的。最終因為vue的名字在字符數和音節數量上占了絕對的優勢而入選。
vue項目構建
預備
vue中文文檔: https://cn.vuejs.org/v2/guide/instance.html
構建工具環境
nodejs: http://nodejs.cn
構建工具vue-cli:
https://github.com/vuejs/vue-cli
如果是第一次接觸vue或者在已有項目中引入vue時可以選擇用CDN版本或者下載js文件
vue的生產版本js:
https://vuejs.org/js/vue.min.js
引入CDN版本:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
構建項目
如果是作為一個新項目,還是建議使用vue-cli構建項目,省時省心
安裝完nodejs環境後在終端裏輸入:
npm install --global vue-cli
進入要存放項目的目錄後創建一個基於webpack模板的新項目
vue init webpack my-project
其他模板還有pwa、browserify、webpack-simple、simple、browserify-simple等,可以自行到Github上了解:https://github.com/vuejs-templates
在構建時有這麽幾個選項需要註意:選擇Runtime + Compiler: recommended for most users
官方的解釋https://cn.vuejs.org/v2/guide/installation.html#運行時-編譯器-vs-只包含運行時
vue-router:
建議選上,文檔地址 https://router.vuejs.org/zh-cn/
ESLint:
建議選上,模板使用Standard ,官網地址 https://eslint.org
編譯與運行
進入項目根目錄打開package.json
文件可以看到項目的各項配置,其中scripts
下存放的是各種命令,在命令行中通過npm run ***
來執行
npm run dev 或者 npm start
相當於執行webpack-dev-server --config build/webpack.dev.conf.js
啟動開發環境
在開發中經常會使用process.env.***
的值來區分不同的環境。環境變量的值在/config/*.env.js
文件中配置,webpack.dev.conf.js
文件中引入的配置文件是dev.env.js
,我們可以在開發是判斷process.env.NODE_ENV
的值是否為development
來確定當前環境是否為開發環境
在不改任何配置的情況下啟動後,在瀏覽器中輸入http://localhost:8080
就可以看到效果了
npm run build
執行此命令後會對當前項目進行編譯打包,編譯完成後我們就可以在/dist
目錄下看到我們需要的項目文件了。
編譯完成後可以在終端上看到這樣一段溫馨提示,“不允許通過直接打開index.html文件進行訪問哦”
這也就意味著將打包後的項目直接放到Ios或Android項目中使用webview加載也是不允許的。這可如何是好呢?
我們偷偷的點開/dist/index.html文件看看會發生什麽吧
一片空白並且報了ERR_FILE_NOT_FOUND
的錯誤,沒有找到css和js文件。用編輯器打開文件後可以看到,這幾個文件的路徑確實有些問題,於是在路徑前加上一個.
號後發現打開頁面不再是一片空白了。
但是,我們不可能每次編譯都重新手動修改一次文件吧?很明顯這個是可以在編譯的配置裏面設置的.
打開/config/index.js
文件,找到build {}
的配置下有一個assetsPublicPath: ‘/‘
的參數配置,修改成assetsPublicPath: ‘./‘
就好啦,執行npm run build
後資源文件的路徑就修改成./
了。
現在無論是用http://
還是file://
訪問都沒問題了。放到Ios或者Android項目中應該也沒有問題了
關於source map
使用webpack編譯後會發現每個資源文件都有一個對應的.map
文件,而且這個文件所占的體積還不小,在沒加任何代碼的情況下將項目文件壓縮成zip包後大小為227k,如果刪除.map文件後只有50k,可以想象.map文件對項目體積的影響。
在編譯完項目後我們自己寫的所有js代碼會被壓縮到一個app.***.js
文件中,這時候如果在線上某個函數報錯了,.map文件可以幫我們定位到報錯的函數具體是在哪個文件裏的。然而大多數情況下.map
文件是沒有必要打包放到線上的.
打開/config/index.js
文件,找到build {}
的配置下的productionSourceMap
改成false就不會生成.map文件啦
壓縮打包
在一般項目中在開發完成後我們通常會將文件打包成一個zip文件,這樣不但方便保存和傳輸,還有一種儀式感。那麽要怎樣在編譯完成之後自動打包成zip文件呢。
首先我們需要安裝一個webpack-zip-plugin
工具
npm i webpack-zip-plugin --save-dev
然後打開/build/webpack.prod.conf.js
文件,在文件中引入相關的包
const WebpackZipPlugin =require(‘webpack-zip-plugin‘)
在plugin: []
中加入WebpackZipPlugin
的配置:
new WebpackZipPlugin({ initialFile: ‘./dist/release/‘, //需要打包的文件夾(一般為dist) endPath: ‘./dist/release/‘, //打包到對應目錄(一般為當前目錄‘./‘) zipName: ‘release.zip‘ //打包生成的文件名 })
可以在dist
目錄下看到release.zip
文件啦。
關於跨域
在本地開發的時候如果要調用服務端的接口,肯定會遇到跨域問題,這時候我們只需要在/config/index.js
文件中的dev: {}
裏面加上proxyTable就行了
proxyTable:{ ‘/server‘: { target: ‘http://192.168.11.5:3001‘ } }
這樣我們就可以將http://localhost:8080/server
路徑的所有請求都轉發到http://192.168.11.5:3001/server
下了
Android項目
關於WebView
無論是Android的WebView還是Ios的UIWebView和WKWebView都只是提供一套接口方便開發者調用,而實際工作都是交給WebKit完成的。後來Google在WebKit的基礎上按照自己的風格與優化出了Blink,用於自己的瀏覽器產品。由Blink我們可以看出Google在Android的WebView優化上做出了不少的努力。但是還是會難以抑制的擔心系統WebView的性能,尤其是當看到騰訊X5內核標註的技術特性。不管怎樣,騰訊爸爸的話還是要信的,所以在demo中使用了X5內核。
imagehttp://x5.tencent.com/tbs/guide/procIntro.html
加載vue項目
將Vue項目生成的文件放到Android項目的Assets目錄下,使用WebView的loadUrl方法加載就行了
mWebView.loadUrl("file:///android_asset/vue/index.html");
關於跨域
如果vue項目中有請求服務端數據的功能,就有可能產生跨域的問題,日誌中會發現如下錯誤
No ‘Access-Control-Allow-Origin‘ header is present on the requested resource.
Android的WebView處理跨域問題很簡單,只要將AllowUniversalAccessFromFileURLs設置為True就行了
WebSettings webSetting = mWebView.getSettings(); webSetting.setAllowUniversalAccessFromFileURLs(true);
Ios項目
加載vue項目
Ios可以使用UIWebView或者WKWebView直接加載
<!-- UIWebView --> let mWebView = UIWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)) let path = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "vue") let url = URL(fileURLWithPath: path!) self.view.addSubview(mWebView) mWebView.loadRequest(URLRequest(url: url)) <!-- WKWebView --> let mWebView = WKWebView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)) let path = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "vue") let url = URL(fileURLWithPath: path!) self.view.addSubview(mWebView) mWebView.load(URLRequest(url: url))
demo
github: https://github.com/ljnjiannan/vue-demo
Vue項目用於Ios和Android端開發