설계할 때 고려해야 할 Firestore 오프라인에 대한 주의사항

7343 단어 FirebaseFirestoretech

개시하다


당초 온라인을 전제로 Firebase, Firestore를 사용하는 웹 애플리케이션을 제작했다.응용 프로그램의 일부 오프라인 대응이 편리하다고 생각해 오프라인 대응 수정을 추가하려 했으나 포기했다.

2021년 2월 24일 추기


문제 해결을 위해 역시 오프라인 처리가 추가됐다.
https://note.com/sushiwork/n/n548a2ce54b8e
내용은 보도의 마지막에 추가되었다.

오프라인에 대응하기 위해 설계 단계에서 오프라인 대응을 고려해야 한다


이번 경우 오프라인 대응은 필수적인 기능이 아니기 때문에 추후 추가 포기할 예정이지만, 오프라인 대응을 고려하는 경우 설계 단계에서 사전에 고려하지 않으면 이후 큰 재작업이 발생할 수 있다.
따라서 오프라인 대응을 하려면 처음부터 오프라인 기능을 켜서 개발하는 것이 좋다.

"Firestore 실천" 읽어주세요.


파이어스토어를 실천하는'제3장 오프라인 모드'에는 추가 오프라인 대응 시 고려해야 할 주의사항이 기재돼 있다.
3.1 오프라인 모드 사용
3.2 오프라인 상태에서 쓰기
3.3 오프라인 데이터 읽기
3.4 실시간 청취자
3.5 캐시 우선 읽기
이 책은 파이어스토어를 사용해 진정한 개발을 한다면 반드시 읽어야 할 책이다.특히 Firestore의 안전 규칙을 어떻게 써야 할지 고민이신 분들은 특히 추천해드립니다.이 책 덕분에 안전 규칙을 자신 있게 쓸 수 있게 됐어요.감사합니다, 작가님.
Firestore 실행(기술의 샘 시리즈 NextPublising)

서버Timestamp 트랩


기본적인 내용은'실천 파이어스토어'에 맡겼고, 책에 쓰지 않은 부분(일반적으로 생각)을 소개한다.말은 그렇지만 곰곰이 생각해 보면 당연하다.
Firestore에서 문서를 업데이트할 때 firebase.firestore.FieldValue.serverTimestamp() 를 사용하면 문서 열은 로컬 시간이 아닌 서버의 시간으로 업데이트됩니다.
Firestore의 오프라인 기능을 열 때 서버 Timestamp의 값은 요청한 시간(오프라인 상태에서 문서 업데이트를 실행하는 시간)이 아니라 오프라인 상태에서 온라인 상태로 회복하여 실제 등록을 하는 시간입니다.
생성된 프로그램에서 요청한 날짜와 시간을 등록하고 싶어서 오프라인에서 대응할 때 서버 Timestamp를 사용할 수 없습니다.그러면 어쩔 수 없습니다. 그래서 서버 Timestamp 사용을 중지하고 로컬 시간 등록을 생성하는 것을 논의했습니다.
하지만 이렇게 되면Firestore의 안전 규칙은 잘 쓰이지 않는다.나는 요청 날짜를 정확하게 확인하는 방법을 모른다.
서버 Timestamp를 사용할 때의 안전 규칙은 이렇게 쓸 수 있습니다
request.resource.data.hogeAt == request.time
창설된 프로그램에서 날짜와 시간의 정확성은 매우 중요하기 때문에 부정확한 날짜와 시간을 등록하면 불편하다.그래서 오프라인 처리를 포기했습니다.
또한 다른 지식으로 오프라인 상태에서 get으로 서버 Timestamp 업데이트를 추가한 문서를 가져오면 서버 Timestamp를 추가한 열의 값이 비어 있습니다.Firestore에 실제 등록하기 전에 서버 Timestamp의 열은null입니다.

Cloud Function을 사용하지 않으려면 합니다.


오프라인 처리를 하려면 Firebase Cloud Function을 사용하는 데 최소한의 시간이 필요합니다.https callable function은 온라인 상태에서만 사용할 수 있습니다.또한 Trigger function도 문서가 실제로 저장된 후에 실행되기 때문에 오프라인일 때 시작하지 않습니다.

개발 환경에서 오프라인 상태 재현


개발 환경에서 오프라인 상태와 온라인 상태를 간단하게 전환할 수 있다면 테스트가 비교적 쉽다.테스트를 위해 제작된 Vue 구성 요소를 미리 게재합니다.
'v-btn'과'v-btn-toggle'은 vuetify의 구성 부분이다.vuetify를 사용하지 않은 사람은 적당히 다시 쓰십시오.이 구성 요소, App.vue 등에 등록해서 사용하세요.

스크린



Vue 구성 요소 코드


