Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Legacy JS support (fixes #12) #6265

Open
wants to merge 125 commits into
base: main
Choose a base branch
from

Conversation

Tal500
Copy link
Contributor

@Tal500 Tal500 commented Aug 25, 2022

Brief

A feature-complete zero-configuration (JS output) legacy support of SvelteKit, by being compatible with the (potential) output of @vitejs/plugin-legacy.
Additionally, it applies legacy configurations and fixes some JS compatibility issues of kit.svelte.dev with legacy browser, so the official website wouldn't be totally unsupported by legacy browsers.

Online Demo

Please test in your legacy browsers and share the experience/bugs you have.

Def: legacy browser := any browser that doesn't fully supports the ES modules. (according to the vite legacy plugin)

closes #12
(Initiated by and) an alternative to #2745
A more robust alternative to PR #5417, thought I didn't cancel here the introduced changes by this external PR.
Probably closes the old sveltejs/svelte#3388.

Manual Testing

On the simple demo & the kit.svelte.dev website that will be described later:

  • IE11 - Works well (except minor styling issues in the simple demo, but bigger ones in kit.svelte.dev)
  • Chrome 15 (yes, that's old) - Works assuming you're willing to give up on the following Svelte features:
    • svelte/animation - The flip animation requires that the style will have the property transformOrigin, which isn't suppported (see caniuseit. We can try to patch Svelte to use webkit- prefix, but is it worth it?)
    • svelte/transition - For some reason I have encountered some "DOM Exception type 12" errors, don't know (and not sure I want to know) how to fix it except not using transitions at all.
    • svelte/motion - Before chrome 24, there is no support both for window.requestanimationframe() and window.performance.now(). There are polyfills for both of them, but the latter use the precision of Date.now() that is awful (for example the counter component on the simple demo uses svelte/motion.spring, and because the precision it's jumping crazy). For reference, the two polyfills are available here and here (the second one is actually ponyfill, meaning you'll need to overwrite window.performance to be the value of the exported object there by yourself, see the manual there).

I would like that other people here test the following demos on their machines and share their experience.

Demo

Notice: both of the demos are using postcss-preset-env for a limited support of CSS variables in legacy browsers.

Simple

A simple demo is available at this repository, together with an online preview in cloudflare pages (the same demo in the brief section). This demo also include some "patched css" to avoid forcing using CSS variables, when there isn't support, and additionally define and uses some polyfills.
After cloning, to run the demo, execute pnpm install && pnpm build && pnpm preview, and you can see the results both in modern browsers and in legacy ones (I used IE11 for testing).

Automated Testing using Selenium

If you like the demo, you can star it 🌟

kit.svelte.dev

  1. Pull/Clone/degit this PR.
  2. Navigate in this repo to sites\kit.svelte.dev.
  3. Run pnpm install && pnpm build && pnpm preview.
  4. Check the result in any legacy/modern browser you'd like.

Automated Testing (of kit package itself)

It is automatically get tested using Playwright and a custom HTTP middleware that replaces the <script> tags to simulate legacy browsers behavior (with similarity to Vite plugin-legacy internal tests). Didn't want to introduce here a new&heavy Selenium dependency thought, so I left this heavy tool for the simple demo.

In addition, I used eslint-plugin-compat (which uses caniuseit) to verify that all the JS code of the kit package is using an expected JS features, to check that the user legacy builds won't break when modifying kit package code (by accidentally adding an unexpected modern JS feature). Still it's not complete, because the Svelte team need to decide on an official browser support table (but now it's much easier with this feature).

Issue of Vite

Update: Only one open issue about web workers legacy support, that we can leave with right now in my opinion, together with the rest of the Vite community:
vitejs/vite#10383 - Web workers aren't being built well for legacy. This means for example that on legacy browsers that supports web workers (e.g. IE11), the search bar on kit.svelte.dev won't work, see the discussion on the review here #6265 (comment) for more details.

Inner Details

This PR enable legacy support without any new configuration of SvelteKit, it is just make things to be compatible with vite legacy plugin if the user uses it in vite.config.js.
The way it works is by looking at the generated Vite manifest, and check the following legacy assets that the vite legacy plugin might output:

  1. legacy entry (the legacy version of start.js)
  2. legacy polyfills
  3. modern polyfills

Then, on server side HTML rendering, it inject the correct HTML script tags, according to what that is available, in a similar fashion to the injection of the vite legacy plugin. (Vite legacy plugin inject the scripts to the output HTML, but the output HTML is getting wiped up by SvelteKit, so this PR (hopefully) injects the correct script tags in all use cases).

This PR also solves some minor legacy compatibility issues in SvelteKit client-side routing, that cannot be fixed by polyfills.

Notice: No legacy support for dev mode. It was a decision of the creators of the vite legacy plugin.

As you can see in the demos, I suggest for end users to use the following Vite configuration with this additional polyfills, that are needed to make SvelteKit to work:

import { sveltekit } from '@sveltejs/kit/vite';
import legacy from '@vitejs/plugin-legacy';

/** @type {import('vite').UserConfig} */
const config = {
	plugins: [
		sveltekit(),
		legacy({
			// For complete list of available options, see:
			// https://www.npmjs.com/package/@vitejs/plugin-legacy#Options
			targets: ['ie >= 11'],
			additionalLegacyPolyfills: [
				'custom-event-polyfill',
				'core-js/modules/es.promise.js',
				'whatwg-fetch',
				// 'global-this' should be used so 'regenerator-runtime' wouldn't do CSP issues
				'core-js/proposals/global-this',
				'regenerator-runtime/runtime',
				'unorm',
				'path-composedpath-polyfill',
				'proxy-polyfill/proxy.min.js'
			]
		}),
	]
};

export default config;

and add also the following code at the head of script of the root +layout.svelte file:

// Loading first polyfills that are shared between for legacy&modern browsers.
import 'abortcontroller-polyfill';
import 'intersection-observer';

Important: You'll need to have this additional legacy polyfills installed as dev dependancies, as Vite plugin-legacy compiles them internally with an import directive. In this case, these additional legacy polyfills can be installed via (assuming you use pnpm):
pnpm install -D custom-event-polyfill whatwg-fetch regenerator-runtime unorm path-composedpath-polyfill proxy-polyfill abortcontroller-polyfill intersection-observer

As said above, I also fixed some JS issues on legacy browsers, to make kit.svelte.dev to work (no work where done to fix legacy CSS issues). You might want to accept this PR without the changes to this site, but I don't recommend to.

Personal Experience and Opinions

It was a long journey to start understanding 3rd parties logic and bugs.

I think legacy support is crucial for many users (including me), especially by the extreme definition of legacy I gave above (not fully supporting ES modules), even if you decide to "give up on IE11". The lack of legacy support in SvelteKit made me actually use only Sapper (until now!), since I love Svelte.
The reason I believe this feature is more important than other ones (such as i18n), is because the latter can be implemented by the end user or 3rd library, but legacy is (almost) impossible.

I'm very glad that the code change that is needed for legacy support is relatively minor, since the vite legacy plugin do all the hard work, although it was hard to figure out how to connect to its output correctly, and to fix 3rd party issue.

Automatic Notes (Yey! All done!)

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. All changesets should be patch until SvelteKit 1.0

smertelny and others added 26 commits November 5, 2021 00:10
…o legacy-builds.

Not working so well by far...
Dev mode has so much just thought, need to clean up the code.
@changeset-bot
Copy link

changeset-bot bot commented Aug 25, 2022

🦋 Changeset detected

Latest commit: 0dfc032

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@UnrilWever
Copy link

Why hasn't it been merged yet?

@Tal500
Copy link
Contributor Author

Tal500 commented Mar 27, 2023

Why hasn't it been merged yet?

See #6265 (comment), hope that it will be merged (or will be implemented in a different way).

@jokin
Copy link

jokin commented Mar 28, 2023

I've created tvkit a proxy server that transforms a vite dev server into something that can be processed by older browsers.

Start your dev server normally and then run:

npx tvkit@latest serve --browser "ie 11"

Now you're able to access your SvelteKit dev server in an older browsers on http://localhost:3000/

If your building using the adapter-static, tvkit also has an experimental build command to process the generated static build:

npx tvkit@latest build ./build --out ./dist --browser "ie 11"

wow, this is really nice since I had to use the full build and preview server to test the tv portal on the devices. Yes, i'm another one developing tv portals which in my case, are constrained to chrome 49 or Opera browser equivalent. an we have to support thousands of devices already deployed, but even the new ones still came with old browser versions, it's an industry that goes forward very slowly. Maybe we could have a side chat for tips and tricks to develop for this kind of smart devices.

@sdekna
Copy link

sdekna commented Apr 14, 2023

Any updates on this PR? It is really frustrating to not be able to support legacy browsers.

7antra

This comment was marked as spam.

@aslak01
Copy link

aslak01 commented Oct 8, 2023

Any news on this?

@nostrorom
Copy link

nostrorom commented Jan 19, 2024

Intro

Hi,

I am part of the frontend dev team of the radiofrance website, we have tried in the past to support this issue being merged (through various likes, messages or approvals) without success, so I would like to make a more detailed case. Apologies in advance for the wall of text.

Context

We had last week to rollback our migration to SvelteKit 2.x, probably due to this issue #11658 - the OP is another team member at radiofrance

While those two issues are unrelated technically, this has renewed internal discussion about backwards compatibility, which leads back to this issue, which came to light for us when migrating to SK 1.x, where we had to drop support for some OS/browsers (more below)

Stakes

At radiofrance we have been early adopters of Svelte (Sapper days), and some of the key factors (apart from the sweet DX) was the light bundle size and general lightness of the app; because of the following:

Environmental responsibility

We are a heavy traffic website

  • ~25m monthly visits
  • ~9m monthly unique users

so lightness is of importance.

The key point here though is that another main lever of environmental impact is when devices become incompatible with what the users want to access, they have to replace them thus creating electronic waste. Losing backwards compatibility for a small fraction of our users may translate to a non-trivial number of devices becoming unusable to access our service.

Social responsibility

As a Public Service Broadcaster, it is our responsibility and duty to provide access to our information and other programmes to the highest proportion of the population as possible. Remote areas with low bandwidth, people who can't afford to upgrade their devices frequently or use second hand devices, people who are environmentally conscious and limit as much as they can their consumption of devices, non-tech-fluent people who tend to stick with the basic computer/browser they know how to use, etc.

Challenges

On our side we are also confronted with legacy compatibility in general, not only directly about this issue but also any other design/tech choices we make. This is always an on-going conversation, of having to find the right balance of legacy compatibility vs effort needed to do so vs impact on code length or available features: we are aware of the tradeoffs that these questions require.

Impact

For us, this open issue has meant losing support for Safari 13.x when migrating to SK 1.x. We have strongly considered rolling back, judging that a 2019 browser should still be supported on our end. Due to Apple's policy, some devices can't upgrade higher to a certain MacOS version, which in turn means a maximum Safari version. Hence the device impact mentioned above.

We were hoping for this fix to be merged so as to regain compatibility before fully losing our users.

Moving forward

We reckon that those are issues that the Svelte team cares about as well, for the same or other reasons. We are regularly checking out if this issue (or related) moves forward, e.g. this #11643 that for different reasons is supporting the current PR to be merged.

Quoting part of this reply #11643 (comment) from @antony

The effort of supporting abandoned / non-compliant browsers is monumental, and too time consuming to maintain for this small team. We simply can't afford to pay the ongoing price for somebody else's failures.

As said above, we understand that maintaining full compatibility with legacy OS/browser is a sizeable task, but in this matter we do feel that the trade-off is favorable, with @vitejs/plugin-legacy doing the brunt of the work, maintaining SvelteKit's compatibility with it is good return in effort invested for the gains in compatibility.

Our case is surely not the only one, but already with our footprint I hope you'll look favorably into moving this PR forward, and help us and others keep our environmental footprint in check. :)

Thanks for reading, cheers!

@Tal500
Copy link
Contributor Author

Tal500 commented Jan 20, 2024

Intro

Hi,

I am part of the frontend dev team of the radiofrance website, we have tried in the past to support this issue being merged (through various likes, messages or approvals) without success, so I would like to make a more detailed case. Apologies in advance for the wall of text.

Context

We had last week to rollback our migration to SvelteKit 2.x, probably due to this issue #11658 - the OP is another team member at radiofrance

While those two issues are unrelated technically, this has renewed internal discussion about backwards compatibility, which leads back to this issue, which came to light for us when migrating to SK 1.x, where we had to drop support for some OS/browsers (more below)

Stakes

At radiofrance we have been early adopters of Svelte (Sapper days), and some of the key factors (apart from the sweet DX) was the light bundle size and general lightness of the app; because of the following:

Environmental responsibility

We are a heavy traffic website

* ~25m monthly visits

* ~9m monthly unique users

so lightness is of importance.

The key point here though is that another main lever of environmental impact is when devices become incompatible with what the users want to access, they have to replace them thus creating electronic waste. Losing backwards compatibility for a small fraction of our users may translate to a non-trivial number of devices becoming unusable to access our service.

Social responsibility

As a Public Service Broadcaster, it is our responsibility and duty to provide access to our information and other programmes to the highest proportion of the population as possible. Remote areas with low bandwidth, people who can't afford to upgrade their devices frequently or use second hand devices, people who are environmentally conscious and limit as much as they can their consumption of devices, non-tech-fluent people who tend to stick with the basic computer/browser they know how to use, etc.

Challenges

On our side we are also confronted with legacy compatibility in general, not only directly about this issue but also any other design/tech choices we make. This is always an on-going conversation, of having to find the right balance of legacy compatibility vs effort needed to do so vs impact on code length or available features: we are aware of the tradeoffs that these questions require.

Impact

For us, this open issue has meant losing support for Safari 13.x when migrating to SK 1.x. We have strongly considered rolling back, judging that a 2019 browser should still be supported on our end. Due to Apple's policy, some devices can't upgrade higher to a certain MacOS version, which in turn means a maximum Safari version. Hence the device impact mentioned above.

We were hoping for this fix to be merged so as to regain compatibility before fully losing our users.

Moving forward

We reckon that those are issues that the Svelte team cares about as well, for the same or other reasons. We are regularly checking out if this issue (or related) moves forward, e.g. this #11643 that for different reasons is supporting the current PR to be merged.

Quoting part of this reply #11643 (comment) from @antony

The effort of supporting abandoned / non-compliant browsers is monumental, and too time consuming to maintain for this small team. We simply can't afford to pay the ongoing price for somebody else's failures.

As said above, we understand that maintaining full compatibility with legacy OS/browser is a sizeable task, but in this matter we do feel that the trade-off is favorable, with @vitejs/plugin-legacy doing the brunt of the work, maintaining SvelteKit's compatibility with it is good return in effort invested for the gains in compatibility.

Our case is surely not the only one, but already with our footprint I hope you'll look favorably into moving this PR forward, and help us and others keep our environmental footprint in check. :)

Thanks for reading, cheers!

Hi @nostrorom, thanks for the interest!

I am sadly don't have time to keep upgrading this PR and resolve conflicts, but I would like any support from everyone possible.

Specifically, until Svelte team will eventually support this issue(exactly like Vue that have a support for legacy), I can take and merge PR to my own proposed Github fork (that this PR is linked to).

I think have basically created a year ago good automatic system for testing and coverage for this - both by basic unit tests quering only via HTTP and full e2e test on IE11 and old Chromes on Selenium(thanks BrowserStack for their full support to free open-source softwares).

I might add you as a team member in my Github fork if needed.

@nostrorom
Copy link

Hi @Tal500 !

Thanks for the offer; feel free to add me as a team member. I don't have much availability in the very near future to work on this, but I will definitely want to help tackle the matter if the Svelte team don't :(

@leoj3n
Copy link
Contributor

leoj3n commented Feb 1, 2024

I needed to shim a polyfill for Array.prototype.at on older iPad devices. Unfortunately I ran into the problem this PR aims to solve in regards to using @vitejs/plugin-legacy with the latest version of Svelte.

For now I have added the following to my app.html which is working well:

<script src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.at"></script>

Just wanted to comment here in case https://polyfill.io/ helps anyone else out until this gets merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Differential legacy builds