Laravel+Nuxt快速上手
前言 :
完成了一個網站前後台開發作業,但VueJs的SEO問題卻有點難處理,下個專案必須考慮SEO狀況因此單純用VueJs處理前端就已經不敷使用
研究了一下SSR的處理方式,決定透過Nuxt來處理Vue的SSR讓SEO更友善,本篇將紀錄初期開發踩坑全記錄
如何整合Laravel?
Nuxt是不是可以像Vue一樣,將前後端兩個project整合成單一網站來開發?
一開始是這麼想到,畢竟開發者只有我一個人如果還有拆兩塊寫有點麻煩,因此找到gitHub上已經有人整合好的plugin可以使用
https://github.com/m2sd/nuxt-laravel
https://github.com/m2sd/laravel-nuxt
先說結論 : 目前無法使用Nuxt universal模式,也就是無法處理SSR的部分,因此我放棄了
最終我只有在laravel資料夾底下的resources/nuxt 來建立Nuxt專案,整合git repo到同一個專案底下方便管理
建立Nuxt專案
依照Nuxt官網提示很容易只要一個指令就可以將Nuxt初始化安裝起來
1 |
npx create-nuxt-app PROJECT_NAME |
切換到laravel/resources資料夾底下下指令
1 |
npx create-nuxt-app nuxt |
當然踩坑了npx丟了錯誤出來,還好gitHub上也不少人遇到一樣的錯誤
https://github.com/nuxt/create-nuxt-app/issues/383
https://github.com/serverless/serverless/issues/6989
先把create-nuxt-app裝起來就可以了
1 |
sudo npm install -g create-nuxt-app |
接著系統會提示使用的專案資料夾名稱以及其他需要的相依套件
這次我只有裝axios且server使用NodeJs,有需要其他套件就自行選擇
安裝好之後且換到laravel/resources/nuxt資料夾
1 |
npm run dev |
應該就可以透過 http://localhost:3000 看到Nuxt網站已經建立完成
Docker環境也會踩坑嗎?
當然不缺席,如果你跟我一樣開發環境是架構在docker-compose(php7 + nginx)的話需要注意幾個地方
1. 為了避免每次重開docker都需要安裝一次create-nuxt-app 所以我將指令加入php的Dockerfile
1 |
RUN npm i -g create-nuxt-app |
2. 因為Nuxt測試與正式環境都架構在3000 port底下所以記得要把php的Dockerfile expose 3000 port
1 |
EXPOSE 3000 |
3. docker-compose記得將3000 port加入對應的php container
1 2 |
ports: - 3000:3000 |
4. 最後,因為Nuxt 並非扔回3000 port而已,而是http://localhost:3000/,所以要將php的Dockerfile加入
1 |
ENV HOST 0.0.0.0 |
這樣應該就可以透過http://localhost:3000連線了,雖然Nuxt在build的時候會顯示的是container的IP位置
Nuxt的Router怎麼處理
基本上Nuxt不必像Vue一樣需要手動建立每一個連結的Route設定,他會按照page資料夾底下的文件結構自己長出來,基本上如果沒有特殊需求依照官網的指示來設定page資料夾底下的vue檔案就可以了
https://nuxtjs.org/guide/routing/
But! 我個人習慣依照Route的結構來設定全站的使用權限,因此我還是走自行建立Route的方式
https://github.com/nuxt-community/router-module
首先,安裝需要的package
1 |
npm install --save-dev @nuxtjs/router |
接著到resources/nuxt也就是nuxt的根目錄找到nuxt.conf.js,在buildModules 陣列中加入以下
1 |
@nuxtjs/router |
接著就可以在nuxt根目錄建立router.js 建立自己需要的路由資訊了Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import Index from '~/pages/backend/index' Vue.use(Router) export function createRouter () { return new Router({ mode: 'history', routes: [ { path:'/', name: 'index', component: Index } ] }) } |
Nuxt如何處裡.env檔
.env可以用來記錄後端API的位置以及其他環境資訊,使用.env可以分開正式上線後跟開發階段的不同參數,vue整合到laravel後,可以直接讀取laravel的.env檔案,那Nuxt怎麼處理?
https://github.com/nuxt-community/dotenv-module
安裝套件
1 |
npm install --save-dev @nuxtjs/dotenv |
接著到nuxt.conf.js的buildModules加入以下
1 |
@nuxtjs/dotenv |
最後,就可以在nuxt跟目錄底下建立.env檔案,如果有個變數名稱為MIX_API_NAME的話個可已透過process.env.MIX_API_NAME來取得參數值
Nuxt的localStorage
在vue中,可以將需要存在瀏覽器內的資料(ex:登入資訊)存放到localstorage中,但Nuxt是沒有的,如果需要儲存資料可以使用server side的session 或cookie,畢竟Nuxt是Server與Client並存的,所幸也有人已經完成package可以存取localstorage,但是有些需要注意的地方
https://github.com/rubystarashe/nuxt-vuex-localstorage
首先,安裝套件
1 |
npm i nuxt-vuex-localstorage |
接著編輯nuxt.conf.js中的models,加入以下資訊
1 |
['nuxt-vuex-localstorage',{localStorage: ['adminUser']}] |
其中,’adminUser’是我會用來存取localstorage的vuex module,可以把所有有用上的module都填在這個陣列中
以這個範例來看,adminUser中的state資料就會被存放到localstorage中不會揮發
但是,需要注意的是如果Nuxt跑在usiversal模式底下,網頁載入的時候是從server端將資料渲染好再傳回瀏覽器,這時候因為localstorage屬於client端的資料就會無法取得
如果component需要取得localsotrage資料我會在mounted()中將存在localstorage中的資訊取出存回到component的data中,方便頁面渲染資料時直接使用data中的資料
Nuxt使用vue的套件
https://zh.nuxtjs.org/guide/plugins/
根據官網描述,Nuxt是可以直接使用vue的npm套件的,舉例來說如果我們需要用到vue-simple-alert
https://github.com/constkhi/vue-simple-alert
首先,一樣先安裝套件
1 |
npm i vue-simple-alert |
接著在nuxt/plugin資料夾中建立一個檔案命名為vue-simple-alert.js,內容為
1 2 3 4 |
import Vue from "vue"; import VueSimpleAlert from "vue-simple-alert"; Vue.use(VueSimpleAlert); |
接著編輯跟目錄底下的nuxt.conf.js,在plugins中加入
1 |
'~/plugins/vue-simple-alert' |
在component中就可以依照vue套件的原生方式使用了,但我偶爾會遇到錯誤,目前還不知道發生什麼事情
Nuxt中的Server / Client 取得API資料
Nuxt中asyncData與fetch可以說是精華所在,Server端會先跑過這兩個function,換句話說可以在這邊先呼叫api取得資料這樣就可以正確在server端渲染完成了
詳細可以參考這篇文章
https://medium.com/@jackercleaninglab/ssr-nuxt-js-%E8%B6%85%E5%85%A5%E9%96%80-84a0823b45ed
舉例來說,我會這樣子取得資料
1 2 3 |
async fetch ({ store, params, query }) { await store.dispatch("MODULE_NAME/ACTION_NAME",其他需要傳送的參數) }, |
其中,有幾個地方說明一下
params : 是指route中設定好的參數,舉例來說route中如果設定了/:id
就可以透過params.id 來取得網址中帶入的id資料
query: 網址中的_GET參數,如果網址中有?page=2
就可以透過query.page來取得
但是,這次遇到一個狀況是取得資料後我想放回component中的data而不是渲染到網頁中
這部分做法就回到跟vue相同,在mounted中透過dispatch取得資料後watch變數變更的時候再寫回data中即可
如果還有更好的做法會再更新上來
以上幾點,紀錄一下初次開發
下一步將會是在docker中獨立建立container處理Nuxt 伺服器,並且做到docker-compose up後可以自動build 並start Nuxt