NetworkToggleButton.vue
<template>
  <div v-if="showable">
    <v-btn-toggle v-model="networkStatus" tile color="primary" group>
      <v-btn value="enable" @click="enableNetwork">
        enaable
      </v-btn>
      <v-btn value="disable" @click="disableNetwork">
        disable
      </v-btn>
    </v-btn-toggle>
  </div>
</template>

<script>
// firestoreは、firebase.firestore()です。
// import文は、各自の環境に合わせて書き換えてください。
import { firestore } from "@/config/firebase";

export default {
  data: function() {
    return {
      showable: process.env.NODE_ENV === "development",
      networkStatus: "enable",
    };
  },
  methods: {
    enableNetwork: function() {
      firestore.enableNetwork().then(function() {
        // eslint-disable-next-line no-console
        console.log("Network enaabled");
      });
    },
    disableNetwork: function() {
      firestore.disableNetwork().then(function() {
        // eslint-disable-next-line no-console
        console.log("Network disabled");
      });
    },
  },
};
</script>
공식 문서:네트워크 액세스 비활성화 및 활성화

끝맺다


추가 오프라인 대응을 하지 못한 것은 아쉽지만, 이 기사가 효과를 냈으면 좋겠다.
제작 중인 앱도 곧 출시할 때가 되니 가능하면 트위터를 팔로우하세요!

2021년 2월 24일 추기 역시 오프라인 대응 추가


나는 추가된 내용을 기록할 것이다.

Firestore 의 오프라인 대응 설정


이 순서대로 진행할 필요가 있다.
캐시 설정은 자체 애플리케이션이 10MB 정도면 충분하므로 10MB를 설정합니다.
// この設定をuseEmulatorの後に行うと、useEmulatorの設定が打ち消されてしまう
firestore.settings({
  cacheSizeBytes: 10485760, // 10MB
});

if (process.env.NODE_ENV === "development") {
  firestore.useEmulator("localhost", 5050);
}

// firestore.useEmulatorの後に行わないと下記のエラーが出る
// Uncaught FirebaseError: Firestore has already been started and its settings can no longer be changed.
// You can only modify settings before calling any other methods on a Firestore object.
firestore
  .enablePersistence({
    synchronizeTabs: true,
  })
  .catch(function(err) {
    if (err.code == "unimplemented") {
      // The current browser does not support all of the
      // features required to enable persistence
      // eslint-disable-next-line no-console
      console.log("Offline support error.");
    }
  });
공식 문서
https://firebase.google.com/docs/firestore/manage-data/enable-offline?hl=ja

업데이트 처리를 성공의 전제로 바꾸기


Firestore의 오프라인 기능을 사용하면 오프라인 상태에서의 쓰기 처리가 대기열에 들어가고 온라인 복귀할 때 쓰기 처리를 실행합니다.쓰기 처리는 보안 규칙 등을 위반하지 않으면 성공하며, 쓰기 후의 처리는 실제 쓰기가 끝난 후가 아니라 끝난 후의 처리로 쓰기 처리된다.
구체적으로 다음과 같다.
  firestore
    .doc("aaa")
    .update(data)
    .then(() => {
      // 以前はここにupdate後のVuexのmutation処理を書いていた
    });
    
  // 成功する前提で、ここにVuexのmutation処理を書く
  commit(types.mutations.HOGE);

서버Timestamp 대신 로컬 시간 사용


여기에서 균형이 잡혔지만 오류 수정과 오프라인 대응을 우선적으로 진행했습니다. 서버 Timestamp를 사용하여 요청 시간을 저장하지 않고 로컬 시간을 사용했습니다.
보안 규칙에 대한 자세한 내용은 생략했지만 같은 문서에 있는 날짜와 시간의 데이터를 사용하여 응용 프로그램의 요구에 부합하도록 썼다.사용자의 요청 일자와 시간을 사전에 알지 못해 날짜를 정확히 확인할 수 없었으나 앱의 요청에 따라 허용 가능한 수준으로 적었다.
예를 들어 날짜와 시간의 안전 규칙에 대한 쓰기 방법을 설명해 보세요.
request.resource.data.startAt <= resource.data.startAt + duration.value(1, 'h')
를 쓰면 업데이트된 startAt는 업데이트 전 startAt부터 1시간 이내의 규칙을 쓸 수 있습니다.

이번에는 꼭 끝내야 돼요.


이번 경험을 통해Firestore의 오프라인 대응은 대응하는 전제에서 디자인하는 것이 좋다고 생각합니다.

참조 링크


https://developers-jp.googleblog.com/2019/10/why-is-my-cloud-firestore-query-slow.html
원인 2: 오프라인 캐시가 너무 크다
https://medium.com/firebase-developers/the-secrets-of-firestore-fieldvalue-servertimestamp-revealed-29dd7a38a82b
https://github.com/nuxt-community/firebase-module/issues/451#issuecomment-781636812

좋은 웹페이지 즐겨찾기