Search code examples
flutterflutter-webvercel

Flutter Web App not starting: The script has an unsupported MIME type


My flutter web app won't start, I see the following errors in the browser console:

enter image description here

This behavior only occurs when deployed on vercel. I don't get this error when deploying on firebase hosting.

Furthermore, this error only occurs for nested routes. It works when I open my deployed app without a subpath in the URL.

The error must occur somewhere in the loadEntrypoint function

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

Interesting here is that it says Failed to register a ServiceWorker for scope ('https://domainname.net/home/') even though I load the page https://domainname.net/home/questionnaire. In general I expect it would register the ServiceWorker at https://domainname.net but I don't know much about ServiceWorkers anyways...

I'm especially puzzled about this because this only happens on vercel but as the error occurs somewhere in web/index.js, it assume my hosting provider should have not influence on this behavior?

Any ideas?


Solution

  • I have found a solution to this problem.

    When I replace the script in my question above with the following script, it seems to resolve the issue.

        var serviceWorkerVersion = null;
        var scriptLoaded = false;
        function loadMainDartJs() {
          if (scriptLoaded) {
            return;
          }
          scriptLoaded = true;
          var scriptTag = document.createElement('script');
          scriptTag.src = 'main.dart.js';
          scriptTag.type = 'application/javascript';
          document.body.append(scriptTag);
        }
    
        if ('serviceWorker' in navigator) {
          // Service workers are supported. Use them.
          window.addEventListener('load', function () {
            // Wait for registration to finish before dropping the <script> tag.
            // Otherwise, the browser will load the script multiple times,
            // potentially different versions.
            var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
            navigator.serviceWorker.register(serviceWorkerUrl)
              .then((reg) => {
                function waitForActivation(serviceWorker) {
                  serviceWorker.addEventListener('statechange', () => {
                    if (serviceWorker.state == 'activated') {
                      console.log('Installed new service worker.');
                      loadMainDartJs();
                    }
                  });
                }
                if (!reg.active && (reg.installing || reg.waiting)) {
                  // No active web worker and we have installed or are installing
                  // one for the first time. Simply wait for it to activate.
                  waitForActivation(reg.installing ?? reg.waiting);
                } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
                  // When the app updates the serviceWorkerVersion changes, so we
                  // need to ask the service worker to update.
                  console.log('New service worker available.');
                  reg.update();
                  waitForActivation(reg.installing);
                } else {
                  // Existing service worker is still good.
                  console.log('Loading app from service worker.');
                  loadMainDartJs();
                }
              });
    
            // If service worker doesn't succeed in a reasonable amount of time,
            // fallback to plaint <script> tag.
            setTimeout(() => {
              if (!scriptLoaded) {
                console.warn(
                  'Failed to load app from service worker. Falling back to plain <script> tag.',
                );
                loadMainDartJs();
              }
            }, 4000);
          });
        } else {
          // Service workers not supported. Just drop the <script> tag.
          loadMainDartJs();
        }
      </script>
    

    Unfortunately, I have not really found out what exactly the problem was and why this is fixing it but I noticed this issue was occurring only since I updated my flutter version and regenerate my index.html. The script I'm now using is the script used by an older flutter version. I'm not sure if this has other effects but for now I'm going with the older script.