【静态站点(三)】之 Gridsome + Strapi + Vercel + Pm2 部署案例

文章前言

笔记来源:拉勾教育 大前端高薪训练营

阅读建议:内容较多,建议通过左侧导航栏进行阅读

Gridsome 案例

案例介绍

  • 使用第三方案例模板,嵌入到本次项目中

  • 模板地址:https://github.com/zimeng303/startbootstrap-clean-blog

    • 为防止项目作者的一些删除操作,建议将其 Fork 到自己的仓库中
  • 使用 git 将其下载到本地,--depth=1 表示下载最后一次更新的代码

    git clone git@github.com:zimeng303/startbootstrap-clean-blog.git --depth=1
    

基础实现

一、创建项目

  • 使用 gridsome 创建项目

    # 创建项目
    gridsome create #项目名称
    
    # 进入项目
    cd #项目名称
    
    # 启动项目(开发模式)
    npm run develop
    

二、基础配置

根据 startbootstrap-clean-blog/index.html,处理首页模板

  • 安装相关依赖

    npm i bootstrap @fortawesome/fontawesome-free
    
  • src/main.js 中,引入样式文件

    import 'bootstrap/dist/css/bootstrap.min.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');
    
    /* 将 startbootstrap-clean-blog/css/clean-blog.css 中的内容复制到下方 */
    

三、公共模板

  • 每个页面的 头部和底部都是一样的,只有中间部分不一样,因此将其公共部分提取出来

  • startbootstrap-clean-blog/index.htmlbody 部分的 NavigationFooter 内容,复制到 src/layout/Default.vue

  • src/layout/Default.vue,全局组件

    <template>
        <div class="layout">
    
            <!-- Navigation -->
            <nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
                ......
            </nav>
    
            <!-- 默认插槽 -->
            <slot/>
    
            <hr />
    
            <!-- Footer -->
            <footer>
                ......
            </footer>
        </div>
    </template>
    
    <style>
    </style>
    

四、首页模板

  • startbootstrap-clean-blog/index.htmlbody 部分的 Page HeaderMain Content 内容,复制到 src/pages/index.vue

    • src/pages/index.vue ,创建根节点
    • startbootstrap-clean-blog/img 目录拷贝到 static 目录下,并修改 url 路径,如下所示:
    <template>
        <Layout>
            <!-- Page Header -->
            <header class="masthead" style="background-image: url('/img/home-bg.jpg')">
              ......
            </header>
    
            <!-- Main Content -->
            ......
        </Layout>
    </template>
    
    • 其他页面模板,与首页模板相似

五、管理 md 数据

使用第三方插件管理文件,从而可以将 本地md文件中的内容 读取到 Graph QL 数据层

  • 安装插件

    npm install @gridsome/source-filesystem
    
  • gridsome.config.js 中,配置插件,并创建对应路径的 md 文件

    module.exports = {
        plugins: [
            {
                use: '@gridsome/source-filesystem',
                options: {
                    typeName: 'BlogPost',
                    // 抓取文件的路径,即抓取哪些文件
                    path: './content/blog/**/*.md',
                }
            }
        ]
    }
    
  • npm run develop,启动服务,报出如下错误:

    在这里插入图片描述

    提示我们,没有安装转换 markdown 的转换器,即 @gridsome/transformer-remark

  • 安装 @gridsome/transformer-remark 插件,它将 md 文件 转换为 HTML 文件

    npm install @gridsome/transformer-remark
    
  • 生成的数据格式,如图所示:

    在这里插入图片描述

Strapi

使用 Strapi 内容管理平台,对所需的数据进行配置,即添加 PostsTags 等集合数据。

预取数据

一、通过 GraphQL 访问 Strapi

基本使用

二、预取 Strapi 数据

