Examples and Analysis of Low version Browser Compatibility with Vite
Dependency versions:
- vite: v2.9.4
- @vitejs/plugin-legacy: v1.8.1
- IE11: legacy browser
- Chrome 64: The lowest version of the modern browser
- Chrome 106: The latest version of the modern browser
// 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();
// 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)
}),
],
});
Note: If you want to display the following results, you need to set the process.env.DEBUG environment variable.
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:
- 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
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">
- 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
In addition, you can note: Since ESM is not supported, in the <script nomodule>
script, System
is used to load the module.
The output is correct:
Load the file as high version js:
Output error:
Reason: No polyfills block generated for low-version modern browsers!
Load the file as high version js:
The output is correct:
Load file:
Additional loaded -legacy
files, including polyfills.
With the default configuration, it is compatible with legacy browsers, but not modern browsers with lower versions.
// 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
}),
...
Set modernPolyfills: true
to automatically detect polyfills required by modern browsers in the current target range
Generated one more polyfills file for modern browsers
Added load polyfills-modern script
The output is correct:
Load file:
- High version js, with polyfills-modern loaded at the same time (in fact, this file is not needed):
The output is correct (goal achieved!):
Load file:
- High version js + polyfills-modern (correct!)
The output is correct:
Load file:
- Two polyfills loaded (actually execute polyfills-legacy)
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.
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
Disadvantages: Manual addition is troublesome, easy to miss, and the problem may be discovered after the deployment of production!
With the above foundation, the next implementation is relatively simple!
- Chrome 64: The lowest version of the modern browser
- Chrome 106: The latest version of the modern browser
// 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.
Only detect modern polyfills.
Only extra polyfills-modern files will be output.
Chrome 64, Chrome 106 is correct, and the loading file is the same (correct!)
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.