SPA 遷移到SSR_Nuxt.js 從開發到部署

首先,給自己打打氣!

Let us not look back in anger, nor forward in fear, but around in awareness.

-- 不怒然回首,不恐懼前行,活著,就是現在。

補充一個關于腳手架的概念,引用自 編程中的腳手架是什么意思

這里是stackoverflow上的一個回答:

Scaffolding is a meta-programming method of building database-backed software applications. It is a technique supported by some model-view-controller frameworks, in which the programmer may write a specification that describes how the application database may be used. The compiler uses this specification to generate code that the application can use to create, read, update and delete database entries, effectively treating the template as a "scaffold" on which to build a more powerful application.

譯:“腳手架”是一種元編程的方法,用于構建基于數據庫的應用。許多MVC框架都有運用這種思想。程序員編寫一份specification(規格說明書),來描述怎樣去使用數據庫;而由(腳手架的)編譯器來根據這份specification生成相應的代碼,進行增、刪、改、查數據庫的操作。我們把這種模式稱為"腳手架",在腳手架上面去更高效的建造出強大的應用!

Nuxt 項目目錄結構圖

1. main.css

使用 nuxt 要有意識,很多文件需要去 nuxt.config.js 這里配置才能生效。這個是原 SPA 項目的全局樣式文件,遷移后是這樣引入的:

// nuxt.config.js
  css: ['./assets/css/main.css'],

2. flexible.js

這是一個比較 simple 的 flexible 文件

// static/js/flexible.js
var rootResize = function() {
  var baseFontSize = 20
  var baseWidth = 5120
  var minWidth = 1920
  var clientWidth = document.documentElement.clientWidth || window.innerWidth
  var innerWidth = Math.max(Math.min(clientWidth, baseWidth), minWidth)

  var rem = clientWidth / (baseWidth / baseFontSize)
  if (innerWidth == 5120 || innerWidth == 1920) {
    rem = innerWidth / (baseWidth / baseFontSize)
  }
  document.querySelector('html').style.fontSize = rem + 'px'
}
rootResize()

window.onresize = function() {
  rootResize()
}

巨坑,我原本把 flexible 文件當做 plugin 引入了,如下,這是一個錯誤示范:

// nuxt.config.js
  plugins: [
    {
      src: '@/static/js/flexible.js', ssr: false
    }
  ],

這里的 ssr 一定要設置為 false, 否則會報一個叫 document is not defined 的錯。倒也不是不可以生效,不過它是有一個延遲生效的問題。

!!!最優解決方案是,添加 head 配置:
// nuxt.config.js
head: {
    // title, meta, link etc.
    script: [{ src: '/js/flexible.js', type: 'text/javascript', charset: 'utf-8' }]
  },

劃重點,重點,重點!!!這里的 src 路徑一定要寫 static 下面的絕對路徑就好,也就是 /js/flexible.js but not /static/js/flexible.js

3. axios

nuxt 自帶 axios "@nuxtjs/axios"

添加配置:

// nuxt.config.js
 modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
  ],
 axios: {
    proxy: true,
    prefix: '/api/',
    credentials: true
  },

  proxy: {
    '/api/': {
      target: 'http://my-api/',
      pathRewrite: {
        '^/api/': '/',
        changeOrigin: true
      }
    }
  },

以上配置都是針對 vue 文件的,所以在 vue 組件中可以使用 this.$axios 來調用。

  • 組件文件中使用:
// *.vue 
this.$axios.get('/getInfo').then((res)=>{
    console.log(res)
})
  • stats.js 等其他文件中使用:
// middleware/stats.js
import axios from 'axios'
export default function({ route }) {
  return axios.post('http://my-stats-api.com', {
    params,
  })
}

4. eventBus

// plugins/bus-inject.js
import Vue from 'vue'

export default (ctx, inject) => {
  const bus = new Vue()
  inject('bus', bus)
}

組件中觸發事件:

// app.vue
this.$axios
        .get('/getData')
        .then(response => {
          let res = response.data || {}
          this.$bus.$emit('data', res)
        })
        .catch(error => {
          console.log(error)
        })

組件中接收事件:

// sub.vue
this.$bus.$on('data', (res)=>{
    console.log(res)
})

5. wordcloud echarts の詞云

// plugins/echarts.js
import Vue from 'vue'
import echarts from 'echarts'
import wordCloud from 'echarts-wordcloud'

Vue.prototype.$echarts = echarts
Vue.prototype.$echarts.wordCloud = wordCloud
// nuxt.config.js
 plugins: [
 ...
    { src: '@/plugins/echarts', ssr: false }
...
  ],

同樣,ssr: false 一定要寫,否則會報 error: window is not defined

6. 本機 ip 訪問替代 localhost

// package.json
"config": {
    "nuxt": {
      "host": "0.0.0.0",
      "port": 3000
    }
  }

7. BMap api 百度 Map 的 api key

// nuxt.config.js
head:{
    // title, meta, link etc.
  script: [
     ...
      {
        src:
          'http://api.map.baidu.com/api?v=2.0&ak=key...'
      }
      ...
    ]
}

8. iframe 的問題

這個坑是很奇怪的,在 SPA 模式開發一個項目,我會把寫好的頁面以 iframe 的形式串聯到一起,and by then it worked well. 可是到了 SSR 莫名其妙的出現了類似線程阻塞的問題,倒是不需要糾結,只要改成組件引入即可。

出現這個問題的原因應該是,如果是 iframe 的方式引入,首先需要這個頁面已經渲染完成,然后再通過 iframe 引入。所以導致了阻塞問題。

9. 打包與部署

9.1 本地打包

首先執行打包命令:

yarn build 

yarn build 之前需要將所有的 console.log 刪除或注釋,or else 有可能會報 console 的錯而導致打包失敗。

如果打包成功了,啟動打包后的項目:

yarn start

本地啟動沒有問題就可以進行下一步了。

9.2 服務器部署

9.2.1 服務器安裝 node.js,Linux 系統下安裝 node.js,請移步至https://segmentfault.com/a/1190000017866964

9.2.2 服務器創建并 cd 到目錄 local/deploy/front,將以下文件復制到該文件夾下:

然后執行:

yarn install -production

成功后:

居然還沒結束,因為沒有啟用「進程守衛」

9.2.3 安裝 pm2

安裝 pm2 參考 https://www.cnblogs.com/minrh/p/9770890.html

然后 cd 到項目目錄下,執行以下:

# yarn
pm2 start yarn --name "my-nuxt" -- start

# npm
pm2 start npm --name "my-nuxt" -- run start

*** 這里的 my-nuxtpackage.jsonname 的名稱。

感謝那些對我們有所幫助的文章:

nuxt.js部署vue應用到服務端過程
Nuxt項目從開始到部署

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容