公司最近要作一個新產品的官網,要求要對SEO友好,首先想到的是作服務端渲染,Vue.js的服務端渲染vue-server-renderer須要node服務.本身搭建是至關複雜的,因此咱們使用了Nuxt.js。css
Nuxt.js簡介:html
搭建過程:vue
yarn create nuxt-app <項目名>
執行命令後,會提示你進行一系列的選擇,按項目須要進行選擇便可
須要注意的是選擇Nuxt模式(Universal or SPA),由於咱們要作服務端渲染,因此選擇Universal,選擇以後在nuxt.config.js配置文件中會生成配置mode:'universal'
複製代碼
而後會生成這樣的一個項目結構(紅框的目錄是根據須要本身建的) node
下面依次介紹下生成的目錄:android
assets:該目錄下能夠放css,scss,img,js,打包時會被編譯處理webpack
components:放組件,單純的vue文件,沒有Nuxt的擴展,不能執行asyncData之類的ios
layouts:佈局文件,默認有default.vue,若是不配置,pages裏的頁面文件默認的佈局文件都是default.vue,若是想自定義佈局文件,須要在layouts中新建佈局文件,並在pages的頁面文件中進行配置,好比新建error佈局文件:nginx
//layouts/error.vue
<template>
<div>
<nuxt />
</div>
</template>
//pages/404.vue
export default {
layout:'error'
}
複製代碼
middleware:中間件目錄,中間件文件中容許自定義一個函數在頁面渲染以前執行,能夠在layouts,pages和nuxt.config.js中配置,中間件接收 context 做爲第一個參數,栗子:web
//middleware/stats.js
export default function (context) {
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent
}
//nuxt.config.js
router: {
middleware: 'stats'
}
複製代碼
pages:頁面目錄,Nuxt.js會自動讀取該目錄下的文件,生成路由配置,好比目錄結構是這樣的:vuex
pages/
--| mobile/
-----| index.vue
-----| one.vue
--| index.vue
複製代碼
Nuxt.js會自動解析成路由:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'mobile',
path: '/mobile',
component: 'pages/mobile/index.vue'
},
{
name: 'mobile-one',
path: '/mobile/one',
component: 'pages/mobile/one.vue'
}
]
}
複製代碼
Nuxt.js還支持比較複雜的動態路由,能夠參考官方文檔進行目錄配置.
Nuxt.js還擴展了頁面組件,最經常使用的是asyncData,能夠在服務端或者路由更新時執行,支持異步數據處理,其餘的還有當前頁面的head,middle,切換動畫transition配置等等,全部的擴展配置以下,能夠根據須要進行頁面的個性化配置,覆蓋nginx.config.js中的全局配置.
plugins:插件目錄,配置完後能夠全局調用,ui插件,或者js插件,像element-ui,vue-lazyload,均可以在這裏進行配置,配置方法:
//使用swiper插件
//plugins/vue-swiper.js
import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)
//nuxt.config.js
css:['swiper/dist/css/swiper.css'],
plugins:[{ src: '~plugins/vue-swiper', ssr: false }]
ssr:默認是true,表示在服務端執行,設置false表示該文件只在客戶端打包引入
複製代碼
static:靜態文件目錄,不須要webpack構建編譯處理的文件,好比在head中引入的icon就放在這個文件下
store:Vuex文件目錄,經過新建store/index.js激活Vuex,簡單的能夠像下面這樣使用,若是數據較多,能夠把模塊分解爲單獨的文件state.js,actions.js,mutations.js和getters.js,參考官方文檔進行配置.
//store/index.js
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
export const actions = {
getData (state) {
//使用@nuxt/axios能夠直接調用this.$axios
this.$axios.post('/xxx')
}
}
export const getters = {}
複製代碼
nuxt.config.js:全局的配置文件,會覆蓋nuxt的默認配置
項目中用到的nuxt.config.js配置
1.head(對SEO友好的配置,PWA配置)
head: {
title: 'xxx',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'xxxx' },
{ hid: 'keywords', name: 'keywords', content: 'xxx' }
],
link: [
{
rel: 'icon',
type: 'image/png',
sizes: '16x16',
href: '/favicon-16x16.png'
},
{
rel: 'icon',
type: 'image/png',
sizes: '96x96',
href: '/favicon-96x96.png'
},
{
rel: 'icon',
type: 'image/png',
sizes: '32x32',
href: '/favicon-32x32.png'
},
{
rel: 'icon',
type: 'image/png',
sizes: '192x192',
href: '/android-icon-192x192.png'
},
{
rel: 'apple-touch-icon',
sizes: '57x57',
href: '/apple-icon-57x57.png'
},
{
rel: 'apple-touch-icon',
sizes: '60x60',
href: '/apple-icon-60x60.png'
},
{
rel: 'apple-touch-icon',
sizes: '72x72',
href: '/apple-icon-72x72.png'
},
{
rel: 'apple-touch-icon',
sizes: '76x76',
href: '/apple-icon-76x76.png'
},
{
rel: 'apple-touch-icon',
sizes: '114x114',
href: '/apple-icon-114x114.png'
},
{
rel: 'apple-touch-icon',
sizes: '120x120',
href: '/apple-icon-120x120.png'
},
{
rel: 'apple-touch-icon',
sizes: '144x144',
href: '/apple-icon-144x144.png'
},
{
rel: 'apple-touch-icon',
sizes: '152x152',
href: '/apple-icon-152x152.png'
},
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/apple-icon-180x180.png'
},
{
rel: 'manifest',
href: '/manifest.json'
}
]
},
複製代碼
如今有些瀏覽器支持將網頁添加到主屏幕,方便用戶直接打開.
apple-touch-icon和manifest是配置添加到主屏幕的顯示的圖標和名稱等信息.
app-touch-icon是針對safari瀏覽器的.
mainfest文件格式:
{
"short_name": "短名稱",
"name": "這是一個完整名稱",
"icon": [
{
"src": "icon.png",
"type": "image/png",
"sizes": "48x48"
}
...//多個不一樣大小的圖標
],
"start_url": "index.html"
}
複製代碼
2.css
//引入全局的css文件
css: ['~/assets/css/normalize.css']
//若是要使用sass,須要安裝node-sass和sass-loader
npm install --save-dev node-sass sass-loader
css: ['~/assets/css/main.scss']
Nuxt.js會自動識別引入的文件擴展名,webpack會使用相應的預處理器進行解析
須要注意的是若是要寫一些scss的變量或函數,就須要在build中進行一些配置
複製代碼
3.使用swiper插件
//plugins/vue-swiper.js
import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)
//nuxt.config.js
css:['swiper/dist/css/swiper.css'],
plugins:[{ src: '~plugins/vue-swiper', ssr: false }]
複製代碼
4.配置404頁面
由於項目使用靜態部署,因此Nuxt官網上說的方式(在layouts中寫error.vue頁面),由於並無在pages中新加頁面,構建時並不會生成對應的靜態頁,因此這種方式並不起做用.能夠實現的方法是在plugins中監聽路由,若是沒有匹配到已經存在的路由,跳轉到404頁面
//pages/error/index.vue
<template>
<div>
404了
</div>
</template>
//plugins/route.js
export default ({ app }) => {
const {context} = app
const {matched} = context.route
if(!matched.length) {
window.location.href='/error'
}
}
//nuxt.config.js
plugins:[{ src: '~plugins/route.js', ssr: false}]
複製代碼
5.設置代理
//nuxt.config.js
modules: ['@nuxtjs/proxy'],
proxy: {
'/api': {
target: 'https://http://xxx.com',
changeOrigin: true
}
}
複製代碼
6.NUXT有自帶的axios模塊@nuxtjs/axios,若是要用自帶的模塊,能夠這樣配置axios和proxy
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
//axios的一些配置
axios: {
proxy: true,
retry: { retries: 1 }//失敗重試次數
},
proxy: {
'/api': {
target: 'https://xxx.com',
changeOrigin: true
}
}
若是要對axios請求設置統一攔截器,能夠在插件中配置
//plugins/axios.js
export default function ({ $axios, redirect }) {
$axios.setHeader('Content-Type', 'application/json', ['post'])
$axios.setToken('123', 'Bearer', ['post'])
$axios.onRequest(config => {
//設置請求攔截
})
$axios.onError(error => {
//設置報錯處理
})
window.$axios = $axios //掛載到window上,方便在任何js文件中調用
}
//nuxt.config.js
plugins:[{src:'~plugins/axios',ssr:false}]
//在vue文件中使用
mounted() {
this.$axios.post('/xxx')
}
asyncData({app}) {
app.$axios.post('/xxx')
}
//在store/actions中使用
export const actions = {
getData (state) {
this.$axios.post('/xxx')
}
}
複製代碼
可是發現@nuxtjs/axios在asyncData中使用執行nuxt generate靜態構建時會失敗,目前項目中仍是使用的是axios,在api目錄中封裝了axios的調用,像在通常的Vue項目中使用同樣
7.自定義服務端口
server: {
port: 8000, // default: 3000
}
複製代碼
nuxt.config.js還能夠進行不少其餘的配置,後面再學習補充.