React/Redux/redux-saga/TypeScript/Cloud Firestore/Cloud Function당을 사용하여 블로그를 만들었다!

안녕하세요, 아오키입니다.

이번에는 제목에도 있습니다.
React/Redux/redux-saga/TypeScript/Cloud Firestore/Cloud Function
당 기술을 사용하여
Atomic Design
같은 구성의
블로그 사이트를 작성했으므로, 궁리한 ​​점·고생한 점등 써 가면 좋겠습니다.

실제로 만든 사이트는 여기입니다.
오픈 소스이며 github 리포지토리는 여기입니다.

싹둑, 이런 느낌의 UI입니다 ↓


소개



여러분은 블로그를 쓰고 싶다! 라고 생각한 적이 있습니까?
인생에서 한 번 정도는 있지요. (?)

나에게도 그 시기가 왔습니다.

그래서, 나는 정말로 쓰려고 할까라고 생각했습니다.
모처럼의 기회이므로 스스로 오리지날의 블로그를 만들려고 생각했습니다.

아키텍처



올릴 필요 없을지도 모르지만 아키텍처는 이런 느낌입니다.



SPA 사이트에서 서버리스입니다.

Cloud Functions는 OGP 이미지 설정에만 사용됩니다.

또한 디자인 기법으로 Atomic Design을 채용했습니다.
Atomic Design의 경우 이 기사을 이해하기 쉽습니다.

주요 기능



이번에 작성한 블로그 사이트의 주요 기능은 다음과 같습니다.

· 기사 게시/편집/삭제/취득
· 태그 기능
· 좋아요 기능

뭐 보통의 블로그 사이트에는 있는 것 같은 기능이군요.
각각 간단하게 사용한 라이브러리 등을 설명합니다.

· 기사 게시 / 편집 / 삭제 / 표시



여기는 FireStore에서 제공하는 메서드를 두드리는 것입니다.
공식 문서에 자세히 작성되었습니다.

예를 들면 기사의 취득에 관해서, 이하와 같은 코드가 되어 있습니다.

모든 기사를 얻는 코드
export const getArticles = async () => {
  try {
    const articles: Model.Article[] = [];
    await firebase
      .firestore()
      .collection("articles")
      .orderBy("date", "desc")
      .get()
      .then(snapshot => {
        if(snapshot.empty) {
          return;
        }
        snapshot.forEach(doc => {
          articles.push({
            uid: doc.id,
            content: doc.data().content,
            subTitle: doc.data().subTitle,
            title: doc.data().title,
            date: doc.data().date.toDate(),
            tagIds: doc.data().tagIds,
            goodCount: doc.data().goodCount,
            thumbnailImagePath: doc.data().thumbnailImagePath
          });
        });
      })
      .catch(err => {
        throw new Error(err.message);
      });
    return { articles };
  } catch(error) {
    return { error };
  }
};


이 근처

⚠︎ 이 소스의 코딩이 Pest Practice 쓰는 방법은 아닙니다 (아래와 같이)

· 태그 기능



react-tag-input이라는 라이브러리를 사용했습니다.
아래와 같은 서제스트도 간단하게 구현할 수 있어 편리했습니다!


서제스트를 표시하는 코드
import React, { FC, useState, useEffect } from "react";
import { WithContext as ReactTags } from "react-tag-input";

// import css
import "./react-input-tag.css";

// import methods
import * as tagMethod from "methods/tagMethods";

// import models
import * as Model from "models/tagModel";

interface DefaultProps {
  onBlur: (tags: { id: string; text: string; }[]) => void;
  defaultTags?: Model.Tag[];
}

const KeyCodes = {
  comma: 188,
  enter: 13
};

const delimiters = [KeyCodes.comma, KeyCodes.enter];

const AdminCreateArticleTags: FC<DefaultProps> = ({ onBlur, defaultTags }) => {
  const [tags, setTags] = useState<Model.Tag[]>(defaultTags ? defaultTags : []);
  const [suggestions, setSuggestions] = useState<Model.Tag[]>([]);

  useEffect(() => {
    getData();
  }, []);

  const getData = async () => {
    const data = await tagMethod.getTags();
    setSuggestions(data);
  };

  const handleDelete = (i: number) => {
    setTags(tags.filter((tag: Model.Tag, index: number) => index !== i));
  };

  const handleAddition = (tag: Model.Tag) => {
    setTags([...tags, tag]);
  };

  const handleInputBlur = () => {
    tags.forEach(tag => {
      tagMethod.addTag(tag.text);
    });
    onBlur(tags);
  };

  const handleDrag = (tag: Model.Tag, currPos: number, newPos: number) => {
    const newTags = tags.slice();

    newTags.splice(currPos, 1);
    newTags.splice(newPos, 0, tag);
    setTags(newTags);
  };

  return (
    <ReactTags
      tags={tags}
      suggestions={suggestions}
      handleDelete={handleDelete}
      handleAddition={handleAddition}
      handleDrag={handleDrag}
      handleInputBlur={handleInputBlur}
      delimiters={delimiters}
    />
  );
};

export default AdminCreateArticleTags;



이 근처

· 좋아요 기능




↑같은 느낌으로, 좋아하는 수를 파악하기 위해, firestore에 하나 필드를 추가하고 있습니다.

그것을 갱신해 나가는 형태로 구현했습니다.

코드에 관해서는 기사 업데이트와 거의 다르지 않으므로 생략합니다.

개발해보세요



실은, 위에서 든 주요 기능 이외의 곳에도 고집하고 있어,

· 이미지를 압축하여 스토리지에 저장 (canvas를 이용하여 클라이언트 측에서 이미지를 압축)
· OGP 이미지를 위해 Cloud Functions 사용
· 쓸데없는 import를 줄이기 위해 동적 import를 채용
・기사를 5건 읽어들여, 스크롤에 따라 5건씩 취득하는 기능

등입니다.

이러한 기능군을 0부터 개인개발함으로써 성장할 수 있었습니다.

여러분도 뭔가 만들고 싶다! 라고 생각되는 것이 있으면 꼭 만들어보세요!

이상이 됩니다.

좋은 웹페이지 즐겨찾기