借助于 gridsome 的插件,将 Strapi 数据集成到 Gridsome 应用中

  • 安装 @gridsome/source-strapi 插件

    npm install @gridsome/source-strapi
    
  • gridsome.config.js 文件中,配置插件信息

    module.exports = {
        plugins: [
            {
                use: '@gridsome/source-filesystem',
                options: {
                    typeName: 'BlogPost',
                    // 抓取文件的路径,即抓取哪些文件
                    path: './content/blog/**/*.md',
                }
            },
            {
                use: '@gridsome/source-strapi',
                options: {
                    apiURL: 'http://localhost:1337', // 接口地址
                    queryLimit: 1000, // Defaults to 100
                    contentTypes: ['post'], // 查询的数据类型
                    // singleTypes: ['impressum'], // 单个节点
                    // Possibility to login with a Strapi user,
                    // when content types are not publicly available (optional).
                    // loginData: { // 登录信息
                    //   identifier: '',
                    //   password: ''
                    // }
                }
            }
        ],
    }
    
  • 重新启动服务,访问 http://localhost:8080/___explore

    在这里插入图片描述

    注意:

    ​ 若 Strapi 中数据等被改变,必须重启 Strapi 项目,否则新数据无法同步预取到 Gridsome

具体实现

一、设计数据模型

  • 设计文章的字段,如图所示:

    在这里插入图片描述

  • 设计标签时,需创建一个 引用 字段,用于表示 标签和文章的关系

    在这里插入图片描述

  • 标签字段列表,如图所示:

    在这里插入图片描述

    注意:

    ​ 标签的数据也要向外暴露 Public,否则,无法访问

    在这里插入图片描述

二、展示文章列表

  • pages/index.vue 中,从 GraphQL 数据层 获取数据,进行页面数据动态渲染

    <template>
        <Layout>
            <!-- Main Content -->
            <div class="container">
                <div class="row">
                    <div class="col-lg-8 col-md-10 mx-auto">
                        <div class="post-preview" v-for="edge in $page.posts.edges" :key="edge.node.id">
                            <a href="post.html">
                                <h2 class="post-title">
                                    {{ edge.node.title }}
                                </h2>
                            </a>
                            <p class="post-meta">
                                Posted by
                                <a href="#">Start Bootstrap</a>
                                on {{ edge.node.create_at }}
                            </p>
                            <p>
                                <span v-for="tag in edge.node.tags" :key="tag.id">
                                    <g-link :to="'/tags/' + tag.id">
                                    	{{ tag.title }}
                                    </g-link>
                                </span>
                            </p>
    
                            <hr />
                        </div>
    
                        <!-- Pager -->
                    </div>
                </div>
            </div>
        </Layout>
    </template>
    
    <page-query>
     query {
        posts: allStrapiPosts {
        	edges {
        		node {
        			id
        			title  
        			created_at
        			tags {
        				id
        				title
        			}
        		} 
        	}
        }
    }
    </page-query>
    

三、文章列表分页

  • 参考网址:https://gridsome.org/docs/pagination/

  • 使用 Gridsome@paginate 指令,进行分页

  • pages/index.vue,分页的具体实现

     <!-- Pager -->
    <Pager :info="$page.posts.pageInfo" />
    
    <page-query>
    query ($page: Int) {
        posts: allStrapiPosts (perPage: 1, page: $page) @paginate {
            pageInfo {
                totalPages
                currentPage
            }
            edges {
                node {
                    id
                    title  
                    created_at
                    tags {
                        id
                        title
                    }
                } 
            }
        }
    }
    </page-query>
    
    
    <script>
    
    // 引入分页组件
    import { Pager } from 'gridsome'
    
    export default {
      components: {
        Pager
      }
    };
    </script>
    

四、展示文章详情

  • gridsome.config.js 中,配置模板

    module.exports = {
        templates: { // 配置模板
            // StrapiPost 表示 gridsome/source-strapi 插件生成的 
            // 集合名称:typeName + contentTypes
            StrapiPosts: [
                {
                    path: '/posts/:id',
                    component: './src/templates/Post.vue'
                }
            ]
        }
    }
    
  • ./src/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>
                            </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: strapiPosts (id: $id) {
            id
            title  
            content
            cover {
            	url
            }
            tags {
                id
                title
            }
        }
    }
    </page-query>
    

