Gridsome 静态站点生成

859 阅读3分钟

一、Gridsome 介绍

  • Gridsome 是一个免费、开源、基于 Vue 技术栈的网站生成器
  • 官方网站
  • Github 什么是静态网站生成器
  • 静态网站生成器是使用一系列配置、模版以及数据、生成静态HTMl文件及相关工具
  • 同时这个功能也叫预渲染
  • 生成的网站不需要类似 PHP 这样的服务器
  • 只需要放到静态资源的 Web Server 或者 CDN 上运行 静态网站的好处
  • 省钱 不需要专业的服务器,只要能托管静态文件的空间即可
  • 快速 不经过后端服务器的出来,只传输内容
  • 安全 没有后端程序的执行,自然会更安全 常见的静态网站生成器
  • Jekyll (Ruby)
  • Hexo (Node)
  • Hugo (Golang)
  • Gatsby (Node/React)
  • Gridsome (Node/Vue)
  • 另外,Next.js, Nuxt.js 也能生成静态网站,但是他们更多认为是SSR(服务端渲染)框架 JAMStack
  • 这类静态网站生成器还有个漂亮的名字叫JAMStack
  • JAMStack的JAM是JavaScript、API和Markup的首字母组合 本质上是一种胖前端,通过调用各种API来实现更多的功能
  • 其实也是一种前后端的模式,只不过离得比较开,甚至前后端来自多个不同的厂商 静态应用的使用场景
  • 不适合有大量路由页面的应用
    • 如果您的站点有成百上千条路由页面,则预渲染将非常缓慢。当然,您每次更新只需要做一次,但是可能要花一些时间。大多数人不会最终获得数千条静态路由页面,而只是以防万一
  • 不适合有大量动态内容的应用
    • 如果渲染路线中包含特定于用户查看其内容或其他动态源的内容,则应确保您具有可以显示的占位符组件,直到动态内容加载到客户端为止。否则可能有点怪异

二、Gridsome基础

创建Gridsome 项目

  • node-gyp
npm install -g node-gyp

image.png

  • 安装 Gridsome 脚手架
yarn global add @gridsome/cli
npm install --global @gridsome/cli

gridsome create gridsome-blog // 初始化项目

cd gridsome-blog
gridsome develop

安装依赖的时候很慢,无进度条,解决方法:

  • 中断当前安装
  • 进入已经生成的项目目录下,删除当前的 node_modules
  • 执行 npm install ,此时就可以看到进度了
  • 安装好依赖之后,执行npm run develop启动项目

image.png 启动后效果如下:

image.png

预渲染

打包生成dist目录

yarn build

安装web静态服务器

 npm i -g serve

将build文件夹部署到该服务器

serve dist

image.png 效果如下:

image.png 打开控制台,看到返回的是预渲染好的html文件

image.png

目录结构

image.png

  • gridsome.config.js gridsome 的配置文件
  • gridsome.server.js 也是 girdsome 的配置文件,是配置服务端的,Gridsome 内部的服务配置。
  • Default.vue 中有个特别之处, query 就是专门查询gridsome数据给组件使用
  • components 放一些公共组件
  • static 静态资源
  • dist打包文件
<static-query>
query {
  metadata {
  siteName
  }
}
</static-query>

项目配置

查看Gridsome的配置

module.exports = {
  siteName: 'Grisome', // 页面上的名称
  pathPrefix: '/strapi', // 路径前缀, 部署是否有子目录
  templates: {}, // 定义路由模版
  configgureWebapck: {}, // type Object | Function webpack 配置
  siteDescription: '学习', // meta 名称
  plugins: [] // 配置插件
}

Pages

pages 就是我们项目当中的路由组件,最终会生成路由页面,在编译的时候会成为静态的HTML

两种创建方式

  • 基于文件创建 直接在pages文件下新建文件 例如demo.vue
  • 基于API创建
// gridsome.server.js 配置
api.createPages(({ createPage }) => {
   // Use the Pages API here: https://gridsome.org/docs/pages-api/
   createPage({
     path: '/demo',
     component: './src/templates/demo.vue'
   })
 })

动态路由 pages 下面创建的页面文件名称用方括号括起来,作为动态路由参数:src/pages/user/[id].vue

<template>
  <h1>
    User {{ $route.params.id }} Page
   </h1>
</template>

<script>
export default {
  name: 'UserPage'
}
</script>

API 创建

api.createPages(({ createPage }) => {
  createPage({
    path: '/user/:id(\\d+)',
    component: './src/templates/User.vue'
  })
})

添加集合

创建一个demo 组件

<template>
  <Layout>
      <h1>demo</h1>
      <ul>
      <li v-for="post in posts" :key="post.id">{{ post.title }}</li>
    </ul>
    </Layout>
</template>

<script>
import axios from 'axios'
export default {
  name: 'demo',
  data () {
    return {
      posts: []
    }
  },
  async created () {
    const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
    this.posts = data
  }
}
</script>

通过这种方式渲染不是静态化渲染的,它是在客户端动态加载的,我们需要用预渲染方式将数据渲染到页面中预渲染数据

// gridsome.server.js
const axios = require('axios')

module.exports = function (api) {
  api.loadSource(async ({ addCollection }) => {
    const collection = addCollection('Post')

    const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')

    for (const item of data) {
      collection.addNode({
        id: item.id,
        title: item.title,
        content: item.body
      })
    }
  })
}

在GraphQl中查询数据

访问 http://localhost:8080/___explore

query {
  post (id : 2) {
    id
    title
    content
  }
}

image.png

在页面中查询GraphQl

  • 组件中使用 <static-query></static-query>
  • 页面路由中使用 <page-query></page-query>
<template>
  <Layout>
      <h1>Posts2</h1>
      <ul>
        <li v-for="edge in $page.posts.edges" :key="edge.node.id">
          <g-link to="/">{{edge.node.title}}</g-link>
        </li>
      </ul>
    </Layout>
</template>

<script>
export default {
  name: 'Posts',
}
</script>

<page-query>
query {
  posts: allPost {
    edges {
      node {
        id
        title
      }
    }
  }
}
</page-query>

使用模版渲染节点页面

Templates for collections:配置路由模版

// gridsome.config.js
module.exports = {
  siteName: '拉钩教育',
  siteDescription: '大前端',
  plugins: [],
  templates: {
    Post: [
      {
        path: '/posts/:id',
        component: './src/templates/Post.vue'
      }
    ]
  }
}

创建一个Post.vue 预渲染页面,从GraphQL获取的数据

<template>
  <Layout>
    <h1>{{$page.post.title}}</h1>
    <p>{{$page.post.content}}</p>
  </Layout>
</template>

<page-query>
// ID! 不能为空,动态路由参数会自动传入进来
query($id: ID!) {
  post(id: $id) {
    id
    title
    content
  }
}
</page-query>

<script>
export default {
  name: 'PostPage',
  metaInfo () {
    return {
      title: this.$page.post.title
    }
  }
}
</script>