Default starter for Gridsome
This is the project you get when you run gridsome create new-project
.
1. Install Gridsome CLI tool if you don't have
npm install --global @gridsome/cli
2. Create a Gridsome project
-
gridsome create my-gridsome-site
to install default starter -
cd my-gridsome-site
to open the folder -
gridsome develop
to start a local dev server athttp://localhost:8080
- Happy coding ????
項目搭建過程
-
項目初始化
- Fork此項目到自己的倉庫
- 將 Fork 到的項目添加到當前工作區,便于復制
- 安裝 bootstrap 和@fortawesome/fontawesome-free npm 方式
- 在 main.js 中加載全局樣式
- 加載谷歌字體 assets/css/index.css 中 @import 方式引入
- 引入樣式
- 將 index.html 中的內容復制到 pages/index.vue 中
- 啟動項目,訪問正常,需要復制圖片到 static/img/目錄下,修改圖片路徑為/
- 將<nav>和<footer>標簽放入 layouts/Default.vue 中,添加默認插槽<slot />
- 添加頁面 Post.vue、About.vue、Contact.vue,初始化頁面完成
-
使用本地 md 文件管理文章內容
- 在 GridSome 官網找到source-filesystem插件,轉化文件內容為可以在組件中使用 GraphQL 獲取的內容。
-
npm install @gridsome/source-filesystem
安裝 - 在 gridsome.config.js 的 plugins 中進行配置
plugins: [ { use: '@gridsome/source-filesystem', // 插件 options: { typeName: 'BlogPost', // 類型,對應GraphQL中的查詢 path: './content/blog/**/*.md', // 文件路徑 }, }, ],
- 創建 content/blog/article1.md 和 arttcle2.md 文件
- 重啟項目,報錯
Error: No transformer for 'text/markdown' is installed.
- 原因是需要 Gridsome 的 Markdown 變換器@gridsome/transformer-remark,安裝并重啟
- 打開 GraphQL 操作頁面,查詢數據得到結果,然后既可以渲染到頁面上
query { allBlogPost { edges { node { id path title content } } } }
使用 strapi 接口數據
-
快速開始安裝并啟動 strapi 應用,安裝成功打開http://localhost:1337/,創建 Content Type,比如 post,添加 id、title 和 content 字段
-
分配權限
需要給 publish 角色以下權限,就可在 postman 中使用
image-20210401081645397.png
-
-
使用 postman 測試,符合 REST API 的規范
image-20210401091814427.png
修改 Authenticated 權限,全選,添加用戶,設置角色為 Authenticated
-
在 postman 測試登陸
localhost:1337/auth/local { "identifier": "756638369@qq.com", "password": "123456" } { "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjE3MjM2NTM1LCJleHAiOjE2MTk4Mjg1MzV9.8Ha5sZxLwSKERdQH3OOvWU9qNsGw2fabpL4uxuChJvQ", "user": { "id": 1, "username": "wangxiang", "email": "756638369@qq.com", "provider": "local", "confirmed": false, "blocked": false, "role": { "id": 1, "name": "Authenticated", "description": "Default role given to authenticated user.", "type": "authenticated" }, "created_at": "2021-04-01T00:20:37.396Z", "updated_at": "2021-04-01T00:20:37.405Z" } }
得到 jwt 就可以請求了
可以使用 GraphQL 進行安裝,安裝 npm run strapi install graphql
安裝完成,打開 http://localhost:1337/graphql即可訪問
如何把 strapi 數據通過預取的方式集成到 gridsome 中,想要實現渲染前就拿到 strapi 中的數據,借助 gridsome 插件 strapi
-
使用
export default { plugins: [ { use: '@gridsome/source-strapi', options: { apiURL: 'http://localhost:1337', queryLimit: 1000, // Defaults to 100 contentTypes: ['article', 'user'], singleTypes: ['impressum'], // Possibility to login with a Strapi user, // when content types are not publicly available (optional). loginData: { identifier: '', password: '', }, }, }, ], }
重啟項目,啟動完成后就可以在 grapjQL 中訪問 strapi 中的數據了
-
strapi 新增或刪除數據后,gridsome 需要重啟項目,因為在啟動過程中拉取數據
image-20210401091814427.png
刪除 post,重新創建,添加字段 title、content、cover、is_publish、created_name 關聯 user
創建 tags
重啟 gridsome,發現報錯,因為沒有權限,重置 post 和 tag 的權限
-
修改頁面,添加查詢
<div v-for="item in $page.posts.edges" class="post-preview" :key="item.node.id" > <a href="post.html"> <h2 class="post-title"> {{ item.node.title }} </h2> <h3 class="post-subtitle"> {{ item.node.title }} </h3> </a> <p class="post-meta"> Posted by <a href="#" >{{ item.node.created_name.firstname + item.node.created_name.lastname }}</a > {{ item.node.created_at }} </p> <span v-for="tag in item.node.tags" :key="tag.id"> <a href="">{{ tag.title }}</a> </span> <hr /> </div> <page-query> query { posts: allStrapiPost { edges { node { id title created_name { id firstname lastname } created_at updated_at tags { id title } } } } } </page-query>
-
加載分頁組件
引入并注冊 Pager 組件,頁面中添加,查詢時添加 pageInfo
... <!-- Pager --> <Pager :info="$page.posts.pageInfo"/> ... query ($page: Int){ posts: allStrapiPost (perPage: 2, page: $page) @paginate{ pageInfo { totalPages currentPage } edges { node { id title created_name { id firstname lastname } created_at updated_at tags { id title } } } } } </page-query> import { Pager } from 'gridsome' export default { name: 'Home', components: { Pager }, }
-
加載文章詳情
修改 gridsome.config.js,添加 templates
// 詳情的模板頁面 根據對應內容類型創建模板 // 模板名稱StrapiPost一定要寫集合的名字 此時集合由'@gridsome/source-strapi'生成 templates: { StrapiPost: [ { path: '/post/:id', // 詳情對應路由 component: './src/templates/Post.vue', }, ] },
創建 templates/Post.vue 文章詳情模板
查詢數據,替換模板
<template> <Layout> <!-- Page Header --> <header class="masthead" :style="{ backgroundImage: `url(http://localhost:1337${ $page.post.cover.url })`, }" > <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="post-heading"> <h1>{{ $page.post.title }}</h1> <h2 class="subheading"> {{ $page.post.title }} </h2> <span class="meta" >Posted by <a href="#">{{ $page.post.created_name.firstname + $page.post.created_name.lastname }}</a> on {{ $page.post.created_at }}</span > </div> </div> </div> </div> </header> <!-- Post Content --> <article> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto" v-html="$page.post.content" ></div> </div> </div> </article> </Layout> </template> <page-query> query ($id: ID!){ post: strapiPost (id: $id) { id title content cover { url } created_name { id firstname lastname } created_at tags { id title } } } </page-query> <script> export default { name: 'Post', metaInfo: { title: 'Post', }, } </script> <style></style>
修改/pages/index.vue,a 標簽為 g-link 標簽
... <g-link :to="`/post/${item.node.id}`"> <h2 class="post-title"> {{ item.node.title }} </h2> <h3 class="post-subtitle"> {{ item.node.title }} </h3> </g-link> ...
-
處理 markdown 格式文檔
使用markdown-it處理 markdown 格式數據
<template> ... <div class="col-lg-8 col-md-10 mx-auto" v-html="mdToHtml($page.post.content)" ></div> ... </template> <script> import MarkdownIt from 'markdown-it' const md = new MarkdownIt() export default { name: 'Post', metaInfo: { title: 'Post', }, methods: { mdToHtml(markdown) { return md.render(markdown) }, }, } </script>
-
文章標簽
修改 gridsome.config.js,contentTypes 添加 tag
{ use: '@gridsome/source-strapi', options: { apiURL: 'http://localhost:1337', queryLimit: 1000, // Defaults to 100 contentTypes: ['post', 'tag'], // StrapiPost // typeName: 'Strapi', // singleTypes: ['impressum'], // Possibility to login with a Strapi user, // when content types are not publicly available (optional). // loginData: { // identifier: '', // password: '', // }, }, },
添加 tag 模板
StrapiTag: [ { path: '/tag/:id', // 詳情對應路由 component: './src/templates/Tag.vue', }, ]
創建/templates/Tag.vue 模板
<template> <Layout> <!-- Page Header --> <header class="masthead" style="background-image: url('/img/home-bg.jpg')" > <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1># {{ $page.tag.title }}</h1> </div> </div> </div> </div> </header> <!-- Main Content --> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div v-for="item in $page.tag.posts" class="post-preview" :key="item.id" > <g-link :to="`/post/${item.id}`"> <h2 class="post-title"> {{ item.title }} </h2> <h3 class="post-subtitle"> {{ item.title }} </h3> </g-link> <hr /> </div> <!-- Pager --> <Pager :info="$page.posts.pageInfo" /> </div> </div> </div> </Layout> </template> <page-query> query ($id: ID!){ strapiTag (id: $id) { id title posts { id title } } } </page-query> <script> export default { name: 'Tag', } </script> <style></style>
修改/pages/index.vue,a 標簽為 g-link 標簽
... <span v-for="tag in item.node.tags" :key="tag.id"> <g-link href="" :to="`/tag/${tag.id}`">{{ tag.title }}</g-link> </span> ...
-
基本設置
設置博客首頁標題、副標題和封面
處理網站標題和副標題、包括網站首頁封面,都可以統一管理起來,設計統一數據結構,在頁面展示即可
Content Type 相當于集合,而此時只需要創建單個的數據節點,選擇 Single Type
在 strapi 中新增一個 Single Type(單一類型),名稱為 General,并添加三個字段,title、subtitle 和 cover
保存成功后,在 general 中添加相應字段并保存,對其配置 find 權限
接著集成到網站當中去使用,配置 gridsome.config.js 的 plugins 選項
... { use: '@gridsome/source-strapi', options: { apiURL: 'http://localhost:1337', queryLimit: 1000, // Defaults to 100 contentTypes: ['post', 'tag'], // StrapiPost配置集合 // typeName: 'Strapi', singleTypes: ['general'], // 配置單節點 // Possibility to login with a Strapi user, // when content types are not publicly available (optional). // loginData: { // identifier: '', // password: '', // }, }, }, ...
在/pages/index.vue`中,讀取 GraphQL 數據層的數據,并在視圖中渲染
<template> <Layout> <header class="masthead" :style="{ backgroundImage: `url(http://localhost:1337${general.cover.url})`, }" > <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1>{{ general.title }}</h1> <span class="subheading">{{ general.subtitle }}</span> </div> </div> </div> </div> </header> ... </Layout> </template> <page-query> query ($page: Int){ ... allStrapiGeneral { edges { node { id title subtitle cover { url } } } } } </page-query> <script> ... // 使用計算屬性 computed: { general() { return this.$page.allStrapiGeneral.edges[0].node }, }, ... </script> <style></style>
-
聯系我頁面實現
使用純客戶端實現并將數據保存
創建contact集合,根據頁面需要添加name、email、phone和message字段,并賦予contact集合create權限
使用postman進行測試,localhost:1337/contacts添加數據并測試
修改/pages/contact.vue頁面
<template> <!-- 使用v-model綁定表單數據、并添加按鈕點擊事件 --> </template> <script> import axios from 'axios' export default { name: 'Contact', metaInfo: { title: 'Contact', }, data() { return { form: { name: '', email: '', phone: '', message: '', }, } }, methods: { // 此處應該加入表單校驗 async onSubmit() { try { const { data } = await axios({ method: 'POST', url: 'http://localhost:1337/contacts', data: this.form, }) this.form = { name: '', email: '', phone: '', message: '', } window.alert('發送成功') } catch (err) { window.alert('發送失敗') throw new Error(err) } }, }, } </script> <style></style>
部署strapi
需要支持 Node 的服務器
數據庫 – 建議 MySQL 或者 MongoDB寫給前端的MySQL極簡安裝
strapi默認使用 sqlite 數據庫,部署到線上時,不推薦使用
-
切換數據庫為mysqlconfigurations,將 config/database.js 替換為Mysql的配置
module.exports = ({ env }) => ({ defaultConnection: "default", connections: { default: { connector: "bookshelf", settings: { client: "mysql", host: env("DATABASE_HOST", "localhost"), port: env.int("DATABASE_PORT", 3306), database: env("DATABASE_NAME", "strapi"), username: env("DATABASE_USERNAME", "root"), password: env("DATABASE_PASSWORD", "329926"), }, options: {}, }, }, });
修改 package.json,添加 mysql 依賴
npm install mysql --save
,如果不需要測試,則可以刪除 sqlite3將項目上傳到遠程倉庫后臺項目地址
在服務器上克隆上傳到項目地址
git clone https://github.com/wang1xiang/blog-backend.git
安裝依賴
npm i
,打包項目npm run build
,啟動項目npm run start
可以使用pm2
pm2 start npm -- run start --name blog-backend
啟動項目,可以讓node應用跑到后臺安裝成功,打開
http://106.75.190.29/admin
訪問并重新加載數據
本地GridSome應用連接遠程服務器
-
修改gridsome.config.js
module.exports = { siteName: 'Gridsome', plugins: [ ... { use: '@gridsome/source-strapi', options: { apiURL: 'http://106.75.190.29:1337', queryLimit: 1000, // Defaults to 100 contentTypes: ['post', 'tag'], // StrapiPost配置集合 // typeName: 'Strapi', singleTypes: ['general'] }, }, ] }
-
apiURL可以使用環境變量的形式設定,配置環境變量,添加.env.development和.env.production
// .env.development GRIDSOME_API_URL=http://106.75.190.29:1337 // .env.production GRIDSOME_API_URL=http://106.75.190.29:1337 // gridsome.config.js { use: '@gridsome/source-strapi', options: { apiURL: process.env.GRIDSOME_API_URL, ... }, },
可以配置不同的ip地址,修改apiURL為process.env.GRIDSOME_API_URL,重啟
-
此時可以正常訪問網站,當時發現圖片加載有問題,需要設置圖片路徑,當然不能直接在模板中寫
process.env.GRIDSOME_API_URL
,使用mixin代替// main.js Vue.mixin({ data() { return { GRIDSOME_API_URL: process.env.GRIDSOME_API_URL, } }, })
使用ip的地方替換為GRIDSOME_API_URL即可
打開應用
http://localhost:8080/
訪問成功,圖片正常加載,此時已聯通GridSome客戶端和服務器的strapi
使用Vercel – 部署 Gridsome 應用
使用Vercel 進行靜態應用項目的部署
基本使用
使用gitHub登陸,選擇
Continue With GitHub
登陸成功,選擇
new Project
選擇Import Git Repository,添加自己的git倉庫,選擇項目導入import
-
如果不需要修改build和環境變量,直接選擇Deploy,等待Vercel部署打包完成
image-20210403163433202.png -
等待部署成功,點擊visit,即可訪問生成的靜態站點
image-20210403165828150.png
配置自動構建
配置strapi,當數據改變時,觸發Vercel自動構建
-
選擇項目blog-with-gridsome,選擇settings --> git --> Deploy Hooks,設置部署鉤子
image-20210403171715153.png
- 點擊create Hook,將生成的鉤子地址復制到strapi中
- 在strapi后臺項目中,選擇設置 --> Webhooks --> 創建新Hook,當數據更新操作時,請求webhooks,重新觸發構建
- 此時回到vercel,打開項目的Deployments部署記錄,修改數據,當前頁面會自動刷新
- 等待部署完成,有時頁面可能會有延時,需要手動刷新
使用GitHub Page+ GitHub Actions – 部署 Gridsome 應用
-
在gridsome.config.js中修改pathPrefix為github項目路徑
pathPrefix: 'blog-with-gridsome/' #項目地址
-
重新打包,取消
.gitignore
中的dist
,將dist目錄上傳到遠程分支git subtree push --prefix dist origin gh-pages
-
項目對應的settings,GitHub Pages會自動加載gh-pages下的分支,點擊上面的連接訪問網站
image-20210403180137115.png
-
配置GitHub Actinos自動部署
個人設置 --> Personal access tokens --> New personal access token
img -
github對應項目 --> Settings --> New Secrets,添加剛剛生成的token
img .github/workflows/deploy.yml
name: GitHub Actions Build and Deploy Demo
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@master
env:
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
BRANCH: gh-pages
FOLDER: dist
BUILD_SCRIPT: npm install && npm run build
-
重新修改代碼,并提交,可以看到actions中的狀態
image-20210403182638066.png