五、处理 md 文件

  • 参考网址:https://github.com/markdown-it/markdown-it

  • 借助 markdown-it 插件,将 md 格式的文件,转换为 HTML

  • 安装 markdown-it 插件

    npm install markdown-it --save
    
  • 将插件加载进来,进行转换

    <div class="col-lg-8 col-md-10 mx-auto" v-html="mdToHtml($page.post.content)">     
    
    <script> 
    import MarkdownIt from 'markdown-it'
    const md = new MarkdownIt()
    export default {
      methods: {
        mdToHtml (markdown) {
          return md.render(markdown)
        }
      }
    };
    </script>
    

六、文章标签页面

  • gridsome.config.js 中,添加 contentTypes,以及配置模板

    module.exports = {
        plugins: [
            {
                use: '@gridsome/source-strapi',
                options: {
                    contentTypes: ['posts', 'tags'], // 查询的数据类型
                }
            }
        ],
        templates: { // 配置模板
            // StrapiPost 表示 gridsome/source-strapi 插件生成的 
            // 集合名称:typeName + contentTypes
            StrapiPosts: [
                {
                    path: '/tags/:id',
                    component: './src/templates/Tag.vue'
                }
            ]
        }
    }
    
  • ./src/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 class="post-preview" v-for="post in $page.tag.posts" :key="post.id">
                            <g-link :to="'/posts/' + post.id">
                                <h2 class="post-title">
                                    {{ post.title }}
                                </h2>
                            </g-link>
                        </div>
                    </div>
                </div>
            </div>
        </Layout>
    </template>
    
    <page-query>
        query ($id: ID!) {
            tag: strapiTags (id: $id) {
                id
                title
                posts {
                    id
                    title
                }
            }
        }
    </page-query>
    

七、处理基本设置

  • strapi 中新增一个 Single Type(单一类型),名称为 General,并添加三个字段,如图所示:
    在这里插入图片描述

  • gridsome.config.js 的 plugins 选项中,进行配置

    module.exports = {
        plugins: [
            {
                use: '@gridsome/source-strapi',
                options: {
                    apiURL: 'http://localhost:1337', // 接口地址
                    queryLimit: 1000, // Defaults to 100
                    contentTypes: ['posts', 'tags'], // 查询的数据类型
                    // typeName: 'Strapi',
            		singleTypes: ['General'], // 单个节点
                }
            }
        ]
    }
    
  • src/pages/index.vue 中,读取 GraphQL 数据层 的数据,并在视图中渲染

      <!-- Page Header -->
      <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>
      
      <page-query>
          query ($page: Int) {
              ......
              allStrapiGeneral {
                  edges {
                      node {
                          id
                          title
                          subtitle
                          cover {
                          	url
                          }
                      }
                  }
              }
          }
      </page-query>
    

八、联系我页面

  • 查看页面布局,如图所示:

    在这里插入图片描述

  • strapi 中新增一个 Content Type(内容类型),名称为 Contact,并添加四个字段,如图所示:

    在这里插入图片描述

  • 使用 Postman ,测试接口是否可用,测试结果如下:

    在这里插入图片描述

  • 安装 axios,将添加用户输入信息

    npm i axios
    
  • src/pages/Contact.vue 中,添加方法,进行接口请求

    <script>
        import axios from "axios";
    
        export default {
            name: "ContactPage",
            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,
                        });
                        alert('发送成功')
                        this.$router.push('/')
                    } catch (err) {
                        throw new Error(err)
                    }
                },
            },
        };
    </script>
    

部署 Strapi

一、准备工作

  • 支持 Node 的服务器

  • 数据库 – 建议 MySQL 或者 MongoDB

  • 修改 config/database.js,将原来的 sqlite 的配置,修改为 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', 'blog'),
                    // 你的服务器中的数据库的用户名和密码
                    username: env('DATABASE_USERNAME', '远端服务器数据库用户名'),
                    password: env('DATABASE_PASSWORD', '远端服务器数据库密码'),
                },
                options: {},
            },
        },
    });
    
    
  • 修改 package.json,删除 sqlite3,添加 mysql,如图所示:

    在这里插入图片描述
    在这里插入图片描述

