Dev/Flutter

[Flutter] Web 업데이트 이후 캐시 문제

RaCoCeTTe 2023. 6. 15. 13:22
dvcs_client

Flutter Web 프로젝트를 새로 업데이트 하여 서버에 업로드 하였는데, 사용자가 사이트에 들어갔을때는 이전 버전의 웹사이트가 보였다..

 

이유는 캐시 문제.. 이전에 받은 플러터 파일이 사용자한테 남아 있어서 나오는 문제였다.

사용자한테 일일히 캐시를 제거해서 사용하라고 할 수도 없는 노릇

업데이트가 되면 새로운 버전으로 받게끔 만들어야한다.


1. Web Build

flutter build web

터미널에 해당 명령어를 입력하면 Web이 빌드가 되고 해당 파일은 "(현재 프로젝트 폴더)/build/web" 에 존재한다.

 

2. index.html 

"index.html" 파일을 열어보면

<!DOCTYPE html>
<html>
<head>
  <base href="/">
  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A new Flutter project.">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="dvcs_client">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">
  <link rel="icon" type="image/png" href="favicon.png"/>
  <title>dvcs_client</title>
  <link rel="manifest" href="manifest.json">
  <script>
    var serviceWorkerVersion = '3694318503';
  </script>
  <script src="flutter.js" defer></script>
</head>
<body>
  <script>
    window.addEventListener('load', function(ev) {
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        }
      }).then(function(engineInitializer) {
        return engineInitializer.initializeEngine();
      }).then(function(appRunner) {
        return appRunner.runApp();
      });
    });
  </script>
</body>
</html>

이런 구조로 파일이 형성되어 있는데 여기서

<script src="flutter.js" defer></script> → <script src="flutter.js?v=[원하는 값]" defer></script>

위와 같이 변경하면 된다.

[원하는 값] 에는 보통 버전을 명시하거나 자바스크립트의 time()함수를 이용 하여  항상 바뀌게 하는 방법이 있다.

 

참고로 "?v=1.2.3" 이런 형태는 예시일 뿐이고 "?c=1.2.3" , "?version=1.2.3" 등  원하는 형태로 작성하면 된다.

 

3. flutter.js

"index.html"에서 "flutter.js"만 변경하면 제대로 동작하지 않는다.

<script>
    window.addEventListener('load', function(ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        }
      }).then(function(engineInitializer) {
        return engineInitializer.initializeEngine();
      }).then(function(appRunner) {
        return appRunner.runApp();
      });
    });
  </script>

"index.html" 안에 해당 내용이 있는데 이는 "flutter.js"에 작성되어 있는 함수를 실행하여 "main.dart.js" 파일을 다운로드하여 불러오는 코드이다.

 

해당 코드가 불러오는 "main.dart.js" 파일도 캐시로 남아 있기 때문에 "main.dart.js"도 src를 변경해야 한다.

 

"flutter.js" 파일을 편집기에 열어보자.

편집기를 열고 위 스크립트에서 사용한 "loadEntrypoint" 함수를 찾으면 된다.

loadEntrypoint(options) {
      const {
        entrypointUrl = "main.dart.js",
        serviceWorker,
      } = (options || {});
      return this._loadWithServiceWorker(entrypointUrl, serviceWorker);
}
flutter sdk 버전마다 약간 차이가 있긴 하나 , 똑같으니 그대로 진행하면된다.

해당 함수를 2번과 같은 방식으로 진행하면 된다.

loadEntrypoint(options) {
      const {
        entrypointUrl = "main.dart.js?v=1.2.3",
        serviceWorker,
      } = (options || {});
      return this._loadWithServiceWorker(entrypointUrl, serviceWorker);
 }

 

꼭 "flutter.js"에서 작성한 "?v=1.2.3" 하고는 같을 필요는 없으나 관리 차원에서 같은 것으로 명시하는 것이 편하니,

같은 값으로 작성하는 것이 좋다.

 

 

 

이제 사용자가 굳이 캐시를 지우지 않아도 업데이트 시 웹사이트가 변경되었음을 알 수 있다.

끝!