message: Make hot reloading more reliable
diff: @@ -33,7 +33,7 @@ type Message =
  run();
  -function run({retry = 0} = {}) {
  +function run() {
  const {host, port} = options.webSocket;
  if (host === '*') {
  @@ -43,11 +43,34 @@ function run({retry = 0} = {}) {
  }
  let open = false;
  + let retry = 0;
  +
  + const cleanupActions = new Set<() => void>();
  +
  + connect();
  +
  + function cleanup() {
  + for (const action of cleanupActions) {
  + action();
  + }
  +
  + cleanupActions.clear();
  + }
  +
  + function connect() {
  const socket = new WebSocket(
  `${options.https ? 'wss' : 'ws'}://${host}:${port}`,
  );
  - socket.addEventListener('close', () => {
  + const handleOpen = () => {
  + open = true;
  + retry = 0;
  + log('listening for changes...');
  + };
  +
  + const handleClose = () => {
  + cleanup();
  +
  if (retry > MAX_RETRIES) {
  log(`ending reconnect after ${MAX_RETRIES} attempts`);
  return;
  @@ -56,31 +79,26 @@ function run({retry = 0} = {}) {
  if (open) {
  open = false;
  log('lost connection to asset server, trying to reconnect...');
  - run();
  + connect();
  } else {
  const timeout = 1000 * retry ** 2 + Math.random() * 100;
  + retry += 1;
  log(`attempting reconnect in ${timeout / 1000}s`);
  setTimeout(() => {
  - run({retry: retry + 1});
  + connect();
  }, timeout);
  }
  - });
  + };
  - socket.addEventListener('message', (event) => {
  + const handleMessage = (event: MessageEvent<any>) => {
  const message = JSON.parse(event.data) as Message;
  switch (message.type) {
  case 'ok':
  case 'warnings': {
  - if (open) {
  reload();
  - } else {
  - open = true;
  - log('listening for changes...');
  - }
  -
  break;
  }
  case 'window-reload': {
  @@ -102,12 +120,25 @@ function run({retry = 0} = {}) {
  break;
  }
  }
  + };
  +
  + socket.addEventListener('open', handleOpen);
  + socket.addEventListener('close', handleClose);
  + socket.addEventListener('message', handleMessage);
  +
  + cleanupActions.add(() => {
  + socket.removeEventListener('open', handleOpen);
  + socket.removeEventListener('close', handleClose);
  + socket.removeEventListener('message', handleMessage);
  + socket.close();
  });
  }
  function reload() {
  + cleanup();
  self.shopify.reload();
  }
  +}
  function log(message: string) {
  // eslint-disable-next-line no-console
  