Fauna, Netlify, Nuxt와 유사한 카운터 만들기

소개


내가 이 사이트를 세웠을 때, 나는 끊임없이 내가 주목하고 흠모하는 과학 기술자들로부터 영감을 찾았다.그 중 한 명은 조시 코모.
트위터).
그의 사이트에서 나는 아주 좋은 블로그를 읽었다. 제목은 Building a Modern-Day Hit Counter이다. 이것은 서버 기능이 없는 것과 FaunaDB가 Jamstack 사이트에서의 강력한 기능을 보여 준다.
그의 게시물은 주로React/Gatsby와 관련이 있지만 나는 그가 제공한 서버 개념과 코드를 사용하여 모든 블로그 게시물에'like'계수기(나의 예에서'voltage'계수기)를 만들어 멋진 디테일로 삼고 싶다(조쉬가 블로그 게시물에 올린'heart'계수기와 매우 유사하다).나는 또 그의 코드를 중복 사용하고 확장할 것이다. 그래서 나는 그에게 감사하고 싶다.
본고의 목적은 Netlify 함수와 FaunaDB를 사용하여 설정하고 이 도구를 이용하여 개인 Nuxt 블로그에 동적 "like"계수기를 구축하는 방법을 보여 주는 것입니다.
Fauna에 익숙하지 않다면 GraphQL API가 있는 서버 없는 지연 시간 없는 클라우드 데이터베이스입니다.우리는 블로그slug를 유일한 식별자로 사용하고 블로그 게시물마다'좋아요'계수를 저장합니다.

설치 프로그램


우리가 시작하기 전에, 우리는 데이터를 저장하고 검색하는 데 사용되는 플로라 계정 설정과 Netlify 계정을 확보해야 한다. 우리는 그 안에 응용 프로그램과 묶인 서버 없는 기능을 배치할 것이다.
그 밖에 블로그 내용을 관리하기 위해 헤아릴 수 없는 CMS를 선택해야 한다.나는 개인적으로 Nuxt Content를 사용하지만, 당신이 모든 블로그 게시물을 이용하거나 정의할 수 있다면!

동물군


일단 동물 계정을 만들면, 프로젝트에 로그인해서 새로운 데이터베이스를 만들고 싶을 것이다.

데이터베이스를 구축한 후에 우리는 모든 블로그 게시물의 좋아요를 저장하는 집합을 만들어야 한다."likes"라는 이름을 계속 만듭니다.

데이터베이스를 성공적으로 조회하기 위해서, 우리는 색인을 설정해야 한다.색인을 사용하면 문서 인용이 아닌 문서 속성에 따라 문서를 조회할 수 있습니다. 이것은 우리가 블로그slug를 사용하여 해당하는 like를 가져오고 업데이트할 때 매우 중요합니다.
우리는 그것들의 강도를 거의 모르기 때문에 Fauna's official documentation 이상의 색인을 마음대로 읽으십시오.slug라는 색인을 계속 만들고 우리의 likes_by_slug 집합을 원본 집합으로 사용하며 likes 는 우리가 검색할 수 있는 용어 중의 하나입니다.

너무 신기하다우리는 곧 도착할 것이다.이제 Nuxt 프로젝트에서 동물 데이터베이스를 안전하게 조회할 수 있는 API 키를 생성해야 합니다.Flora dashboard의 보안 부분을 탐색하고 새 관리 키를 생성합니다.

환경 변수 data.slug 를 사용하여 키를 참조합니다.

Nuxt 회사


너무 좋아요.우리는 이미 준비가 다 되었다.이제 Nuxt 프로젝트로 넘어가서 우리가 시작해야 할 의존 항목을 도입할 수 있습니다.
설치를 계속합니다Fauna npm package.
# install using npm
npm install --save faunadb

# install using yarn
yarn add faunadb
또한 API 요청을 처리하기 위해 Axios 을 사용하므로 Nuxt 모듈을 계속 설치합니다.
# install using npm
npm install @nuxtjs/axios

# install using yarn
yarn add @nuxtjs/axios
FAUNA_SECRET_KEY 파일에 추가합니다.
export default {
  modules: ['@nuxtjs/axios']
}
또한 프로젝트의 루트 디렉터리에 nuxt.config.js 파일을 만들고 이전에 생성한 Fanura API 키를 가져옵니다.
BASE_URL=YOUR_PROD_URL
FAUNA_SECRET_KEY=YOUR_KEY
너무 좋아요.마지막으로, 우리는 현재 .env 환경 변수를 사용하여 로컬 개발과 생산 배치를 위해 Axios 설정을 얻을 수 있다.
우리는 Nuxt의 Runtime Config 를 사용하여 설정을 처리할 것이다 Axios Options.이 행을 BASE_URL 파일에 추가합니다.
export default {
  publicRuntimeConfig: {
    axios: {
      baseURL: process.env.NODE_ENV === 'production' ? process.env.BASE_URL || 'http://localhost:8888/' : 'http://localhost:8888/',
    }
  },
}
Netlify 프로젝트를 로컬에서 실행할 때 Netlify Dev 포트에서 실행합니다.서버 기능이 없는 것을 테스트할 때 문제가 발생하지 않도록 Axios가 포트 nuxt.config.js 를 통해 호출하거나 로컬 개발 시 원하는 포트를 알려야 합니다.

