公司最近要作一个新产品的官网,要求要对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还能够进行不少其余的配置,后面再学习补充.