Nuxt项目总结

公司最近要作一个新产品的官网,要求要对SEO友好,首先想到的是作服务端渲染,Vue.js的服务端渲染vue-server-renderer须要node服务.本身搭建是至关复杂的,因此咱们使用了Nuxt.js。css

Nuxt.js简介:html

  • Nuxt.js是基于Vue的服务端渲染应用框架.
  • 集成了Vue2,Vue-Router,Vue SSR,Vuex,Vue-Meta.
  • 能够轻松地经过配置实现服务端渲染或单页模式.
  • Nuxt.js根据pages文件目录自动生成路由配置.
  • 经过nuxt generate命令依据应用的路由配置将每个路由编译成为对应的 HTML 文件,实现Vue应用的静态化.

搭建过程:vue

  • 首先用NUXT的脚手架create-nuxt-app生成项目
yarn create nuxt-app <项目名>
执行命令后,会提示你进行一系列的选择,按项目须要进行选择便可
须要注意的是选择Nuxt模式(Universal or SPA),由于咱们要作服务端渲染,因此选择Universal,选择以后在nuxt.config.js配置文件中会生成配置mode:'universal'
复制代码
  • 而后会生成这样的一个项目结构(红框的目录是根据须要本身建的) node

    Nuxt.js的文件打包和页面路由都是依据目录来生成的,因此若是没有额外配置,不要修改目录的名称

  • 下面依次介绍下生成的目录: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"
    }
    复制代码

    关于mainfest的介绍

    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还能够进行不少其余的配置,后面再学习补充.

相关文章
相关标签/搜索