二、上传文件

  • 创建 GitHub 远程仓库,将本地代码上传到 GitHub 远程仓库

  • 连接服务器,并将代码克隆到服务器上

    git clone # 你的GitHub 仓库地址
    

    注意:

    ​ 如果觉得 Git 下载代码较慢,可以将文件压缩后,使用 FileZilla 上传到服务器上,然后在服务器上进行解压缩

  • 上传文件后,安装项目依赖

    npm i
    

    注意:

    ​ 如果安装依赖时,报出 permission denied 错误,解决方案:https://blog.csdn.net/zimeng303/article/details/113113546

  • 对项目进行打包构建

    npm run build
    
  • 启动项目

    npm run start
    

    注意:

    ​ 直接启动项目,会占用命令行应用,当退出时,则服务也会停止。因此,不建议使用。我们在此使用 pm2,详情参考

三、PM2 启动 web 服务

  • 配置网址:https://blog.csdn.net/zimeng303/article/details/112598948

  • 启动命令

    pm2 start npm -- start --name blog-backend
    

    服务启动成功,如图所示:

    在这里插入图片描述

  • 登录 服务器IP + 端口号(1337),将项目中所需的数据进行配置,如图所示:

    在这里插入图片描述

    注意:

    设置的必填字段,必须要填上数据,否则会报错。

  • 重要提示:

    • 角色和权限,必须要进行配置,否则无法调用接口

    在这里插入图片描述

本地服务联通远程 Strapi

具体实现

  • 1,创建 .env.development.env.production 环境文件,配置 GRIDSOME_API_URL,代码如下:

    GRIDSOME_API_URL=http://123.57.28.48:1337
    
  • 2,将 gridsome.config.js 中配置的 apiURL ,修改为环境变量 GRIDSOME_API_URL

     apiURL: process.env.GRIDSOME_API_URL, // 接口地址
    

Vercel – 部署 Gridsome 应用

使用 Vercel 进行静态应用项目的部署。

基本使用

  • 1,登录 Vercel,可以使用第三方账户,也可以自行注册(在此使用 GitHub 账户登录)

    在这里插入图片描述

  • 2,登录以后,新建项目

    在这里插入图片描述

  • 3,可以导入 Git 仓库,或者克隆其他模板(在此导入 GitHub 中已存在的仓库)

    在这里插入图片描述

  • 4,点击 Continue with GitHub,选择 GitHub 仓库,进行导入
    在这里插入图片描述

  • 5,点击 仓库名称 右侧的 import 按钮,进行导入,选择团队
    在这里插入图片描述

  • 6,展示基本配置,点击 Deploy` ,开始安装依赖,构建发布
    在这里插入图片描述

  • 7,最后,会自动弹框,点击 Visit,即可访问生成的静态站点

配置自动构建

当数据改变时,需要告诉 Vercel,触发自动构建。

  • 1,在 Vercel 中,找到构建的应用项目,然后点击进入
    在这里插入图片描述

  • 点击 Settings ,然后点击 Git,找到 Deploy Hooks
    在这里插入图片描述

  • 创建部署钩子,生成链接地址

    在这里插入图片描述

    生成的 Hook 地址,如图所示:

    在这里插入图片描述

  • 然后,进入 Strapi 内容管理平台,添加 Webhooks

    在这里插入图片描述

  • 填入名称、请求地址等,如图所示:

    • 请求地址,指的是在 Vercel 中生成的地址

      在这里插入图片描述

  • 最后,点击保存,在 Strapi 中,添加数据,进行保存发布后,回到 Vercel 的应用项目中,点击 Deployments

  • 项目正在被构建,如图所示:

    在这里插入图片描述

    注意:

    Vercel 页面可能会有延时,可以刷新 Vercel 页面。

完整代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值