第一部分
之前一直不太理解為什么要使用vue+webapck,還有在使用了vue-cli之后會用到后台,即vue-cli自動幫我們安裝了express服務器,在本地服務器上運行,因為我們希望可以模擬在真是服務器上的效果,然而又不可能始終在真實的服務器上運行,所以在本地服務器上運行就很重要了。
但是通過vue+webpack構建的項目如何部署到服務器上呢?
首先VUE 是一個javascript的前端框架,注定了它是運行在瀏覽器里的,對服務器本地沒有任何要求,只要一個靜態文件服務器能通過http訪問到其資源文件就足矣!無論你是用apache ,ngnix 就算你要用node 自己實現一個靜態文件服務器,也用不了多少行代碼。
npm run dev 是用來在本地開發的時候做調試用的,vue開發的是前端的東西,不是nodejs 服務端程序,按道理講,生產環境里就不該存在npm,甚至nodejs也不需要(用nodejs來做web靜態服務的除外),正確的做法很簡單,通過npm run build 把生成的dist文件夾(不要上傳文件夾)里的內容上傳到http服務器上就可以通過 http來訪問了,開發機上正常,上傳以后 程序出現錯誤不能運行的原因99.99%的可能性是你引用資源的路徑有問題。
一般如果vue框架的程序上傳到網站服務器的根目錄下是不 會有問題的,也不存在資源文件引用錯誤的情況,但如果你不是根目錄,就會有問題,通過vue-cli 生成的開發目錄,build以后默認引用資源文件的路徑是:
比如 app.js的引用方式<script type="text/javascript" src="/static/js/app.js"></script>
所以,如果你的目錄結構是 如下:
www/
+hot/
+static/
+index.html
當你通過http://www.xxx.com/hot/index.html來訪問的時候 會出現找不到app.js。
因為index.html里引用的app.js路徑是:
http://www.xxx.com/static/js/app.js
但是app.js的實際路徑是:
http://www.xxx.com/hot/static/js/app.js 所以出現了404
要解決的方法很簡單把引用方式 改成如下兩種方式 都可以:
<script type="text/javascript" src="./static/js/app.js"></script> 或者 <script type="text/javascript" src="/hot/static/js/app.js"></script> 推薦這樣的方式,可以保正在vue-router生成的url下也不出現問題
都可以,當然這也不需要手動去改。
或者在config中的index.js下修改webpack配置:
assetsPublicPath: './' 或者 assetsPublicPath: '/hot/',
這樣,我們就基本解決了有服務器子目下運行的問題,
當然,如果你還用到了vue-router
要在router的配置中加上
export default new Router({ mode: 'history', base: '/hot/', //加上這一行
用瀏覽器打開http://www.xxx.com/hot/
一切運行正常,點擊各種鏈接也能出來,但是由於我啟用了history模式,我直接在瀏覽里訪問 http://www.xxx.com/hot/item/1 這樣的url是又404了,為什么 我可以在首頁通過點擊進入 http://www.xxx.com/hot/item/1 這個頁面,但是直接訪問又不行呢,
因為在history 模式下,只是動態的通過js 操作window.history 來改變有瀏覽器地址欄里的路徑,並沒有發起http請求,但當你直接 在瀏覽器里輸入這個地址的時候 就一定要先對服務器放起http請求,但是這個目標在服務器上又不存在所以就返回了404了,怎么解決呢,就是把所有的請求全部轉發到http://www.xxx.com/hot/index.hmtl上就可以了
<IfModule mod_rewrite.c> Options +FollowSymlinks RewriteEngine On RewriteCond %{REQUEST_URI} ^/(hot|hot/.*)$ RewriteRule ^/hot/index\.html$ - [L,NC] RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(hot|hot/.*)$ hot/index.html [L] </IfModule>
這個配置的作用就是把所有服務器上不存在請求全部轉發到index.html上去,這樣就可以直接通過各種url來訪問了
主要內容均來自:https://www.zhihu.com/question/46630687
第二部分: 實際問題的解決
這一部分即解決實際中遇到的問題。
我將文件打包成了production之后放在下面的目錄之下:
這樣,即放在了tomcat的webapps下的bbg下的wechat2中,而沒有直接放在webapps的根目錄下,這樣在實際運行的過程中,就會發現報錯,不能正常顯示,因為index.html引用的路徑都是/static/.... ,然而static 叜webapps的根目錄下,所以就會報錯。
解決方法很簡答,即在config下的index.js中修改靜態資源的路徑:、
build: { env: require('./prod.env'), index: path.resolve(__dirname, '../dist/index.html'), assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: '/bbg/wechat2/',
從最后兩行,可以看到這樣index.html最終引用的就是/bbg/wechat2/static了,成功執行。
說明:之所以將靜態文件放在這里運行,是因為我們在bbg同級的目錄下放了一個war包。 war包實際上就是將一個zip文件的后綴直接修改為war,然后tomcat服務器在啟動時,就會自動解壓這個war包。解壓后就和你直接整套的去部署是一樣的,也就是通過war包可以方便實際的運行。
其實war文件就是Java中web應用程序的打包。借用一個老兄的話,“當你一個web應用程序很多的時候,如果你想把它部署到別的機器上,來回拷這些文件是件挺郁悶的事情,如果要是一個文件就好了。。。那么war文件就可以滿足你這個小小的要求”。
那有人會說,這和直接打成rar文件不一樣嗎?區別大了!
如果你直接打成rar文件,你得手動的去解壓縮,但是war文件不需要,你把它放到tomcat的webapp目錄下,就可以直接運行了,我覺得這個功能夠強大,哈哈。
在tomcat安裝目錄下的conf目錄下有個server.xml,搜索“unpackWARs”關鍵字,你會看到在<Host>標簽中會有對其的設置,如果設置成true,那么tomcat在啟動的時候,會在webapps目錄下自動解壓你那個war文件;如果設置成false,則tomcat直接訪問war文件。
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
假如他的值是true,你的tomcat已經啟動了,你把自動解壓的文件夾刪了,tomcat又會自動解壓,我覺得它是實時的在檢查,一旦沒有,就會解壓。你可以不用擔心啟動它和放war的順序,或者啟動服務器和存放文件的順序。