Loading...

Nuxt.js -- Vue.js 单页应用的服务端渲染

发布者 milleros - 6 个月前

简介

Vuejs现在几乎成了单页应用的代名词,但作为单页应用,在搜索引擎的友好程度上显然是不行的,当网站爬虫爬取到vue应用时如果没有做过特殊的处理,爬虫通常是爬取不到页面的主要内容的,因为vue单页应用通常使用的都是前端渲染,而爬虫爬取通常是不执行JS的;所以在种种情况下Vue的服务端渲染显然是作为对SEO优化最好的选择,因此Nuxt.js应运而生。

Nuxt.js

Nuxt.js 是一个基于 Vue.js 的通用应用框架,它预设了利用 Vue.js 开发 服务端渲染(SSR, Server Side Render) 的应用所需要的各种配置,同时也可以一键生成静态站点。

作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。区别于其他 vue SSR 框架,Nuxt.js 有以下比较明显的特性。

  • 自动代码分层
  • 强大的路由功能,支持异步数据(路由无需额外配置)
  • HTML头部标签管理(依赖 vue-meta 实现)
  • 内置 webpack 配置,无需额外配置

起步

项目创建

使用基于vue-cli的脚手架工具

$ vue init nuxt-community/starter-template <project-name>

通过此命令行命令初始化一个nuxt项目。

目录结构

├─assets                      资源目录,未编译的静态资源如less、js
├─components             组件目录,例如页面共用的头部,底部
├─layouts                    布局目录,例如所有页面都分成三部分,上中下
├─middleware             用于存放应用的中间件,允许您定义一个自定义函数运行在一个页面或一组页面渲染之前。
├─node_modules           
├─pages                      页面目录,放置页面除去组件后的主要部分
  ├─index.vue
  ├─....                 
├─plugins                    插件 例如jq,swiper等插件的文件
├─static                      静态文件目录
├─store                       vuex store 

vuex store : vuex状态树

配置项

// nuxt.config.js 文件配置
const path = require('path')

module.exports = {
  // Headers of the page
  head: {
    title: '默认共用title', //对应HTML<title />
    meta: [ //对应HTML<meta>
      { charset: 'utf-8' },
      { 'http-equiv': 'pragma', content: 'no-cache' },
      { 'http-equiv': 'cache-control', content: 'no-cache' },
      { 'http-equiv': 'expires', content: '0' },
      { content: 'telephone=no', name: 'format-detection' }
    ],
    // html head 中创建 script 标签
    script: [
      { innerHTML: require('./assets/js/flexible_nuxt'), type: 'text/javascript', charset: 'utf-8'}
    ],
    // 不对<script>标签中内容做转义处理
    __dangerouslyDisableSanitizers: ['script']
  },
  // Global CSS
  css: ['~/assets/css/reset.css', '~/assets/css/main.less'],
  // Global env
  env: {
    __ENV: process.env.__ENV
  },
  build: {
    vendor: ['axios'],
    postcss: [
      require('postcss-px2rem')({
        remUnit: 75
      })
    ],
    extend (config, ctx) {
      if (ctx.isClient) {
        // 拓展 webpack 配置
        config.entry['polyfill'] = ['babel-polyfill']
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
        // 添加 alias 配置
        Object.assign(config.resolve.alias, {
          'utils': path.resolve(__dirname, 'utils')
        })
      }
    }
  },
  plugins: [{src: '~plugins/toast', ssr: false}, {src: '~plugins/dialog', ssr: false}]
}

头部标签配置

Nuxt.js 通过 vue-meta 实现头部标签管理,在 nuxt.config.js 中的 head 配置。所有的页面都会走这个配置,如果想要修改某一页面的title,可以在 pages/yourpage.vue 文件下,添加如下配置,这时该页面的标题就变成了“This is Miller”,其余页面还保持原有标题不变。

<script>
    export default {
        head () {
            return {
                title:'This is Miller'
            }
        }
    }
    //do something
</script>

在config header配置中, __dangerouslyDisableSanitizers: ['script'] 主要是为了不对innerHTML中内容做转义处理

路由

Nuxt.js 依据 pages 目录结构,自动生成 vue-router 模块的路由配置。

详情可查看Nuxt.js官网路由板块

布局

Nuxt.js布局方式如下图所示: Nuxt.js布局方式

布局配置文件存储在layouts文件夹下,默认布局为default.vue:

<template>
  <div id="milleros">
    <AppHeader />
    <nuxt/>
    <AppFooter />
    <AppLoading />
  </div>
</template>

这里<nuxt/>是一个页面的主体,所有/pages/*.vue中的内容都会插入到此标签中;

<AppHeader />、<AppFooter />、<AppLoading />为conponents组件,是所有页面共用的组件。

所以layouts布局就是配置不同组件和页面主体的结构。

我们可以根据不同的页面定制不同的layouts布局:

<script>
export default {
  layout: 'demo_layout',
  //do something
}
</script>

vuex

在根目录创建 store 目录,就会默认引用 vuex 模块,除此之外,还进行了以下的操作: 1)将 vuex 模块 加到 vendors 构建配置中去; 2)设置 Vue 根实例的 store 配置项。

Nuxt.js 支持两种使用 store 的方式:

  • 普通方式:store/index.js 返回一个 Vuex.Store 实例
  • 模块方式:store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块 (当然,index 是根模块,相当于设置了namespaced: true)

Nuxt.js提供了模块方式的简单写法:使用状态树模块化的方式,store/index.js 不需要返回 Vuex.Store 实例,直接将 state、mutations 和 actions 暴露出来即可。示例如下:

export const state = () => ({
  accesstoken: ''
})

export const mutations = {
  setAccesstoken (state, accesstoken) {
    state.accesstoken = accesstoken
  }
}

asyncData

asyncData方法是服务端渲染的重点!!!

因为asyncData可以在组件(仅限于页面组件)每次加载之前被调用。而且可以再服务端或路由调用之前被调用

Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。

详细查看异步数据

标签纵览

Python(1)VueJS(1)Nodejs(1)Linux(3)前端(2)