sveltejs/sapper

Usage of shimport makes legacy support prohibitively challenging

jacobmischka opened this issue Β· 16 comments

Shimport is a super neat project, but its critical integration in recent Sapper apps makes supporting IE11 very challenging. While shimport may work in legacy browsers when the APIs it uses are properly polyfilled, there's no convenient way currently to include such polyfills in Sapper apps, as Sapper uses shimport to load all of the user code.

The best method of working around this issue I've found is to include a polyfill.io script tag before %sapper.scripts%, but even so I've failed in coming up with the correct set of polyfills to include to get Shimport to work correctly.

Currently, I'm using the following features:

  • Blob
  • fetch
  • Promise
  • URL
  • Map
  • String.prototype.startsWith
  • Array.from
  • Array.prototype.keys (may be unnecessary)
  • classList (pretty sure unnecessary)

Resulting in the following script tag:

	<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=Blob%2Cfetch%2CPromise%2CURL%2CElement.prototype.classList%2CArray.prototype.keys%2CMap%2CArray.from%2CString.prototype.startsWith"></script>

Using these polyfills, I get an Unsupported BodyInit type error in IE11 when Shimport tries to load my client code, which seems to be caused when the fetch polyfill tries to use a body of type Blob. Am I missing any polyfills that would allow Shimport to work? Are there any other escape hatches I may be missing?

Ideally I'd like to remove the reliance on polyfill.io, as I fear it may not be polyfilling correctly which is what's causing the error, but I can't think of a better way to integrate polyfills before shimport is loaded using the current configuration options supported by Sapper. I'm currently using the rollup template, though I'd be happy to switch to webpack instead if that makes a workaround any easier.

An automatic workaround when compiling with --legacy would be amazing, but if we can come up with a manual one in the meantime that would be really great.

Thanks, as always!

Hey @jacobmischka, I'm also trying to make sapper works on IE11.
Your issue helped me understanding shimport, thanks !

I was able to solves the Unsupported BodyInit type error which was caused by polyfill.io 's implementation of fetch.
The workaround was to use github/fetch's implementation and keep polyfill.io for the dependencies of fetch.

I inserted this before %sapper.scripts%

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=Promise%2CURL%2CMap%2CArray.from%2CString.prototype.startsWith"></script>
<!-- polyfill.io's fetch fails with "Unsupported BodyInit type" in IE11 -->
<script src="https://unpkg.com/whatwg-fetch@3.0.0/dist/fetch.umd.js"></script>

However, there are other issues.

This config #626 (comment) also helped.

The spec: true parameter of @babel/preset-env config fixed the first issue: SCRIPT 1009: Expected '}' and leaved me with another error: TypeError: Cannot instantiate an arrow function

If we use core-js polyfill (version 2 or 3) with

useBuiltIns: 'usage',
corejs: 3 // or 2

We get an Object expected error.

Using

useBuiltIns: 'entry',
corejs: 3 // or 2

with an import of core-js in the client.js file leads to the TypeError: Cannot instantiate an arrow function error.

I made all these tests with the smallest "Hello world" example possible and with "ie >= 11" in the target's babel-preset-env config.

I don't know if the Object expected error is happening before the Cannot instantiate an arrow function one.

It's also really hard to get more details as we cannot see the source of the JS error as IE11 considers the file as "Blob" and won't show its content.

I'm getting similar problems. I started to switch from Svelte v2 to Svelte v3 in order to support IE11 as we are getting customer complaints, but to my surprise it still doesn't work.

The error I'm getting in my console is a bit different to the ones listed above:

SCRIPT1007: Expected ']'

_shimport__.define('http://mob.beyonk.com:1234/client/legacy/client.3ea0e0ca.js', [], function (__import, __exports){ [object Blob] });

This seeems like there might be a problem with Shimport?

After nearly a day of fiddling, I'm now at the same point as @gnuletik - so the above can be ignored. I think it was due to the polyfill.io version of Blob not loading, so I used the one here:

https://github.com/bjornstar/blob-polyfill

So now I'm stuck with the same "cannot instantiate an arrow function" error, and not being able to debug it because it's a blob.

thgh commented

My most crossbrowser tested app has this line:

<script>if(!window.Promise||![].includes||!Object.assign||!window.Map||!window.fetch){
document['wr'+'ite']('<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,fetch,Array.prototype.find"><\/script>')}</script>

It only loads the polyfill when needed and doesn't complain about document.write

@thgh Do you have a template repo / source code for your crossbrowser app?

I've tried your code above, and with an otherwise bare, unadulterated instance of sapper-template, I get "can't instantiate an arrow function".

For posterity: A couple of hours ago Shimport 1.0.1 was released, with a bug fixed that affects minified transpiled Svelte components. (export default( wasn't handled correctly by Shimport, and this code was produced, after minification, by Babel from export default class.) With this fix, and with a polyfill of https://cdn.polyfill.io/v2/polyfill.min.js?features=default,fetch,Array.prototype.find, a simple Sapper site seemed to run on IE11. There are still possibly other styling issues to work out. I'm not sure which of these are styles that don't work in IE and which are outright bugs in how Sapper handles styles when delivering the legacy build.

FWIW - There are nuances to getting things to work in both IE11 and Edge. You will have to run your production build through babel too, since Edge doesn't exactly support modern javascript, but yet doesn't need a legacy build.

I'm keeping track of my progress here:

https://github.com/antony/sapper-ie

There could be an argument to exclude IE11 (usage is getting pretty low?), but it could be disappointing to potential users to find that Sapper doesn't yet support Edge β€œin the box”.

I think the most popular similar frameworks generally treat Edge as an acceptably current evergreen browser to be included in automated testing of every commit/release. I wonder if that could be added to Supper.

@kylecordes IE11 has a worldwide usage of twice that of Windows Edge. If one is to be excluded, it would be Edge.

Having said that, these browsers are supportable, with a bit of effort, and they currently make up between 10% and 15% of traffic depending on country.

I'm not about to alienate 15% of my userbase, no matter how much I hate their life choices!

I work at a hospital system where most of the computers are still running Win7 and IE11. I unfortunately need IE11 support for most of my projects.

Btw, https://sapper.svelte.dev/ doesn't work in IE11.

@matyunya I don't think anybody using Svelte is using IE11 as their main browser!

@antony But if it did work it would probably be the first place for devs to check how it's done.

cbenz commented

#657 (comment) said that shimport 1.0.1 was released, but how to use it with sapper? Should we wait for sapper to be updated too, or is there a way to do?

Sapper depends on "shimport": "^1.0.0", so there's no need for Sapper to be updated as well. Your package manager will be able to update to Shimport 1.0.1 if you tell it to.

Should this issue be closed now that Shimport 1.0.1 has been released?

Antony has documented how to support IE here: https://github.com/antony/sapper-ie. Maybe that should also be in the main docs and tested here, but we could open a new issue for that. This one doesn't seem relevant anymore