Netlify 회사


만약 당신이 익숙하지 않다면Netlify functions, 그것들은 기본적으로 Netlify가 AWS Lambda 위에 있는 포장기(매우 아낌없는 무료층을 가지고 있다)이다.간단하게 말하자면, 그것들은 완전히 관리되고 자동으로 확장되는 서버 없는 기능으로 Netlify 프로젝트에만 적용된다.
우리가 배치한 사이트가 우리의 동물 데이터베이스를 성공적으로 조회할 수 있도록 Netlify로 이동하여 우리가 이전에 정의한 environment variables 를 추가하여 우리가 응용 프로그램을 배치할 때 사용할 수 있도록 해야 합니다!

또한 Netlify Dev 을 보십시오. 이것은 배치하기 전에 로컬에서 기능을 테스트할 수 있도록 합니다.이것은 디버그 기능과 UI를 할 때 많은 시간을 절약할 수 있다.이것은 과정이기 때문에 저는 그것을 소개하지 않겠지만 Netlify CLI 설정을 얻고 귀하의 사이트를 귀하의 프로젝트에 연결하는 것을 절대 권장합니다!
걸출했어우리는 현재 이미 필요한 설정을 완전히 완성했다.
우리는 Fauna가 우리의 "likes"저장소를 처리하고, Netlify 기능으로 Axios를 통해 데이터를 업데이트하고 검색합니다. Axios는 우리가 선택한 무두 CMS입니다. 물론 Nuxt도 있습니다!
코드를 깊이 연구할 때가 됐어!

우리의 함수를 작성하다


