8.4.2 静态站点生成

本文为拉勾网大前端高薪训练营第一期笔记

什么是静态网站生成器

  • 静态网站生成器是使用一系列配置、模板以及数据,生成静态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学习建议

需要有一定的Vue基础

项目配置

gridsome.config.js

https://gridsome.org/docs/config/

module.exports = {
	siteName: '拉勾教育',
	siteDescription: '大前端',
	plugins: []
}

siteName是网页title "a - b"这里的b,同时也是header左上角的名称

siteDescription是网页meta description

Pages

https://gridsome.org/docs/pages/

两种选项创建页面,一种是文件系统

  • src/pages/Index.vue becomes /(The frontpage)
  • src/pages/AboutUs.vue becomes /about-us/
  • src/pages/about/Vision.vue becomes /about/vision/
  • src/pages/blog/Index.vue becomes /blog/

动态路由式

  • src/pages/user/[id].vue becomes /user/:id.
  • src/pages/user/[id]/settings.vue becomes /user/:id/settings.

一种是编程式

gridsome.server.js

module.exports = function (api) {
  api.createPages(({ createPage }) => {
    createPage({
      path: '/my-page',
      component: './src/templates/MyPage.vue'
    })
  })
}

动态路由例子

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

另外可以配置动态路由

https://gridsome.org/docs/dynamic-routing/

每页的meta info,gridsome通过vue-meta配置的




自己定义的404页面放这个路径

src/pages/404.vue

模拟数据接口 jsonplaceholder.typicode.com

加载外部数据

Data Store API添加集合

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

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

    const { data } = await axios.get('')

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

然后检查的方式是打开

//localhost:8080/___explore
//左边输入
query {
	post (id: 1) {
		id
		title
		content
	}
}

//或者查看所有文字
query {
	allPost {
		edges {
      node {
        id
				title
      }
    }
	}
}
//具体结构可以看右侧的docs

在页面中使用外部数据

https://gridsome.org/docs/querying-data/

举例




query {
  posts: allWordPressPost {
    edges {
      node {
        id
        title
				path
      }
    }
  }
}

想看静态外部数据的话,得npm run build看index.html才能看出效果

使用模板

//gridsome.config.js
module.exports = {
  templates: {
    Post: {
      path: '/posts/:id',
      components: './src/templates/Post.vue'
    }
  }
}

//templates/Post.vue
// ID!表示不能为空




query ($id: ID!) {
  post (id: $id) {
    id
    title
    content
  }
}





创建项目

gridsome create blog-with-gridsome
npm run develop

fork https://github.com/StartBootstrap/startbootstrap-clean-blog
git clone https://github.com//startbootstrap-clean-blog --depth=1

npm i bootstrap @fortawesome/fontawesome-free

/src/main.js
import 'bootstrap/dist/css/bootstrap.css'
import '@fortawesome/fontawesome-free/css/all.min.css'
import './assets/css/index.css'

/src/assets/css/index.css
@import url("https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic");
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800");

copy startbootstrap-clean-blog/css/clean-blog.css content to /src/assets/css/index.css

copy startbootstrap-clean-blog/index.html   page-header/main-content
to src/pages/index.vue template

copy startbootstrap-clean-blog/img to static

add leading / to "/img/home-bg.jpg" in index.vue

copy src/pages/index.vue navigation/footer to src/layouts/Default.vue template
navigation 和 footer 中继加

给pages/index.vue 加  Layout
删除page-query和styles

add pages/Post.vue
copy startbootstrap-clean-blog/post.html page-header/post-content to Post.vue
copy startbootstrap-clean-blog/about.html page-header/about-content to About.vue

add pages/Contact.vue
copy startbootstrap-clean-blog/contact.html page-header/main-content to About.vue

使用本地md文件当做数据来源

https://gridsome.org/docs/fetching-data/#markdown

//gridsome.config.js
module.exports = {
  plugins: [
    {
      use: '@gridsome/source-filesystem',
      options: {
        path: 'blog/**/*.md',
        typeName: 'Post',
      },
    },
  ],
};

strapi介绍

strapi CMS系统

https://strapi.io

跑起来可以通过页面上的内容类型生成器来添加类型

可以创建用户,设置权限,并且登陆后获取jwt token,header里放Authorization: Bearer

可以设置role,然后给用户关联role,这样做权限控制可以方便控制哪种role可以创建更新,权限控制很自由。

通过graphQL访问Strapi

https://strapi.io/documentation/3.0.0-beta.x/plugins/graphql.html

yarn strapi install graphql

可以创建tag这种数据类型,然后和post多对多关联

Gridsome用strapi的数据

安装@gridsome/source-strapi插件

分页

https://gridsome.org/docs/pagination/

//gridsome built-in pager component example usage





query ($page: Int) {
  allBlogPost(perPage: 10, page: $page) @paginate {
    pageInfo {
      totalPages
      currentPage
    }
    edges {
      node {
        id
        title
      }
    }
  }
}

展示文章详情

//gridsome.config.js
module.exports = {
  siteName: '拉勾教育',
  siteDescription: '大前端',
  plugins: [
    {
      use: 'gridsome-source-strapi',
      options: {
        apiURL: `http://localhost:1337`,
        queryLimit: 1000, // Defaults to 100
        contentTypes: [`post`],
        // typeName: 'Strapi',
        // plural: true, // pluralizes names of Content Types in API
        // Possibility to login with a Strapi user, when content types are not publicly available (optional).
        // loginData: {
          // identifier: '',
          // password: '',
        // },
      }
    }
  ],
  templates: {
    StrapiPost: [ //因为typeName+contentTypes
      {
        path: '/posts/:id',
        component: './src/templates/Post.vue'
      }
    ]
  }
}

处理markdown

读来数据以后用markdown-it处理一下,methods里增加一个mdToHtml的方法,最后v-html的时候调用一下

文章标签

//gridsome.config.js
templates: {
  StrapiTag: [ 
    {
      path: '/tags/:id',
      component: './src/templates/Tag.vue'
    }
  ]
}

//Tag.vue
//取数据部分

query ($id: ID!){
  strapiTag (id: $id){
    id
    title
    posts {
      id
      title
    }
  }
}

strapi里使用single types

唯一的数据类型,比如网站的主标题、副标题、封面

内容类型生成器里single type → create new single type

gridsome.config.js里plugins source-strapi singleTypes里设置你创建的类型

query {
	allStrapiGeneral {
    edges {
      node {
        id
        title
        subtitle
        cover {
          url
        }
      }
    }
  }
}

computed : {
	general () {
		return this.$page.general.edges[0].node
	}
}

Gridsome环境设置

https://gridsome.org/docs/environment-variables/

创建两个文件

.env.development

.env.production

GRIDSOME_API_URL=https://api.example.com
DB_USER=root
DB_PASS=s1mpl3

使用的时候

process.env.DB_USER

另外css里的url可以通过以下方式拿到

//src/main.js
export default function (Vue, {router, head, isClient}) {
	Vue.mixin({
    data() {
      return {
        GRIDSOME_API_URL: ProcessingInstruction.env.GRIDSOME_API_URL
      }
    }
  })
}

Vercel自动部署

https://vercel.com/

hook设置

在settings/git integration里

deploy hooks/create hook

hook name: deploy

git branch name: master

复制生成的钩子链接

然后去strapi设置里webhooks里添加

名称:deploy

请求地址:刚才复制的链接

事件挑需要的选

你可能感兴趣的:(前端,vue.js)