Skip to content

Examples and Analysis of Low version Browser Compatibility with Vite

Gookyn edited this page Oct 31, 2022 · 2 revisions

Dependency versions:

  • vite: v2.9.4
  • @vitejs/plugin-legacy: v1.8.1

Compatible with legacy browsers and modern browsers

Target

Compatible browsers and versions

  • IE11: legacy browser
  • Chrome 64: The lowest version of the modern browser
  • Chrome 106: The latest version of the modern browser

Test the JS API

globalThis

image

Array.includes

image

Test cases

// main.ts
import './play-global-this';
import './play-array';
// play-global-this.ts
export const playGlobalThis = () => {
  console.log('globalThis.Array ==> ', globalThis.Array === Array);
};

playGlobalThis();
// play-array.ts
export function playArray() {
  console.log('array.includes ==> ', [1, 2, 3].includes(3));
}

playArray();

Compatible with legacy browser configurations only

1. Configuration options

// vite.config.ts
import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';

export default defineConfig({
  base: './',
  build: {
    target: 'es2015',
  },
  plugins: [
    legacy({
      targets: ['ie >= 11'], // expected compatible browser target range
      renderLegacyChunks: true, // need to generate legacy browser compatible chunks (default true)
      modernPolyfills: false, // no need to generate polyfills block for modern browsers (default false)
    }),
  ],
});

2. Build log

Note: If you want to display the following results, you need to set the process.env.DEBUG environment variable.

image

Due to the renderLegacyChunks: true and modernPolyfills: false settings, only the polyfills required by legacy browsers are loaded when building; and the polyfills that are actually used (global-this, array.includes) will be loaded.

Note: Other polyfills, some are the default values set by @vitejs/plugin-legacy, such as the source code: image

3. Build output file

image

  • The file with the name -legacy is the file that the legacy browser needs to load
  • polyfills-legacy is the polyfills file that legacy browsers need to load

4. index.html

image

In index.html, there will be two parts of logic for loading JS scripts, and different logics are executed according to whether the browser supports ESM:

  • Browsers that support ESM <script>: load js files via <script type="module">

image

  • Browsers that do not support ESM <script>: additionally load the js file corresponding to -legacy through <script nomodule>

Both types of files are loaded, but the -legacy file is actually executed

image

In addition, you can note: Since ESM is not supported, in the <script nomodule> script, System is used to load the module.

image

5. Visit the page

Chrome 106

The output is correct:

image

Load the file as high version js:

image

Chrome 64

Output error:

Reason: No polyfills block generated for low-version modern browsers!

image

Load the file as high version js:

image

IE11

The output is correct:

image

Load file:

Additional loaded -legacy files, including polyfills.

image

6. Conclusion

With the default configuration, it is compatible with legacy browsers, but not modern browsers with lower versions.

Increase compatibility with low-version modern browser configuration

1. Configuration options

// vite.config.ts
...
legacy({
  targets: ['ie >= 11'], // expected compatible browser target range
  renderLegacyChunks: true, // need to generate legacy browser compatible chunks (default true)
  // ******** change the following configuration based on the previous step ******** //
  modernPolyfills: true, // auto detect polyfills required by modern browsers in the current target range
}),
...

2. Build log

image

Set modernPolyfills: true to automatically detect polyfills required by modern browsers in the current target range

3. Build output file

image

Generated one more polyfills file for modern browsers

4. index.html

image

Added load polyfills-modern script

5. Visit the page

Chrome 106

The output is correct:

image

Load file:

  • High version js, with polyfills-modern loaded at the same time (in fact, this file is not needed):

image

Chrome 64

The output is correct (goal achieved!):

image

Load file:

  • High version js + polyfills-modern (correct!)

image

IE11

The output is correct:

image

Load file:

  • Two polyfills loaded (actually execute polyfills-legacy)

image

6. Conclusion

Through renderLegacyChunks: true compatible with legacy browsers, modernPolyfills: true compatible with lower version modern browsers, and finally compatible with all versions of browsers, achieve the goal!
Insufficient: The introduction of unnecessary files in high-version modern browsers and legacy browsers will increase traffic consumption, but it has little effect.

Other configuration way

In the previous configuration, the required polyfills are automatically detected, and it can also be achieved by manually adding explicit polyfills:

// vite.config.ts
...
legacy({
  targets: ['ie >= 11'], // expected compatible browser target range
  renderLegacyChunks: true, // need to generate legacy browser compatible chunks
  polyfills: ['es/global-this', 'es/array/includes'], // manually add polyfills required by legacy browsers
  modernPolyfills: ['es/global-this'], // manually add polyfills required by modern browsers
}),
...

Benefit: Doesn't introduce unnecessary polyfills, as shown in the following figure

image

Disadvantages: Manual addition is troublesome, easy to miss, and the problem may be discovered after the deployment of production!

Compatible with modern browsers only

With the above foundation, the next implementation is relatively simple!

Target

Compatible browsers and versions

  • Chrome 64: The lowest version of the modern browser
  • Chrome 106: The latest version of the modern browser

Configure

// vite.config.ts
...
legacy({
  targets: ['chrome >= 64'], // compatible with modern browsers only
  renderLegacyChunks: false, // no need to generate legacy browser compatibility chunks
	modernPolyfills: true, // auto detect polyfills required by modern browsers in the current target range
}),
...

Because we don't need to be compatible with legacy browsers, we can set renderLegacyChunks: false, and we only need to detect polyfills modernPolyfills: true required by modern browsers.

Build result

1. Log

image

Only detect modern polyfills.

2. Output file

image

Only extra polyfills-modern files will be output.

3. index.html

image

Visit the page

Chrome 64, Chrome 106 is correct, and the loading file is the same (correct!)

image

Conclusion

If legacy browsers are completely ignored, generation of legacy chunks can be disabled: renderLegacyChunks: false, in which case the polyfills option will also have no effect.

At the same time, if you want to be compatible with lower versions of modern browsers, you can set the compatible target range and automatically detect the polyfills needed in the target range through modernPolyfills: true, or you can manually add only the polyfills you need.