우리의 이러한 기능에 대한 수요는 두 부분으로 나눌 수 있다.
  • 현재 좋아하는 블로그를 페이지로 불러와야 합니다
  • 사용자가 우리의'좋아요'계수기
  • 를 눌렀을 때, 우리는 이 좋아요를 증가시킬 수 있어야 한다

    likes 함수 가져오기


    우리는 페이지에 불러올 때 (또는 구성 요소가 불러올 때) 우리의 블로그 8888 계수를 얻는 예부터 시작할 것이다.
    계속해서 Nuxt 프로젝트의 루트 디렉터리에 8888 라는 폴더를 만듭니다.Netlify는 배포할 때마다 서버 기능이 없는 곳을 자동으로 찾습니다.like 폴더에 functions 라는 파일을 만듭니다.
    // Credit to Josh Comeau 
    const faunadb = require('faunadb');
    exports.handler = async (event) => {
      const q = faunadb.query;
      const client = new faunadb.Client({
        secret: process.env.FAUNA_SECRET_KEY,
      });
    
      const { slug } = event.queryStringParameters;
      if (!slug) {
        return {
          statusCode: 400,
          body: JSON.stringify({
            message: 'Article slug not provided',
          }),
        };
      }
    
      const doesDocExist = await client.query(
        q.Exists(q.Match(q.Index('likes_by_slug'), slug))
      );
    
      if (!doesDocExist) {
        await client.query(
          q.Create(q.Collection('likes'), {
            data: { slug: slug, likes: 1 },
          })
        );
      }
    
      const document = await client.query(
        q.Get(q.Match(q.Index('likes_by_slug'), slug))
      );
    
      return {
        statusCode: 200,
        body: JSON.stringify({
          likes: document.data.likes,
        }),
      };
    };
    
    한번 훑어봅시다.
  • 우선 이전에 생성된 키
  • 를 사용하여 Flora 클라이언트를 초기화합니다.
  • 블로그slug가 검색 매개 변수로 제공되는지 확인하고 있습니다. 그렇지 않으면 400으로 되돌려줍니다.
  • 우리는 동물군의 파일이 이미 존재하는지 검사한다
  • 존재하지 않으면 fetch_likes_for_blog.js 집합에서 새 문서를 만들고 functions 를 유일한 식별자로 사용합니다.
  • 초기 like를 likes 로 설정합니다.
  • 우리는 1 이전에 만든 slug 인덱스를 조회하여 현재like
  • 를 검색합니다
  • 유사한 블로그로 돌아왔습니다
  • 점증likes 함수


    이 함수는fetch 함수와 매우 비슷하지만, 클라이언트에게 되돌려주기 전에 기존like계수를 추가해야 합니다.
    사용자가 블로그 게시물을 처리하는 아이콘/단추와 상호작용을 할 때 이 함수를 호출합니다.likes_by_slug 디렉토리에 slug 라는 새 파일 만들기
    // Credit to Josh Comeau
    const faunadb = require('faunadb');
    exports.handler = async (event) => {
      const q = faunadb.query;
      const client = new faunadb.Client({
        secret: process.env.FAUNA_SECRET_KEY,
      });
    
      const { slug } = event.queryStringParameters;
      if (!slug) {
        return {
          statusCode: 400,
          body: JSON.stringify({
            message: 'Article slug not provided',
          }),
        };
      }
    
      const doesDocExist = await client.query(
        q.Exists(q.Match(q.Index('likes_by_slug'), slug))
      );
    
      if (!doesDocExist) {
        await client.query(
          q.Create(q.Collection('likes'), {
            data: { slug: slug, likes: 1 },
          })
        );
      }
    
      const document = await client.query(
        q.Get(q.Match(q.Index('likes_by_slug'), slug))
      );
    
      await client.query(
        q.Update(document.ref, {
          data: {
            likes: document.data.likes + 1,
          },
        })
      );
    
      return {
        statusCode: 200,
        body: JSON.stringify({
          likes: document.data.likes,
        }),
      };
    };
    
    보시다시피 코드는 기본적으로 같습니다. 색인을 조회한 후에 문서에서 functions 를 실행하고 like register-like.js 를 추가합니다.

    Nuxt에서 함수 사용하기


    우리가 최종적으로 응용 프로그램을 배치할 때, 그것들은 경로: update 에서 우리에게 제공될 것이다.
    내 예에서 나는 VoltBatteryCounter 구성 요소를 만들어서 1 동적 블로그 페이지의 양쪽에 삽입했다.이 구성 요소에서, 나는 /.netlify/functions/NAME_OF_FUNCTION를 이용하여slug를 함수에 전달한다.
    나는 Nuxtpages/blog/_slug.vue 모드를 사용하기 때문에 fetch 갈고리와 this.$route.params.slug 집합을 이용하여 구성 요소를 설치할 때마다 갈고리를 호출하는 것이지 구축 기간에 한 번만 호출하는 것이 아니다.
    <script>
    export default {
      data() {
        return {
          initialLikes: null,
        }
      },
      async fetch() {
        const { data } = await this.$axios.get(`/.netlify/functions/fetch_likes_for_blog?slug=${this.$route.params.slug}`);
        this.initialLikes = data.likes;
      },
      fetchOnServer: false,
    }
    </script>
    
    그리고 사용자가 블로그 글 오른쪽에 설치된 배터리를 눌렀을 때마다, 나는 우리가 이전에 설정한 Axios를 사용하여 Servless 함수를 호출하여 like 계수를 증가시킨다.
    <script>
    export default {
      data() {
        return {
          initialLikes: null,
        }
      },
      async fetch() {
        const { data } = await this.$axios.get(`/.netlify/functions/fetch_likes_for_blog?slug=${this.$route.params.slug}`);
        this.initialLikes = data.likes;
      },
      fetchOnServer: false,
      methods: {
        addLike() {
          this.initialLikes++;
          this.incrementLikes();
        },
        async incrementLikes() {
          await this.$axios.post(`/.netlify/functions/register-like?slug=${this.$route.params.slug}`);
        }
      },
    }
    </script>
    
    하지만 누군가가 내가 좋아하는 버튼을 수천 번만 보내고 내 무료 기능층을 완전히 먹어치우기로 결정하면 어떻게 해야 할지 생각할 수도 있다.
    갈 수 있는 길이 몇 개 있다.그 중 하나는 일부 국부 상태, 예를 들어 staticfetchOnServer: false라고 불리는 계산 속성을 도입하는 것이다. 이 속성은 사용자가 계수기를 12배 정도만 증가시킬 수 있다.전임자:
    <script>
    export default {
      data() {
        return {
          initialLikes: null,
          userLikeCount: 0,
        }
      },
      async fetch() {
        const { data } = await this.$axios.get(`/.netlify/functions/fetch_likes_for_blog?slug=${this.$route.params.slug}`);
        this.initialLikes = data.likes;
      },
      fetchOnServer: false,
      methods: {
        addLike() {
          if(!likesMaxed) {
            this.initialLikes++;
            this.userLikeCount++;
            this.incrementLikes();
          }
        },
        async incrementLikes() {
          await this.$axios.post(`/.netlify/functions/register-like?slug=${this.$route.params.slug}`);
        }
      },
      computed: {
        likesMaxed() {
          return this.userLikeCount >= 12;
        },
      },
    }
    </script>
    
    그러나 사용자는 페이지를 다시 불러오고 계수기를 12배로 늘리기만 하면 된다.
    제 예에서 저는 userLikeCount를 사용하여 사용자가 블로그 게시물당 최대 12회까지만 비슷한 횟수를 늘릴 수 있도록 확보하기로 결정했습니다. 이것은 후속 페이지 방문까지 지속될 것입니다(이 생각은 덕분입니다!)

    로컬 저장소에 like 저장


    Nuxt 프로젝트의 likesMaxed 디렉터리에서 localStorage 라는 파일을 만들기 시작합니다.
    export const state = () => ({
      storedUserLikes: 1
    })
    
    export const mutations = {
      initializeLikes(state, slug) {
        const storedLikes = Math.abs(Number(localStorage.getItem(slug)));
    
        if(storedLikes) {
          storedLikes >= 12 ? state.storedUserLikes = 12 : state.storedUserLikes = storedLikes;
        } else {
          localStorage.setItem(slug, 1);
          state.storedUserLikes = 1;
        }
      },
      incrementLikes(state, slug) {
        state.storedUserLikes = state.storedUserLikes + 1;
        localStorage.setItem(slug, state.storedUserLikes);
      }
    }
    
    우선, 나는 로컬 저장소에서 관련 계수를 읽어서 페이지의like를 초기화합니다.
    사용자가 음수로 편집하지 않도록 절대값을 가져오기 위해 검사를 추가했습니다. 사용자가 무한히 클릭할 수 있도록 하고, 숫자가 12보다 큰지 확인하여storedLikes만 12로 설정합니다.
    현재, 우리는 이전의 코드를 확장하여 이 새로운 전역 상태를 이용할 수 있다.
    <script>
    export default {
      data() {
        return {
          initialLikes: null,
          userLikeCount: 0,
        }
      },
      async fetch() {
        const { data } = await this.$axios.get(`/.netlify/functions/fetch_likes_for_blog?slug=${this.$route.params.slug}`);
        this.initialLikes = data.likes;
      },
      mounted() {
        this.$store.commit('initializeLikes', this.$route.params.slug);
      },
      fetchOnServer: false,
      methods: {
        async addLike() {
          if(this.storedUserLikes < 12) {
            this.initialLikes++;
            this.$store.commit('incrementLikes', this.$route.params.slug);
            this.incrementLikes();
          }
        },
        async incrementLikes() {
          await this.$axios.post(`/.netlify/functions/register-like?slug=${this.$route.params.slug}`);
        }
      },
      computed: {
        likesMaxed() {
          return this.userLikeCount >= 12;
        },
        storedUserLikes() {
          return this.$store.state.storedUserLikes;
        }
      }
    }
    </script>
    
    우리는 우선 index.js 갈고리에서 우리의 Vuex 변이 store 를 호출합니다. 왜냐하면localStorage는 우리에게 사용할 수 있기 때문입니다. 그리고 우리는 계산 속성 initializeLikes 을 사용하여 이 블로그의 좋아요 (존재한다면) 를 검색합니다.
    경탄했어여러 세션과 페이지 접근을 지속할 수 있는 like 계수기가 있습니다.이것은 당신이 유사한 계수를 어떻게 과장하고 싶은지에 달려 있기 때문에 당신의 상상력을 발휘하세요!만약 당신이 나의 배터리와 유사한 일을 하고 싶다면, Github에서 나의 source code 코드를 보십시오. 왜냐하면 나는 이미 나의 사이트의 원본 코드를 개방하기로 결정했기 때문입니다.
    만약 당신이 더욱 전통적인'버튼을 좋아한다'는 외관을 좋아한다면, 여기에 간단한 순풍이 당신을 시작합니다!
    <template>
      <button @click="addLike" class="focus:outline-none" :class="{'text-red-600' : likesMaxed}">
        {{initialLikes}}
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>
      </button>
    </template>
    

    끝내다


    만약 네가 이 점을 할 수 있다면, 잘했어!나는 장래에 정적으로 생성된 Nuxt 사이트에서 유사한 동적 계수기를 더 많이 볼 수 있기를 간절히 바란다.
    만약 네가 정말로 하나를 실시하기로 결정한다면, 나는 네가 무엇을 생각해 낼 수 있는지 매우 보고 싶다.
    읽어주셔서 감사합니다!
    본문은 on my blog에 최초로 발표되었다

    좋은 웹페이지 즐겨찾기