2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+193
View File
@@ -0,0 +1,193 @@
# @vitejs/plugin-legacy [![npm](https://img.shields.io/npm/v/@vitejs/plugin-legacy.svg)](https://npmjs.com/package/@vitejs/plugin-legacy)
Vite's default browser support baseline is [Native ESM](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta). This plugin provides support for legacy browsers that do not support those features when building for production.
By default, this plugin will:
- Generate a corresponding legacy chunk for every chunk in the final bundle, transformed with [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) and emitted as [SystemJS modules](https://github.com/systemjs/systemjs) (code splitting is still supported!).
- Generate a polyfill chunk including SystemJS runtime, and any necessary polyfills determined by specified browser targets and **actual usage** in the bundle.
- Inject `<script nomodule>` tags into generated HTML to conditionally load the polyfills and legacy bundle only in browsers without widely-available features support.
- Inject the `import.meta.env.LEGACY` env variable, which will only be `true` in the legacy production build, and `false` in all other cases.
## Usage
```js
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
}
```
Terser must be installed because plugin-legacy uses Terser for minification.
```sh
npm add -D terser
```
## Options
### `targets`
- **Type:** `string | string[] | { [key: string]: string }`
- **Default:** [`'last 2 versions and not dead, > 0.3%, Firefox ESR'`](https://browsersl.ist/#q=last+2+versions+and+not+dead%2C+%3E+0.3%25%2C+Firefox+ESR)
If explicitly set, it's passed on to [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env#targets) when rendering **legacy chunks**.
The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.
If it's not set, plugin-legacy will load [the browserslist config sources](https://github.com/browserslist/browserslist#queries) and then fallback to the default value.
### `modernTargets`
- **Type:** `string | string[]`
- **Default:** [`'edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1'`](https://browsersl.ist/#q=edge%3E%3D80%2C+firefox%3E%3D72%2C+chrome%3E%3D80%2C+safari%3E%3D13.1%2C+chromeAndroid%3E%3D80%2C+iOS%3E%3D13.1)
If explicitly set, it's passed on to [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env#targets) when rendering **modern chunks**.
The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.
If it's not set, plugin-legacy will fallback to the default value.
### `polyfills`
- **Type:** `boolean | string[]`
- **Default:** `true`
By default, a polyfills chunk is generated based on the target browser ranges and actual usage in the final bundle (detected via `@babel/preset-env`'s `useBuiltIns: 'usage'`).
Set to a list of strings to explicitly control which polyfills to include. See [Polyfill Specifiers](#polyfill-specifiers) for details.
Set to `false` to avoid generating polyfills and handle it yourself (will still generate legacy chunks with syntax transformations).
### `additionalLegacyPolyfills`
- **Type:** `string[]`
Add custom imports to the legacy polyfills chunk. Since the usage-based polyfill detection only covers ES language features, it may be necessary to manually specify additional DOM API polyfills using this option.
Note: if additional polyfills are needed for both the modern and legacy chunks, they can simply be imported in the application source code.
### `modernPolyfills`
- **Type:** `boolean | string[]`
- **Default:** `false`
Defaults to `false`. Enabling this option will generate a separate polyfills chunk for the modern build (targeting [browsers that support widely-available features](#browsers-that-supports-esm-but-does-not-support-widely-available-features)).
Set to a list of strings to explicitly control which polyfills to include. See [Polyfill Specifiers](#polyfill-specifiers) for details.
Note it is **not recommended** to use the `true` value (which uses auto-detection) because `core-js@3` is very aggressive in polyfill inclusions due to all the bleeding edge features it supports. Even when targeting native ESM support, it injects 15kb of polyfills!
If you don't have hard reliance on bleeding edge runtime features, it is not that hard to avoid having to use polyfills in the modern build altogether. Alternatively, consider using an on-demand service like [Polyfill.io](https://polyfill.io) to only inject necessary polyfills based on actual browser user-agents (most modern browsers will need nothing!).
### `renderLegacyChunks`
- **Type:** `boolean`
- **Default:** `true`
Set to `false` to disable legacy chunks. This is only useful if you are using `modernPolyfills`, which essentially allows you to use this plugin for injecting polyfills to the modern build only:
```js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
modernPolyfills: [
/* ... */
],
renderLegacyChunks: false,
}),
],
}
```
### `externalSystemJS`
- **Type:** `boolean`
- **Default:** `false`
Defaults to `false`. Enabling this option will exclude `systemjs/dist/s.min.js` inside polyfills-legacy chunk.
### `renderModernChunks`
- **Type:** `boolean`
- **Default:** `true`
Set to `false` to only output the legacy bundles that support all target browsers.
## Browsers that supports ESM but does not support widely-available features
The legacy plugin offers a way to use widely-available features natively in the modern build, while falling back to the legacy build in browsers with native ESM but without those features supported (e.g. Legacy Edge). This feature works by injecting a runtime check and loading the legacy bundle with SystemJs runtime if needed. There are the following drawbacks:
- Modern bundle is downloaded in all ESM browsers
- Modern bundle throws `SyntaxError` in browsers without those features support
The following syntax are considered as widely-available:
- dynamic import
- `import.meta`
- async generator
## Polyfill Specifiers
Polyfill specifier strings for `polyfills` and `modernPolyfills` can be either of the following:
- Any [`core-js` 3 sub import paths](https://unpkg.com/browse/core-js@latest/) - e.g. `es/map` will import `core-js/es/map`
- Any [individual `core-js` 3 modules](https://unpkg.com/browse/core-js@latest/modules/) - e.g. `es.array.iterator` will import `core-js/modules/es.array.iterator.js`
**Example**
```js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
polyfills: ['es.promise.finally', 'es/map', 'es/set'],
modernPolyfills: ['es.promise.finally'],
}),
],
}
```
## Content Security Policy
The legacy plugin requires inline scripts for [Safari 10.1 `nomodule` fix](https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc), SystemJS initialization, and dynamic import fallback. If you have a strict CSP policy requirement, you will need to [add the corresponding hashes to your `script-src` list](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_inline_script).
The hash values (without the `sha256-` prefix) can be retrieved via:
```js
import { cspHashes } from '@vitejs/plugin-legacy'
```
The current values are:
- `sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=`
- `sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=`
- `sha256-VA8O2hAdooB288EpSTrGLl7z3QikbWU9wwoebO/QaYk=`
- `sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=`
<!--
Run `node --input-type=module -e "import {cspHashes} from '@vitejs/plugin-legacy'; console.log(cspHashes.map(h => 'sha256-'+h))"` to retrieve the value.
-->
Note that these values could change between minor versions. Thus, we recommend generating the CSP header from the exported `cspHashes` variable. If you copy the values manually, then you should pin the minor version using `~`.
When using the `regenerator-runtime` polyfill, it will attempt to use the `globalThis` object to register itself. If `globalThis` is not available (it is [fairly new](https://caniuse.com/?search=globalThis) and not widely supported, including IE 11), it attempts to perform dynamic `Function(...)` call which violates the CSP. To avoid dynamic `eval` in the absence of `globalThis` consider adding `core-js/proposals/global-this` to `additionalLegacyPolyfills` to define it.
## References
- [Vue CLI modern mode](https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode)
- [Using Native JavaScript Modules in Production Today](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/)
- [rollup-native-modules-boilerplate](https://github.com/philipwalton/rollup-native-modules-boilerplate)
+738
View File
@@ -0,0 +1,738 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const path = require('node:path');
const node_crypto = require('node:crypto');
const node_module = require('node:module');
const node_url = require('node:url');
const vite = require('vite');
const MagicString = require('magic-string');
const require$$0 = require('tty');
const browserslist = require('browserslist');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
const require$$0__default = /*#__PURE__*/_interopDefaultCompat(require$$0);
const browserslist__default = /*#__PURE__*/_interopDefaultCompat(browserslist);
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var picocolors = {exports: {}};
let tty = require$$0__default;
let isColorSupported =
!("NO_COLOR" in process.env || process.argv.includes("--no-color")) &&
("FORCE_COLOR" in process.env ||
process.argv.includes("--color") ||
process.platform === "win32" ||
(tty.isatty(1) && process.env.TERM !== "dumb") ||
"CI" in process.env);
let formatter =
(open, close, replace = open) =>
input => {
let string = "" + input;
let index = string.indexOf(close, open.length);
return ~index
? open + replaceClose(string, close, replace, index) + close
: open + string + close
};
let replaceClose = (string, close, replace, index) => {
let start = string.substring(0, index) + replace;
let end = string.substring(index + close.length);
let nextIndex = end.indexOf(close);
return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end
};
let createColors = (enabled = isColorSupported) => ({
isColorSupported: enabled,
reset: enabled ? s => `\x1b[0m${s}\x1b[0m` : String,
bold: enabled ? formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m") : String,
dim: enabled ? formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m") : String,
italic: enabled ? formatter("\x1b[3m", "\x1b[23m") : String,
underline: enabled ? formatter("\x1b[4m", "\x1b[24m") : String,
inverse: enabled ? formatter("\x1b[7m", "\x1b[27m") : String,
hidden: enabled ? formatter("\x1b[8m", "\x1b[28m") : String,
strikethrough: enabled ? formatter("\x1b[9m", "\x1b[29m") : String,
black: enabled ? formatter("\x1b[30m", "\x1b[39m") : String,
red: enabled ? formatter("\x1b[31m", "\x1b[39m") : String,
green: enabled ? formatter("\x1b[32m", "\x1b[39m") : String,
yellow: enabled ? formatter("\x1b[33m", "\x1b[39m") : String,
blue: enabled ? formatter("\x1b[34m", "\x1b[39m") : String,
magenta: enabled ? formatter("\x1b[35m", "\x1b[39m") : String,
cyan: enabled ? formatter("\x1b[36m", "\x1b[39m") : String,
white: enabled ? formatter("\x1b[37m", "\x1b[39m") : String,
gray: enabled ? formatter("\x1b[90m", "\x1b[39m") : String,
bgBlack: enabled ? formatter("\x1b[40m", "\x1b[49m") : String,
bgRed: enabled ? formatter("\x1b[41m", "\x1b[49m") : String,
bgGreen: enabled ? formatter("\x1b[42m", "\x1b[49m") : String,
bgYellow: enabled ? formatter("\x1b[43m", "\x1b[49m") : String,
bgBlue: enabled ? formatter("\x1b[44m", "\x1b[49m") : String,
bgMagenta: enabled ? formatter("\x1b[45m", "\x1b[49m") : String,
bgCyan: enabled ? formatter("\x1b[46m", "\x1b[49m") : String,
bgWhite: enabled ? formatter("\x1b[47m", "\x1b[49m") : String,
});
picocolors.exports = createColors();
picocolors.exports.createColors = createColors;
var picocolorsExports = picocolors.exports;
const colors = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
const legacyPolyfillId = "vite-legacy-polyfill";
const legacyEntryId = "vite-legacy-entry";
const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
const detectModernBrowserVarName = "__vite_is_modern_browser";
const detectModernBrowserDetector = `import.meta.url;import("_").catch(()=>1);(async function*(){})().next()`;
const detectModernBrowserCode = `${detectModernBrowserDetector};if(location.protocol!="file:"){window.${detectModernBrowserVarName}=true}`;
const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
const modernChunkLegacyGuard = `export function __vite_legacy_guard(){${detectModernBrowserDetector}};`;
let babel;
async function loadBabel() {
if (!babel) {
babel = await import('@babel/core');
}
return babel;
}
const { loadConfig: browserslistLoadConfig } = browserslist__default;
function toOutputFilePathInHtml(filename, type, hostId, hostType, config, toRelative) {
const { renderBuiltUrl } = config.experimental;
let relative = config.base === "" || config.base === "./";
if (renderBuiltUrl) {
const result = renderBuiltUrl(filename, {
hostId,
hostType,
type,
ssr: !!config.build.ssr
});
if (typeof result === "object") {
if (result.runtime) {
throw new Error(
`{ runtime: "${result.runtime}" } is not supported for assets in ${hostType} files: ${filename}`
);
}
if (typeof result.relative === "boolean") {
relative = result.relative;
}
} else if (result) {
return result;
}
}
if (relative && !config.build.ssr) {
return toRelative(filename, hostId);
} else {
return config.base + filename;
}
}
function getBaseInHTML(urlRelativePath, config) {
return config.base === "./" || config.base === "" ? path__default.posix.join(
path__default.posix.relative(urlRelativePath, "").slice(0, -2),
"./"
) : config.base;
}
function toAssetPathFromHtml(filename, htmlPath, config) {
const relativeUrlPath = vite.normalizePath(path__default.relative(config.root, htmlPath));
const toRelative = (filename2, hostId) => getBaseInHTML(relativeUrlPath, config) + filename2;
return toOutputFilePathInHtml(
filename,
"asset",
htmlPath,
"html",
config,
toRelative
);
}
const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
const _require = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
const nonLeadingHashInFileNameRE = /[^/]+\[hash(?::\d+)?\]/;
const prefixedHashInFileNameRE = /\W?\[hash(:\d+)?\]/;
function viteLegacyPlugin(options = {}) {
let config;
let targets;
let modernTargets;
const modernTargetsEsbuild = [
"es2020",
"edge79",
"firefox67",
"chrome64",
"safari12"
];
const modernTargetsBabel = "edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1";
const genLegacy = options.renderLegacyChunks !== false;
const genModern = options.renderModernChunks !== false;
if (!genLegacy && !genModern) {
throw new Error(
"`renderLegacyChunks` and `renderModernChunks` cannot be both false"
);
}
const debugFlags = (process.env.DEBUG || "").split(",");
const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
const facadeToLegacyPolyfillMap = /* @__PURE__ */ new Map();
const facadeToModernPolyfillMap = /* @__PURE__ */ new Map();
const modernPolyfills = /* @__PURE__ */ new Set();
const legacyPolyfills = /* @__PURE__ */ new Set();
if (Array.isArray(options.modernPolyfills) && genModern) {
options.modernPolyfills.forEach((i) => {
modernPolyfills.add(
i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`
);
});
}
if (Array.isArray(options.polyfills)) {
options.polyfills.forEach((i) => {
if (i.startsWith(`regenerator`)) {
legacyPolyfills.add(`regenerator-runtime/runtime.js`);
} else {
legacyPolyfills.add(
i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`
);
}
});
}
if (Array.isArray(options.additionalLegacyPolyfills)) {
options.additionalLegacyPolyfills.forEach((i) => {
legacyPolyfills.add(i);
});
}
let overriddenBuildTarget = false;
let overriddenDefaultModernTargets = false;
const legacyConfigPlugin = {
name: "vite:legacy-config",
async config(config2, env) {
if (env.command === "build" && !config2.build?.ssr) {
if (!config2.build) {
config2.build = {};
}
if (!config2.build.cssTarget) {
config2.build.cssTarget = "chrome61";
}
if (genLegacy) {
overriddenBuildTarget = config2.build.target !== void 0;
overriddenDefaultModernTargets = options.modernTargets !== void 0;
if (options.modernTargets) {
const { default: browserslistToEsbuild } = await import('browserslist-to-esbuild');
config2.build.target = browserslistToEsbuild(options.modernTargets);
} else {
config2.build.target = modernTargetsEsbuild;
}
}
}
return {
define: {
"import.meta.env.LEGACY": env.command === "serve" || config2.build?.ssr ? false : legacyEnvVarMarker
}
};
},
configResolved(config2) {
if (overriddenBuildTarget) {
config2.logger.warn(
colors.yellow(
`plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.`
)
);
}
if (overriddenDefaultModernTargets) {
config2.logger.warn(
colors.yellow(
`plugin-legacy 'modernTargets' option overrode the builtin targets of modern chunks. Some versions of browsers between legacy and modern may not be supported.`
)
);
}
}
};
const legacyGenerateBundlePlugin = {
name: "vite:legacy-generate-polyfill-chunk",
apply: "build",
async generateBundle(opts, bundle) {
if (config.build.ssr) {
return;
}
if (!isLegacyBundle(bundle, opts)) {
if (!modernPolyfills.size) {
return;
}
isDebug && console.log(
`[@vitejs/plugin-legacy] modern polyfills:`,
modernPolyfills
);
const polyfillChunk = await buildPolyfillChunk(
config.mode,
modernPolyfills,
bundle,
facadeToModernPolyfillMap,
config.build,
"es",
opts,
true
);
if (genLegacy && polyfillChunk) {
polyfillChunk.code = modernChunkLegacyGuard + polyfillChunk.code;
}
return;
}
if (!genLegacy) {
return;
}
if (options.polyfills !== false) {
await detectPolyfills(
`Promise.resolve(); Promise.all();`,
targets,
legacyPolyfills
);
}
if (legacyPolyfills.size || !options.externalSystemJS) {
isDebug && console.log(
`[@vitejs/plugin-legacy] legacy polyfills:`,
legacyPolyfills
);
await buildPolyfillChunk(
config.mode,
legacyPolyfills,
bundle,
facadeToLegacyPolyfillMap,
// force using terser for legacy polyfill minification, since esbuild
// isn't legacy-safe
config.build,
"iife",
opts,
options.externalSystemJS
);
}
}
};
const legacyPostPlugin = {
name: "vite:legacy-post-process",
enforce: "post",
apply: "build",
configResolved(_config) {
if (_config.build.lib) {
throw new Error("@vitejs/plugin-legacy does not support library mode.");
}
config = _config;
modernTargets = options.modernTargets || modernTargetsBabel;
isDebug && console.log(`[@vitejs/plugin-legacy] modernTargets:`, modernTargets);
if (!genLegacy || config.build.ssr) {
return;
}
targets = options.targets || browserslistLoadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
if (!fileNames) {
return path__default.posix.join(config.build.assetsDir, defaultFileName);
}
return (chunkInfo) => {
let fileName = typeof fileNames === "function" ? fileNames(chunkInfo) : fileNames;
if (fileName.includes("[name]")) {
fileName = fileName.replace("[name]", "[name]-legacy");
} else if (nonLeadingHashInFileNameRE.test(fileName)) {
fileName = fileName.replace(prefixedHashInFileNameRE, "-legacy$&");
} else {
fileName = fileName.replace(/(.+?)\.(.+)/, "$1-legacy.$2");
}
return fileName;
};
};
const createLegacyOutput = (options2 = {}) => {
return {
...options2,
format: "system",
entryFileNames: getLegacyOutputFileName(options2.entryFileNames),
chunkFileNames: getLegacyOutputFileName(options2.chunkFileNames)
};
};
const { rollupOptions } = config.build;
const { output } = rollupOptions;
if (Array.isArray(output)) {
rollupOptions.output = [
...output.map(createLegacyOutput),
...genModern ? output : []
];
} else {
rollupOptions.output = [
createLegacyOutput(output),
...genModern ? [output || {}] : []
];
}
},
async renderChunk(raw, chunk, opts) {
if (config.build.ssr) {
return null;
}
if (!isLegacyChunk(chunk, opts)) {
if (options.modernPolyfills && !Array.isArray(options.modernPolyfills) && genModern) {
await detectPolyfills(raw, modernTargets, modernPolyfills);
}
const ms = new MagicString__default(raw);
if (genLegacy && chunk.isEntry) {
ms.prepend(modernChunkLegacyGuard);
}
if (raw.includes(legacyEnvVarMarker)) {
const re = new RegExp(legacyEnvVarMarker, "g");
let match;
while (match = re.exec(raw)) {
ms.overwrite(
match.index,
match.index + legacyEnvVarMarker.length,
`false`
);
}
}
if (config.build.sourcemap) {
return {
code: ms.toString(),
map: ms.generateMap({ hires: "boundary" })
};
}
return {
code: ms.toString()
};
}
if (!genLegacy) {
return null;
}
opts.__vite_skip_esbuild__ = true;
opts.__vite_force_terser__ = true;
opts.__vite_skip_asset_emit__ = true;
const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
const sourceMaps = !!config.build.sourcemap;
const babel2 = await loadBabel();
const result = babel2.transform(raw, {
babelrc: false,
configFile: false,
compact: !!config.build.minify,
sourceMaps,
inputSourceMap: void 0,
// sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
presets: [
// forcing our plugin to run before preset-env by wrapping it in a
// preset so we can catch the injected import statements...
[
() => ({
plugins: [
recordAndRemovePolyfillBabelPlugin(legacyPolyfills),
replaceLegacyEnvBabelPlugin(),
wrapIIFEBabelPlugin()
]
})
],
[
(await import('@babel/preset-env')).default,
createBabelPresetEnvOptions(targets, { needPolyfills })
]
]
});
if (result)
return { code: result.code, map: result.map };
return null;
},
transformIndexHtml(html, { chunk }) {
if (config.build.ssr)
return;
if (!chunk)
return;
if (chunk.fileName.includes("-legacy")) {
facadeToLegacyChunkMap.set(chunk.facadeModuleId, chunk.fileName);
if (genModern) {
return;
}
}
if (!genModern) {
html = html.replace(/<script type="module".*?<\/script>/g, "");
}
const tags = [];
const htmlFilename = chunk.facadeModuleId?.replace(/\?.*$/, "");
if (genModern) {
const modernPolyfillFilename = facadeToModernPolyfillMap.get(
chunk.facadeModuleId
);
if (modernPolyfillFilename) {
tags.push({
tag: "script",
attrs: {
type: "module",
crossorigin: true,
src: toAssetPathFromHtml(
modernPolyfillFilename,
chunk.facadeModuleId,
config
)
}
});
} else if (modernPolyfills.size) {
throw new Error(
`No corresponding modern polyfill chunk found for ${htmlFilename}`
);
}
}
if (!genLegacy) {
return { html, tags };
}
if (genModern) {
tags.push({
tag: "script",
attrs: { nomodule: genModern },
children: safari10NoModuleFix,
injectTo: "body"
});
}
const legacyPolyfillFilename = facadeToLegacyPolyfillMap.get(
chunk.facadeModuleId
);
if (legacyPolyfillFilename) {
tags.push({
tag: "script",
attrs: {
nomodule: genModern,
crossorigin: true,
id: legacyPolyfillId,
src: toAssetPathFromHtml(
legacyPolyfillFilename,
chunk.facadeModuleId,
config
)
},
injectTo: "body"
});
} else if (legacyPolyfills.size) {
throw new Error(
`No corresponding legacy polyfill chunk found for ${htmlFilename}`
);
}
const legacyEntryFilename = facadeToLegacyChunkMap.get(
chunk.facadeModuleId
);
if (legacyEntryFilename) {
tags.push({
tag: "script",
attrs: {
nomodule: genModern,
crossorigin: true,
// we set the entry path on the element as an attribute so that the
// script content will stay consistent - which allows using a constant
// hash value for CSP.
id: legacyEntryId,
"data-src": toAssetPathFromHtml(
legacyEntryFilename,
chunk.facadeModuleId,
config
)
},
children: systemJSInlineCode,
injectTo: "body"
});
} else {
throw new Error(
`No corresponding legacy entry chunk found for ${htmlFilename}`
);
}
if (legacyPolyfillFilename && legacyEntryFilename && genModern) {
tags.push({
tag: "script",
attrs: { type: "module" },
children: detectModernBrowserCode,
injectTo: "head"
});
tags.push({
tag: "script",
attrs: { type: "module" },
children: dynamicFallbackInlineCode,
injectTo: "head"
});
}
return {
html,
tags
};
},
generateBundle(opts, bundle) {
if (config.build.ssr) {
return;
}
if (isLegacyBundle(bundle, opts) && genModern) {
for (const name in bundle) {
if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
delete bundle[name];
}
}
}
}
};
return [legacyConfigPlugin, legacyGenerateBundlePlugin, legacyPostPlugin];
}
async function detectPolyfills(code, targets, list) {
const babel2 = await loadBabel();
const result = babel2.transform(code, {
ast: true,
babelrc: false,
configFile: false,
compact: false,
presets: [
[
(await import('@babel/preset-env')).default,
createBabelPresetEnvOptions(targets, {})
]
]
});
for (const node of result.ast.program.body) {
if (node.type === "ImportDeclaration") {
const source = node.source.value;
if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
list.add(source);
}
}
}
}
function createBabelPresetEnvOptions(targets, { needPolyfills = true }) {
return {
targets,
bugfixes: true,
loose: false,
modules: false,
useBuiltIns: needPolyfills ? "usage" : false,
corejs: needPolyfills ? {
version: _require("core-js/package.json").version,
proposals: false
} : void 0,
shippedProposals: true,
ignoreBrowserslistConfig: true
};
}
async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, buildOptions, format, rollupOutputOptions, excludeSystemJS) {
let { minify, assetsDir } = buildOptions;
minify = minify ? "terser" : false;
const res = await vite.build({
mode,
// so that everything is resolved from here
root: path__default.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),
configFile: false,
logLevel: "error",
plugins: [polyfillsPlugin(imports, excludeSystemJS)],
build: {
write: false,
minify,
assetsDir,
rollupOptions: {
input: {
polyfills: polyfillId
},
output: {
format,
entryFileNames: rollupOutputOptions.entryFileNames
}
}
},
// Don't run esbuild for transpilation or minification
// because we don't want to transpile code.
esbuild: false,
optimizeDeps: {
esbuildOptions: {
// If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
// This limits the input code not to include es2015+ codes.
// But core-js is the only dependency which includes commonjs code
// and core-js doesn't include es2015+ codes.
target: "es5"
}
}
});
const _polyfillChunk = Array.isArray(res) ? res[0] : res;
if (!("output" in _polyfillChunk))
return;
const polyfillChunk = _polyfillChunk.output[0];
for (const key in bundle) {
const chunk = bundle[key];
if (chunk.type === "chunk" && chunk.facadeModuleId) {
facadeToChunkMap.set(chunk.facadeModuleId, polyfillChunk.fileName);
}
}
bundle[polyfillChunk.fileName] = polyfillChunk;
return polyfillChunk;
}
const polyfillId = "\0vite/legacy-polyfills";
function polyfillsPlugin(imports, excludeSystemJS) {
return {
name: "vite:legacy-polyfills",
resolveId(id) {
if (id === polyfillId) {
return id;
}
},
load(id) {
if (id === polyfillId) {
return [...imports].map((i) => `import ${JSON.stringify(i)};`).join("") + (excludeSystemJS ? "" : `import "systemjs/dist/s.min.js";`);
}
}
};
}
function isLegacyChunk(chunk, options) {
return options.format === "system" && chunk.fileName.includes("-legacy");
}
function isLegacyBundle(bundle, options) {
if (options.format === "system") {
const entryChunk = Object.values(bundle).find(
(output) => output.type === "chunk" && output.isEntry
);
return !!entryChunk && entryChunk.fileName.includes("-legacy");
}
return false;
}
function recordAndRemovePolyfillBabelPlugin(polyfills) {
return ({ types: t }) => ({
name: "vite-remove-polyfill-import",
post({ path: path2 }) {
path2.get("body").forEach((p) => {
if (t.isImportDeclaration(p.node)) {
polyfills.add(p.node.source.value);
p.remove();
}
});
}
});
}
function replaceLegacyEnvBabelPlugin() {
return ({ types: t }) => ({
name: "vite-replace-env-legacy",
visitor: {
Identifier(path2) {
if (path2.node.name === legacyEnvVarMarker) {
path2.replaceWith(t.booleanLiteral(true));
}
}
}
});
}
function wrapIIFEBabelPlugin() {
return ({ types: t, template }) => {
const buildIIFE = template(";(function(){%%body%%})();");
return {
name: "vite-wrap-iife",
post({ path: path2 }) {
if (!this.isWrapped) {
this.isWrapped = true;
path2.replaceWith(t.program(buildIIFE({ body: path2.node.body })));
}
}
};
};
}
const cspHashes = [
safari10NoModuleFix,
systemJSInlineCode,
detectModernBrowserCode,
dynamicFallbackInlineCode
].map((i) => node_crypto.createHash("sha256").update(i).digest("base64"));
module.exports = viteLegacyPlugin;
module.exports.cspHashes = cspHashes;
module.exports.default = viteLegacyPlugin;
module.exports.detectPolyfills = detectPolyfills;
+41
View File
@@ -0,0 +1,41 @@
import { Plugin } from 'vite';
interface Options {
/**
* default: 'defaults'
*/
targets?: string | string[] | {
[key: string]: string;
};
/**
* default: 'edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1'
*/
modernTargets?: string | string[];
/**
* default: true
*/
polyfills?: boolean | string[];
additionalLegacyPolyfills?: string[];
/**
* default: false
*/
modernPolyfills?: boolean | string[];
/**
* default: true
*/
renderLegacyChunks?: boolean;
/**
* default: false
*/
externalSystemJS?: boolean;
/**
* default: true
*/
renderModernChunks?: boolean;
}
declare function viteLegacyPlugin(options?: Options): Plugin[];
declare function detectPolyfills(code: string, targets: any, list: Set<string>): Promise<void>;
declare const cspHashes: string[];
export { type Options, cspHashes, viteLegacyPlugin as default, detectPolyfills };
+41
View File
@@ -0,0 +1,41 @@
import { Plugin } from 'vite';
interface Options {
/**
* default: 'defaults'
*/
targets?: string | string[] | {
[key: string]: string;
};
/**
* default: 'edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1'
*/
modernTargets?: string | string[];
/**
* default: true
*/
polyfills?: boolean | string[];
additionalLegacyPolyfills?: string[];
/**
* default: false
*/
modernPolyfills?: boolean | string[];
/**
* default: true
*/
renderLegacyChunks?: boolean;
/**
* default: false
*/
externalSystemJS?: boolean;
/**
* default: true
*/
renderModernChunks?: boolean;
}
declare function viteLegacyPlugin(options?: Options): Plugin[];
declare function detectPolyfills(code: string, targets: any, list: Set<string>): Promise<void>;
declare const cspHashes: string[];
export { type Options, cspHashes, viteLegacyPlugin as default, detectPolyfills };
+41
View File
@@ -0,0 +1,41 @@
import { Plugin } from 'vite';
interface Options {
/**
* default: 'defaults'
*/
targets?: string | string[] | {
[key: string]: string;
};
/**
* default: 'edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1'
*/
modernTargets?: string | string[];
/**
* default: true
*/
polyfills?: boolean | string[];
additionalLegacyPolyfills?: string[];
/**
* default: false
*/
modernPolyfills?: boolean | string[];
/**
* default: true
*/
renderLegacyChunks?: boolean;
/**
* default: false
*/
externalSystemJS?: boolean;
/**
* default: true
*/
renderModernChunks?: boolean;
}
declare function viteLegacyPlugin(options?: Options): Plugin[];
declare function detectPolyfills(code: string, targets: any, list: Set<string>): Promise<void>;
declare const cspHashes: string[];
export { type Options, cspHashes, viteLegacyPlugin as default, detectPolyfills };
+723
View File
@@ -0,0 +1,723 @@
import path from 'node:path';
import { createHash } from 'node:crypto';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { build, normalizePath } from 'vite';
import MagicString from 'magic-string';
import require$$0 from 'tty';
import browserslist from 'browserslist';
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var picocolors = {exports: {}};
let tty = require$$0;
let isColorSupported =
!("NO_COLOR" in process.env || process.argv.includes("--no-color")) &&
("FORCE_COLOR" in process.env ||
process.argv.includes("--color") ||
process.platform === "win32" ||
(tty.isatty(1) && process.env.TERM !== "dumb") ||
"CI" in process.env);
let formatter =
(open, close, replace = open) =>
input => {
let string = "" + input;
let index = string.indexOf(close, open.length);
return ~index
? open + replaceClose(string, close, replace, index) + close
: open + string + close
};
let replaceClose = (string, close, replace, index) => {
let start = string.substring(0, index) + replace;
let end = string.substring(index + close.length);
let nextIndex = end.indexOf(close);
return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end
};
let createColors = (enabled = isColorSupported) => ({
isColorSupported: enabled,
reset: enabled ? s => `\x1b[0m${s}\x1b[0m` : String,
bold: enabled ? formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m") : String,
dim: enabled ? formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m") : String,
italic: enabled ? formatter("\x1b[3m", "\x1b[23m") : String,
underline: enabled ? formatter("\x1b[4m", "\x1b[24m") : String,
inverse: enabled ? formatter("\x1b[7m", "\x1b[27m") : String,
hidden: enabled ? formatter("\x1b[8m", "\x1b[28m") : String,
strikethrough: enabled ? formatter("\x1b[9m", "\x1b[29m") : String,
black: enabled ? formatter("\x1b[30m", "\x1b[39m") : String,
red: enabled ? formatter("\x1b[31m", "\x1b[39m") : String,
green: enabled ? formatter("\x1b[32m", "\x1b[39m") : String,
yellow: enabled ? formatter("\x1b[33m", "\x1b[39m") : String,
blue: enabled ? formatter("\x1b[34m", "\x1b[39m") : String,
magenta: enabled ? formatter("\x1b[35m", "\x1b[39m") : String,
cyan: enabled ? formatter("\x1b[36m", "\x1b[39m") : String,
white: enabled ? formatter("\x1b[37m", "\x1b[39m") : String,
gray: enabled ? formatter("\x1b[90m", "\x1b[39m") : String,
bgBlack: enabled ? formatter("\x1b[40m", "\x1b[49m") : String,
bgRed: enabled ? formatter("\x1b[41m", "\x1b[49m") : String,
bgGreen: enabled ? formatter("\x1b[42m", "\x1b[49m") : String,
bgYellow: enabled ? formatter("\x1b[43m", "\x1b[49m") : String,
bgBlue: enabled ? formatter("\x1b[44m", "\x1b[49m") : String,
bgMagenta: enabled ? formatter("\x1b[45m", "\x1b[49m") : String,
bgCyan: enabled ? formatter("\x1b[46m", "\x1b[49m") : String,
bgWhite: enabled ? formatter("\x1b[47m", "\x1b[49m") : String,
});
picocolors.exports = createColors();
picocolors.exports.createColors = createColors;
var picocolorsExports = picocolors.exports;
const colors = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
const legacyPolyfillId = "vite-legacy-polyfill";
const legacyEntryId = "vite-legacy-entry";
const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
const detectModernBrowserVarName = "__vite_is_modern_browser";
const detectModernBrowserDetector = `import.meta.url;import("_").catch(()=>1);(async function*(){})().next()`;
const detectModernBrowserCode = `${detectModernBrowserDetector};if(location.protocol!="file:"){window.${detectModernBrowserVarName}=true}`;
const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
const modernChunkLegacyGuard = `export function __vite_legacy_guard(){${detectModernBrowserDetector}};`;
let babel;
async function loadBabel() {
if (!babel) {
babel = await import('@babel/core');
}
return babel;
}
const { loadConfig: browserslistLoadConfig } = browserslist;
function toOutputFilePathInHtml(filename, type, hostId, hostType, config, toRelative) {
const { renderBuiltUrl } = config.experimental;
let relative = config.base === "" || config.base === "./";
if (renderBuiltUrl) {
const result = renderBuiltUrl(filename, {
hostId,
hostType,
type,
ssr: !!config.build.ssr
});
if (typeof result === "object") {
if (result.runtime) {
throw new Error(
`{ runtime: "${result.runtime}" } is not supported for assets in ${hostType} files: ${filename}`
);
}
if (typeof result.relative === "boolean") {
relative = result.relative;
}
} else if (result) {
return result;
}
}
if (relative && !config.build.ssr) {
return toRelative(filename, hostId);
} else {
return config.base + filename;
}
}
function getBaseInHTML(urlRelativePath, config) {
return config.base === "./" || config.base === "" ? path.posix.join(
path.posix.relative(urlRelativePath, "").slice(0, -2),
"./"
) : config.base;
}
function toAssetPathFromHtml(filename, htmlPath, config) {
const relativeUrlPath = normalizePath(path.relative(config.root, htmlPath));
const toRelative = (filename2, hostId) => getBaseInHTML(relativeUrlPath, config) + filename2;
return toOutputFilePathInHtml(
filename,
"asset",
htmlPath,
"html",
config,
toRelative
);
}
const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
const _require = createRequire(import.meta.url);
const nonLeadingHashInFileNameRE = /[^/]+\[hash(?::\d+)?\]/;
const prefixedHashInFileNameRE = /\W?\[hash(:\d+)?\]/;
function viteLegacyPlugin(options = {}) {
let config;
let targets;
let modernTargets;
const modernTargetsEsbuild = [
"es2020",
"edge79",
"firefox67",
"chrome64",
"safari12"
];
const modernTargetsBabel = "edge>=80, firefox>=72, chrome>=80, safari>=13.1, chromeAndroid>=80, iOS>=13.1";
const genLegacy = options.renderLegacyChunks !== false;
const genModern = options.renderModernChunks !== false;
if (!genLegacy && !genModern) {
throw new Error(
"`renderLegacyChunks` and `renderModernChunks` cannot be both false"
);
}
const debugFlags = (process.env.DEBUG || "").split(",");
const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
const facadeToLegacyPolyfillMap = /* @__PURE__ */ new Map();
const facadeToModernPolyfillMap = /* @__PURE__ */ new Map();
const modernPolyfills = /* @__PURE__ */ new Set();
const legacyPolyfills = /* @__PURE__ */ new Set();
if (Array.isArray(options.modernPolyfills) && genModern) {
options.modernPolyfills.forEach((i) => {
modernPolyfills.add(
i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`
);
});
}
if (Array.isArray(options.polyfills)) {
options.polyfills.forEach((i) => {
if (i.startsWith(`regenerator`)) {
legacyPolyfills.add(`regenerator-runtime/runtime.js`);
} else {
legacyPolyfills.add(
i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`
);
}
});
}
if (Array.isArray(options.additionalLegacyPolyfills)) {
options.additionalLegacyPolyfills.forEach((i) => {
legacyPolyfills.add(i);
});
}
let overriddenBuildTarget = false;
let overriddenDefaultModernTargets = false;
const legacyConfigPlugin = {
name: "vite:legacy-config",
async config(config2, env) {
if (env.command === "build" && !config2.build?.ssr) {
if (!config2.build) {
config2.build = {};
}
if (!config2.build.cssTarget) {
config2.build.cssTarget = "chrome61";
}
if (genLegacy) {
overriddenBuildTarget = config2.build.target !== void 0;
overriddenDefaultModernTargets = options.modernTargets !== void 0;
if (options.modernTargets) {
const { default: browserslistToEsbuild } = await import('browserslist-to-esbuild');
config2.build.target = browserslistToEsbuild(options.modernTargets);
} else {
config2.build.target = modernTargetsEsbuild;
}
}
}
return {
define: {
"import.meta.env.LEGACY": env.command === "serve" || config2.build?.ssr ? false : legacyEnvVarMarker
}
};
},
configResolved(config2) {
if (overriddenBuildTarget) {
config2.logger.warn(
colors.yellow(
`plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.`
)
);
}
if (overriddenDefaultModernTargets) {
config2.logger.warn(
colors.yellow(
`plugin-legacy 'modernTargets' option overrode the builtin targets of modern chunks. Some versions of browsers between legacy and modern may not be supported.`
)
);
}
}
};
const legacyGenerateBundlePlugin = {
name: "vite:legacy-generate-polyfill-chunk",
apply: "build",
async generateBundle(opts, bundle) {
if (config.build.ssr) {
return;
}
if (!isLegacyBundle(bundle, opts)) {
if (!modernPolyfills.size) {
return;
}
isDebug && console.log(
`[@vitejs/plugin-legacy] modern polyfills:`,
modernPolyfills
);
const polyfillChunk = await buildPolyfillChunk(
config.mode,
modernPolyfills,
bundle,
facadeToModernPolyfillMap,
config.build,
"es",
opts,
true
);
if (genLegacy && polyfillChunk) {
polyfillChunk.code = modernChunkLegacyGuard + polyfillChunk.code;
}
return;
}
if (!genLegacy) {
return;
}
if (options.polyfills !== false) {
await detectPolyfills(
`Promise.resolve(); Promise.all();`,
targets,
legacyPolyfills
);
}
if (legacyPolyfills.size || !options.externalSystemJS) {
isDebug && console.log(
`[@vitejs/plugin-legacy] legacy polyfills:`,
legacyPolyfills
);
await buildPolyfillChunk(
config.mode,
legacyPolyfills,
bundle,
facadeToLegacyPolyfillMap,
// force using terser for legacy polyfill minification, since esbuild
// isn't legacy-safe
config.build,
"iife",
opts,
options.externalSystemJS
);
}
}
};
const legacyPostPlugin = {
name: "vite:legacy-post-process",
enforce: "post",
apply: "build",
configResolved(_config) {
if (_config.build.lib) {
throw new Error("@vitejs/plugin-legacy does not support library mode.");
}
config = _config;
modernTargets = options.modernTargets || modernTargetsBabel;
isDebug && console.log(`[@vitejs/plugin-legacy] modernTargets:`, modernTargets);
if (!genLegacy || config.build.ssr) {
return;
}
targets = options.targets || browserslistLoadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
if (!fileNames) {
return path.posix.join(config.build.assetsDir, defaultFileName);
}
return (chunkInfo) => {
let fileName = typeof fileNames === "function" ? fileNames(chunkInfo) : fileNames;
if (fileName.includes("[name]")) {
fileName = fileName.replace("[name]", "[name]-legacy");
} else if (nonLeadingHashInFileNameRE.test(fileName)) {
fileName = fileName.replace(prefixedHashInFileNameRE, "-legacy$&");
} else {
fileName = fileName.replace(/(.+?)\.(.+)/, "$1-legacy.$2");
}
return fileName;
};
};
const createLegacyOutput = (options2 = {}) => {
return {
...options2,
format: "system",
entryFileNames: getLegacyOutputFileName(options2.entryFileNames),
chunkFileNames: getLegacyOutputFileName(options2.chunkFileNames)
};
};
const { rollupOptions } = config.build;
const { output } = rollupOptions;
if (Array.isArray(output)) {
rollupOptions.output = [
...output.map(createLegacyOutput),
...genModern ? output : []
];
} else {
rollupOptions.output = [
createLegacyOutput(output),
...genModern ? [output || {}] : []
];
}
},
async renderChunk(raw, chunk, opts) {
if (config.build.ssr) {
return null;
}
if (!isLegacyChunk(chunk, opts)) {
if (options.modernPolyfills && !Array.isArray(options.modernPolyfills) && genModern) {
await detectPolyfills(raw, modernTargets, modernPolyfills);
}
const ms = new MagicString(raw);
if (genLegacy && chunk.isEntry) {
ms.prepend(modernChunkLegacyGuard);
}
if (raw.includes(legacyEnvVarMarker)) {
const re = new RegExp(legacyEnvVarMarker, "g");
let match;
while (match = re.exec(raw)) {
ms.overwrite(
match.index,
match.index + legacyEnvVarMarker.length,
`false`
);
}
}
if (config.build.sourcemap) {
return {
code: ms.toString(),
map: ms.generateMap({ hires: "boundary" })
};
}
return {
code: ms.toString()
};
}
if (!genLegacy) {
return null;
}
opts.__vite_skip_esbuild__ = true;
opts.__vite_force_terser__ = true;
opts.__vite_skip_asset_emit__ = true;
const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
const sourceMaps = !!config.build.sourcemap;
const babel2 = await loadBabel();
const result = babel2.transform(raw, {
babelrc: false,
configFile: false,
compact: !!config.build.minify,
sourceMaps,
inputSourceMap: void 0,
// sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
presets: [
// forcing our plugin to run before preset-env by wrapping it in a
// preset so we can catch the injected import statements...
[
() => ({
plugins: [
recordAndRemovePolyfillBabelPlugin(legacyPolyfills),
replaceLegacyEnvBabelPlugin(),
wrapIIFEBabelPlugin()
]
})
],
[
(await import('@babel/preset-env')).default,
createBabelPresetEnvOptions(targets, { needPolyfills })
]
]
});
if (result)
return { code: result.code, map: result.map };
return null;
},
transformIndexHtml(html, { chunk }) {
if (config.build.ssr)
return;
if (!chunk)
return;
if (chunk.fileName.includes("-legacy")) {
facadeToLegacyChunkMap.set(chunk.facadeModuleId, chunk.fileName);
if (genModern) {
return;
}
}
if (!genModern) {
html = html.replace(/<script type="module".*?<\/script>/g, "");
}
const tags = [];
const htmlFilename = chunk.facadeModuleId?.replace(/\?.*$/, "");
if (genModern) {
const modernPolyfillFilename = facadeToModernPolyfillMap.get(
chunk.facadeModuleId
);
if (modernPolyfillFilename) {
tags.push({
tag: "script",
attrs: {
type: "module",
crossorigin: true,
src: toAssetPathFromHtml(
modernPolyfillFilename,
chunk.facadeModuleId,
config
)
}
});
} else if (modernPolyfills.size) {
throw new Error(
`No corresponding modern polyfill chunk found for ${htmlFilename}`
);
}
}
if (!genLegacy) {
return { html, tags };
}
if (genModern) {
tags.push({
tag: "script",
attrs: { nomodule: genModern },
children: safari10NoModuleFix,
injectTo: "body"
});
}
const legacyPolyfillFilename = facadeToLegacyPolyfillMap.get(
chunk.facadeModuleId
);
if (legacyPolyfillFilename) {
tags.push({
tag: "script",
attrs: {
nomodule: genModern,
crossorigin: true,
id: legacyPolyfillId,
src: toAssetPathFromHtml(
legacyPolyfillFilename,
chunk.facadeModuleId,
config
)
},
injectTo: "body"
});
} else if (legacyPolyfills.size) {
throw new Error(
`No corresponding legacy polyfill chunk found for ${htmlFilename}`
);
}
const legacyEntryFilename = facadeToLegacyChunkMap.get(
chunk.facadeModuleId
);
if (legacyEntryFilename) {
tags.push({
tag: "script",
attrs: {
nomodule: genModern,
crossorigin: true,
// we set the entry path on the element as an attribute so that the
// script content will stay consistent - which allows using a constant
// hash value for CSP.
id: legacyEntryId,
"data-src": toAssetPathFromHtml(
legacyEntryFilename,
chunk.facadeModuleId,
config
)
},
children: systemJSInlineCode,
injectTo: "body"
});
} else {
throw new Error(
`No corresponding legacy entry chunk found for ${htmlFilename}`
);
}
if (legacyPolyfillFilename && legacyEntryFilename && genModern) {
tags.push({
tag: "script",
attrs: { type: "module" },
children: detectModernBrowserCode,
injectTo: "head"
});
tags.push({
tag: "script",
attrs: { type: "module" },
children: dynamicFallbackInlineCode,
injectTo: "head"
});
}
return {
html,
tags
};
},
generateBundle(opts, bundle) {
if (config.build.ssr) {
return;
}
if (isLegacyBundle(bundle, opts) && genModern) {
for (const name in bundle) {
if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
delete bundle[name];
}
}
}
}
};
return [legacyConfigPlugin, legacyGenerateBundlePlugin, legacyPostPlugin];
}
async function detectPolyfills(code, targets, list) {
const babel2 = await loadBabel();
const result = babel2.transform(code, {
ast: true,
babelrc: false,
configFile: false,
compact: false,
presets: [
[
(await import('@babel/preset-env')).default,
createBabelPresetEnvOptions(targets, {})
]
]
});
for (const node of result.ast.program.body) {
if (node.type === "ImportDeclaration") {
const source = node.source.value;
if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
list.add(source);
}
}
}
}
function createBabelPresetEnvOptions(targets, { needPolyfills = true }) {
return {
targets,
bugfixes: true,
loose: false,
modules: false,
useBuiltIns: needPolyfills ? "usage" : false,
corejs: needPolyfills ? {
version: _require("core-js/package.json").version,
proposals: false
} : void 0,
shippedProposals: true,
ignoreBrowserslistConfig: true
};
}
async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, buildOptions, format, rollupOutputOptions, excludeSystemJS) {
let { minify, assetsDir } = buildOptions;
minify = minify ? "terser" : false;
const res = await build({
mode,
// so that everything is resolved from here
root: path.dirname(fileURLToPath(import.meta.url)),
configFile: false,
logLevel: "error",
plugins: [polyfillsPlugin(imports, excludeSystemJS)],
build: {
write: false,
minify,
assetsDir,
rollupOptions: {
input: {
polyfills: polyfillId
},
output: {
format,
entryFileNames: rollupOutputOptions.entryFileNames
}
}
},
// Don't run esbuild for transpilation or minification
// because we don't want to transpile code.
esbuild: false,
optimizeDeps: {
esbuildOptions: {
// If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
// This limits the input code not to include es2015+ codes.
// But core-js is the only dependency which includes commonjs code
// and core-js doesn't include es2015+ codes.
target: "es5"
}
}
});
const _polyfillChunk = Array.isArray(res) ? res[0] : res;
if (!("output" in _polyfillChunk))
return;
const polyfillChunk = _polyfillChunk.output[0];
for (const key in bundle) {
const chunk = bundle[key];
if (chunk.type === "chunk" && chunk.facadeModuleId) {
facadeToChunkMap.set(chunk.facadeModuleId, polyfillChunk.fileName);
}
}
bundle[polyfillChunk.fileName] = polyfillChunk;
return polyfillChunk;
}
const polyfillId = "\0vite/legacy-polyfills";
function polyfillsPlugin(imports, excludeSystemJS) {
return {
name: "vite:legacy-polyfills",
resolveId(id) {
if (id === polyfillId) {
return id;
}
},
load(id) {
if (id === polyfillId) {
return [...imports].map((i) => `import ${JSON.stringify(i)};`).join("") + (excludeSystemJS ? "" : `import "systemjs/dist/s.min.js";`);
}
}
};
}
function isLegacyChunk(chunk, options) {
return options.format === "system" && chunk.fileName.includes("-legacy");
}
function isLegacyBundle(bundle, options) {
if (options.format === "system") {
const entryChunk = Object.values(bundle).find(
(output) => output.type === "chunk" && output.isEntry
);
return !!entryChunk && entryChunk.fileName.includes("-legacy");
}
return false;
}
function recordAndRemovePolyfillBabelPlugin(polyfills) {
return ({ types: t }) => ({
name: "vite-remove-polyfill-import",
post({ path: path2 }) {
path2.get("body").forEach((p) => {
if (t.isImportDeclaration(p.node)) {
polyfills.add(p.node.source.value);
p.remove();
}
});
}
});
}
function replaceLegacyEnvBabelPlugin() {
return ({ types: t }) => ({
name: "vite-replace-env-legacy",
visitor: {
Identifier(path2) {
if (path2.node.name === legacyEnvVarMarker) {
path2.replaceWith(t.booleanLiteral(true));
}
}
}
});
}
function wrapIIFEBabelPlugin() {
return ({ types: t, template }) => {
const buildIIFE = template(";(function(){%%body%%})();");
return {
name: "vite-wrap-iife",
post({ path: path2 }) {
if (!this.isWrapped) {
this.isWrapped = true;
path2.replaceWith(t.program(buildIIFE({ body: path2.node.body })));
}
}
};
};
}
const cspHashes = [
safari10NoModuleFix,
systemJSInlineCode,
detectModernBrowserCode,
dynamicFallbackInlineCode
].map((i) => createHash("sha256").update(i).digest("base64"));
export { cspHashes, viteLegacyPlugin as default, detectPolyfills };
+61
View File
@@ -0,0 +1,61 @@
{
"name": "@vitejs/plugin-legacy",
"version": "5.3.2",
"license": "MIT",
"author": "Evan You",
"files": [
"dist"
],
"keywords": [
"frontend",
"vite",
"vite-plugin",
"@vitejs/plugin-legacy"
],
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vitejs/vite.git",
"directory": "packages/plugin-legacy"
},
"bugs": {
"url": "https://github.com/vitejs/vite/issues"
},
"homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
"funding": "https://github.com/vitejs/vite?sponsor=1",
"dependencies": {
"@babel/core": "^7.23.9",
"@babel/preset-env": "^7.23.9",
"browserslist": "^4.23.0",
"browserslist-to-esbuild": "^2.1.1",
"core-js": "^3.36.0",
"magic-string": "^0.30.7",
"regenerator-runtime": "^0.14.1",
"systemjs": "^6.14.3"
},
"peerDependencies": {
"terser": "^5.4.0",
"vite": "^5.0.0"
},
"devDependencies": {
"acorn": "^8.11.3",
"picocolors": "^1.0.0",
"vite": "5.1.5"
},
"scripts": {
"dev": "unbuild --stub",
"build": "unbuild && pnpm run patch-cjs",
"patch-cjs": "tsx ../../scripts/patchCJS.ts"
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+73
View File
@@ -0,0 +1,73 @@
# @vitejs/plugin-vue-jsx [![npm](https://img.shields.io/npm/v/@vitejs/plugin-vue-jsx.svg)](https://npmjs.com/package/@vitejs/plugin-vue-jsx)
Provides Vue 3 JSX & TSX support with HMR.
```js
// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'
export default {
plugins: [
vueJsx({
// options are passed on to @vue/babel-plugin-jsx
}),
],
}
```
## Options
### include
Type: `(string | RegExp)[] | string | RegExp | null`
Default: `/\.[jt]sx$/`
A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files the plugin should operate on.
### exclude
Type: `(string | RegExp)[] | string | RegExp | null`
Default: `undefined`
A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files to be ignored by the plugin.
> See [@vue/babel-plugin-jsx](https://github.com/vuejs/jsx-next) for other options.
## HMR Detection
This plugin supports HMR of Vue JSX components. The detection requirements are:
- The component must be exported.
- The component must be declared by calling `defineComponent` via a root-level statement, either variable declaration or export declaration.
### Supported patterns
```jsx
import { defineComponent } from 'vue'
// named exports w/ variable declaration: ok
export const Foo = defineComponent({})
// named exports referencing variable declaration: ok
const Bar = defineComponent({ render() { return <div>Test</div> }})
export { Bar }
// default export call: ok
export default defineComponent({ render() { return <div>Test</div> }})
// default export referencing variable declaration: ok
const Baz = defineComponent({ render() { return <div>Test</div> }})
export default Baz
```
### Non-supported patterns
```jsx
// not using `defineComponent` call
export const Bar = { ... }
// not exported
const Foo = defineComponent(...)
```
+243
View File
@@ -0,0 +1,243 @@
'use strict';
const node_crypto = require('node:crypto');
const path = require('node:path');
const babel = require('@babel/core');
const jsx = require('@vue/babel-plugin-jsx');
const vite = require('vite');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
const n = Object.create(null);
if (e) {
for (const k in e) {
n[k] = e[k];
}
}
n.default = e;
return n;
}
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
const babel__namespace = /*#__PURE__*/_interopNamespaceCompat(babel);
const jsx__default = /*#__PURE__*/_interopDefaultCompat(jsx);
const ssrRegisterHelperId = "/__vue-jsx-ssr-register-helper";
const ssrRegisterHelperCode = `import { useSSRContext } from "vue"
export ${ssrRegisterHelper.toString()}`;
function ssrRegisterHelper(comp, filename) {
const setup = comp.setup;
comp.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add(filename);
if (setup) {
return setup(props, ctx);
}
};
}
function vueJsxPlugin(options = {}) {
let root = "";
let needHmr = false;
let needSourceMap = true;
const { include, exclude, babelPlugins = [], ...babelPluginOptions } = options;
const filter = vite.createFilter(include || /\.[jt]sx$/, exclude);
return {
name: "vite:vue-jsx",
config(config) {
return {
// only apply esbuild to ts files
// since we are handling jsx and tsx now
esbuild: {
include: /\.ts$/
},
define: {
__VUE_OPTIONS_API__: config.define?.__VUE_OPTIONS_API__ ?? true,
__VUE_PROD_DEVTOOLS__: config.define?.__VUE_PROD_DEVTOOLS__ ?? false
}
};
},
configResolved(config) {
needHmr = config.command === "serve" && !config.isProduction;
needSourceMap = config.command === "serve" || !!config.build.sourcemap;
root = config.root;
},
resolveId(id) {
if (id === ssrRegisterHelperId) {
return id;
}
},
load(id) {
if (id === ssrRegisterHelperId) {
return ssrRegisterHelperCode;
}
},
async transform(code, id, opt) {
const ssr = opt?.ssr === true;
const [filepath] = id.split("?");
if (filter(id) || filter(filepath)) {
const plugins = [[jsx__default, babelPluginOptions], ...babelPlugins];
if (id.endsWith(".tsx") || filepath.endsWith(".tsx")) {
plugins.push([
// @ts-ignore missing type
await import('@babel/plugin-transform-typescript').then(
(r) => r.default
),
// @ts-ignore
{ isTSX: true, allowExtensions: true }
]);
}
if (!ssr && !needHmr) {
plugins.push(() => {
return {
visitor: {
CallExpression: {
enter(_path) {
if (isDefineComponentCall(_path.node)) {
const callee = _path.node.callee;
callee.name = `/* @__PURE__ */ ${callee.name}`;
}
}
}
}
};
});
}
const result = babel__namespace.transformSync(code, {
babelrc: false,
ast: true,
plugins,
sourceMaps: needSourceMap,
sourceFileName: id,
configFile: false
});
if (!ssr && !needHmr) {
if (!result.code)
return;
return {
code: result.code,
map: result.map
};
}
const declaredComponents = [];
const hotComponents = [];
let hasDefault = false;
for (const node of result.ast.program.body) {
if (node.type === "VariableDeclaration") {
const names = parseComponentDecls(node);
if (names.length) {
declaredComponents.push(...names);
}
}
if (node.type === "ExportNamedDeclaration") {
if (node.declaration && node.declaration.type === "VariableDeclaration") {
hotComponents.push(
...parseComponentDecls(node.declaration).map((name) => ({
local: name,
exported: name,
id: getHash(id + name)
}))
);
} else if (node.specifiers.length) {
for (const spec of node.specifiers) {
if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") {
const matched = declaredComponents.find(
(name) => name === spec.local.name
);
if (matched) {
hotComponents.push({
local: spec.local.name,
exported: spec.exported.name,
id: getHash(id + spec.exported.name)
});
}
}
}
}
}
if (node.type === "ExportDefaultDeclaration") {
if (node.declaration.type === "Identifier") {
const _name = node.declaration.name;
const matched = declaredComponents.find((name) => name === _name);
if (matched) {
hotComponents.push({
local: _name,
exported: "default",
id: getHash(id + "default")
});
}
} else if (isDefineComponentCall(node.declaration)) {
hasDefault = true;
hotComponents.push({
local: "__default__",
exported: "default",
id: getHash(id + "default")
});
}
}
}
if (hotComponents.length) {
if (hasDefault && (needHmr || ssr)) {
result.code = result.code.replace(
/export default defineComponent/g,
`const __default__ = defineComponent`
) + `
export default __default__`;
}
if (needHmr && !ssr && !/\?vue&type=script/.test(id)) {
let code2 = result.code;
let callbackCode = ``;
for (const { local, exported, id: id2 } of hotComponents) {
code2 += `
${local}.__hmrId = "${id2}"
__VUE_HMR_RUNTIME__.createRecord("${id2}", ${local})`;
callbackCode += `
__VUE_HMR_RUNTIME__.reload("${id2}", __${exported})`;
}
const newCompNames = hotComponents.map((c) => `${c.exported}: __${c.exported}`).join(",");
code2 += `
import.meta.hot.accept(({${newCompNames}}) => {${callbackCode}
})`;
result.code = code2;
}
if (ssr) {
const normalizedId = vite.normalizePath(path__default.relative(root, id));
let ssrInjectCode = `
import { ssrRegisterHelper } from "${ssrRegisterHelperId}"
const __moduleId = ${JSON.stringify(normalizedId)}`;
for (const { local } of hotComponents) {
ssrInjectCode += `
ssrRegisterHelper(${local}, __moduleId)`;
}
result.code += ssrInjectCode;
}
}
if (!result.code)
return;
return {
code: result.code,
map: result.map
};
}
}
};
}
function parseComponentDecls(node) {
const names = [];
for (const decl of node.declarations) {
if (decl.id.type === "Identifier" && isDefineComponentCall(decl.init)) {
names.push(decl.id.name);
}
}
return names;
}
function isDefineComponentCall(node) {
return node && node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "defineComponent";
}
function getHash(text) {
return node_crypto.createHash("sha256").update(text).digest("hex").substring(0, 8);
}
module.exports = vueJsxPlugin;
module.exports.default = vueJsxPlugin;
+14
View File
@@ -0,0 +1,14 @@
import { FilterPattern, Plugin } from 'vite';
import { VueJSXPluginOptions } from '@vue/babel-plugin-jsx';
interface FilterOptions {
include?: FilterPattern;
exclude?: FilterPattern;
}
type Options = VueJSXPluginOptions & FilterOptions & {
babelPlugins?: any[];
};
declare function vueJsxPlugin(options?: Options): Plugin;
export { type FilterOptions, type Options, vueJsxPlugin as default };
+14
View File
@@ -0,0 +1,14 @@
import { FilterPattern, Plugin } from 'vite';
import { VueJSXPluginOptions } from '@vue/babel-plugin-jsx';
interface FilterOptions {
include?: FilterPattern;
exclude?: FilterPattern;
}
type Options = VueJSXPluginOptions & FilterOptions & {
babelPlugins?: any[];
};
declare function vueJsxPlugin(options?: Options): Plugin;
export { type FilterOptions, type Options, vueJsxPlugin as default };
+14
View File
@@ -0,0 +1,14 @@
import { FilterPattern, Plugin } from 'vite';
import { VueJSXPluginOptions } from '@vue/babel-plugin-jsx';
interface FilterOptions {
include?: FilterPattern;
exclude?: FilterPattern;
}
type Options = VueJSXPluginOptions & FilterOptions & {
babelPlugins?: any[];
};
declare function vueJsxPlugin(options?: Options): Plugin;
export { type FilterOptions, type Options, vueJsxPlugin as default };
+222
View File
@@ -0,0 +1,222 @@
import { createHash } from 'node:crypto';
import path from 'node:path';
import * as babel from '@babel/core';
import jsx from '@vue/babel-plugin-jsx';
import { createFilter, normalizePath } from 'vite';
const ssrRegisterHelperId = "/__vue-jsx-ssr-register-helper";
const ssrRegisterHelperCode = `import { useSSRContext } from "vue"
export ${ssrRegisterHelper.toString()}`;
function ssrRegisterHelper(comp, filename) {
const setup = comp.setup;
comp.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add(filename);
if (setup) {
return setup(props, ctx);
}
};
}
function vueJsxPlugin(options = {}) {
let root = "";
let needHmr = false;
let needSourceMap = true;
const { include, exclude, babelPlugins = [], ...babelPluginOptions } = options;
const filter = createFilter(include || /\.[jt]sx$/, exclude);
return {
name: "vite:vue-jsx",
config(config) {
return {
// only apply esbuild to ts files
// since we are handling jsx and tsx now
esbuild: {
include: /\.ts$/
},
define: {
__VUE_OPTIONS_API__: config.define?.__VUE_OPTIONS_API__ ?? true,
__VUE_PROD_DEVTOOLS__: config.define?.__VUE_PROD_DEVTOOLS__ ?? false
}
};
},
configResolved(config) {
needHmr = config.command === "serve" && !config.isProduction;
needSourceMap = config.command === "serve" || !!config.build.sourcemap;
root = config.root;
},
resolveId(id) {
if (id === ssrRegisterHelperId) {
return id;
}
},
load(id) {
if (id === ssrRegisterHelperId) {
return ssrRegisterHelperCode;
}
},
async transform(code, id, opt) {
const ssr = opt?.ssr === true;
const [filepath] = id.split("?");
if (filter(id) || filter(filepath)) {
const plugins = [[jsx, babelPluginOptions], ...babelPlugins];
if (id.endsWith(".tsx") || filepath.endsWith(".tsx")) {
plugins.push([
// @ts-ignore missing type
await import('@babel/plugin-transform-typescript').then(
(r) => r.default
),
// @ts-ignore
{ isTSX: true, allowExtensions: true }
]);
}
if (!ssr && !needHmr) {
plugins.push(() => {
return {
visitor: {
CallExpression: {
enter(_path) {
if (isDefineComponentCall(_path.node)) {
const callee = _path.node.callee;
callee.name = `/* @__PURE__ */ ${callee.name}`;
}
}
}
}
};
});
}
const result = babel.transformSync(code, {
babelrc: false,
ast: true,
plugins,
sourceMaps: needSourceMap,
sourceFileName: id,
configFile: false
});
if (!ssr && !needHmr) {
if (!result.code)
return;
return {
code: result.code,
map: result.map
};
}
const declaredComponents = [];
const hotComponents = [];
let hasDefault = false;
for (const node of result.ast.program.body) {
if (node.type === "VariableDeclaration") {
const names = parseComponentDecls(node);
if (names.length) {
declaredComponents.push(...names);
}
}
if (node.type === "ExportNamedDeclaration") {
if (node.declaration && node.declaration.type === "VariableDeclaration") {
hotComponents.push(
...parseComponentDecls(node.declaration).map((name) => ({
local: name,
exported: name,
id: getHash(id + name)
}))
);
} else if (node.specifiers.length) {
for (const spec of node.specifiers) {
if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") {
const matched = declaredComponents.find(
(name) => name === spec.local.name
);
if (matched) {
hotComponents.push({
local: spec.local.name,
exported: spec.exported.name,
id: getHash(id + spec.exported.name)
});
}
}
}
}
}
if (node.type === "ExportDefaultDeclaration") {
if (node.declaration.type === "Identifier") {
const _name = node.declaration.name;
const matched = declaredComponents.find((name) => name === _name);
if (matched) {
hotComponents.push({
local: _name,
exported: "default",
id: getHash(id + "default")
});
}
} else if (isDefineComponentCall(node.declaration)) {
hasDefault = true;
hotComponents.push({
local: "__default__",
exported: "default",
id: getHash(id + "default")
});
}
}
}
if (hotComponents.length) {
if (hasDefault && (needHmr || ssr)) {
result.code = result.code.replace(
/export default defineComponent/g,
`const __default__ = defineComponent`
) + `
export default __default__`;
}
if (needHmr && !ssr && !/\?vue&type=script/.test(id)) {
let code2 = result.code;
let callbackCode = ``;
for (const { local, exported, id: id2 } of hotComponents) {
code2 += `
${local}.__hmrId = "${id2}"
__VUE_HMR_RUNTIME__.createRecord("${id2}", ${local})`;
callbackCode += `
__VUE_HMR_RUNTIME__.reload("${id2}", __${exported})`;
}
const newCompNames = hotComponents.map((c) => `${c.exported}: __${c.exported}`).join(",");
code2 += `
import.meta.hot.accept(({${newCompNames}}) => {${callbackCode}
})`;
result.code = code2;
}
if (ssr) {
const normalizedId = normalizePath(path.relative(root, id));
let ssrInjectCode = `
import { ssrRegisterHelper } from "${ssrRegisterHelperId}"
const __moduleId = ${JSON.stringify(normalizedId)}`;
for (const { local } of hotComponents) {
ssrInjectCode += `
ssrRegisterHelper(${local}, __moduleId)`;
}
result.code += ssrInjectCode;
}
}
if (!result.code)
return;
return {
code: result.code,
map: result.map
};
}
}
};
}
function parseComponentDecls(node) {
const names = [];
for (const decl of node.declarations) {
if (decl.id.type === "Identifier" && isDefineComponentCall(decl.init)) {
names.push(decl.id.name);
}
}
return names;
}
function isDefineComponentCall(node) {
return node && node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "defineComponent";
}
function getHash(text) {
return createHash("sha256").update(text).digest("hex").substring(0, 8);
}
export { vueJsxPlugin as default };
+47
View File
@@ -0,0 +1,47 @@
{
"name": "@vitejs/plugin-vue-jsx",
"version": "3.1.0",
"license": "MIT",
"author": "Evan You",
"files": [
"dist"
],
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vitejs/vite-plugin-vue.git",
"directory": "packages/plugin-vue-jsx"
},
"bugs": {
"url": "https://github.com/vitejs/vite-plugin-vue/issues"
},
"homepage": "https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx#readme",
"dependencies": {
"@babel/core": "^7.23.3",
"@babel/plugin-transform-typescript": "^7.23.3",
"@vue/babel-plugin-jsx": "^1.1.5"
},
"devDependencies": {
"vite": "^4.5.0"
},
"peerDependencies": {
"vite": "^4.0.0 || ^5.0.0",
"vue": "^3.0.0"
},
"scripts": {
"dev": "unbuild --stub",
"build": "unbuild && pnpm run patch-cjs",
"patch-cjs": "tsx ../../scripts/patchCJS.ts"
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+261
View File
@@ -0,0 +1,261 @@
# @vitejs/plugin-vue [![npm](https://img.shields.io/npm/v/@vitejs/plugin-vue.svg)](https://npmjs.com/package/@vitejs/plugin-vue)
> Note: as of `vue` 3.2.13+ and `@vitejs/plugin-vue` 1.9.0+, `@vue/compiler-sfc` is no longer required as a peer dependency.
```js
// vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
plugins: [vue()],
}
```
For JSX / TSX support, [`@vitejs/plugin-vue-jsx`](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx) is also needed.
## Options
```ts
export interface Options {
include?: string | RegExp | (string | RegExp)[]
exclude?: string | RegExp | (string | RegExp)[]
isProduction?: boolean
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[]
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean
}
// `script`, `template` and `style` are lower-level compiler options
// to pass on to respective APIs of `vue/compiler-sfc`
script?: Partial<
Omit<
SFCScriptCompileOptions,
| 'id'
| 'isProd'
| 'inlineTemplate'
| 'templateOptions'
| 'sourceMap'
| 'genDefaultAs'
| 'customElement'
>
>
template?: Partial<
Omit<
SFCTemplateCompileOptions,
| 'id'
| 'source'
| 'ast'
| 'filename'
| 'scoped'
| 'slotted'
| 'isProd'
| 'inMap'
| 'ssr'
| 'ssrCssVars'
| 'preprocessLang'
>
>
style?: Partial<
Omit<
SFCStyleCompileOptions,
| 'filename'
| 'id'
| 'isProd'
| 'source'
| 'scoped'
| 'cssDevSourcemap'
| 'postcssOptions'
| 'map'
| 'postcssPlugins'
| 'preprocessCustomRequire'
| 'preprocessLang'
| 'preprocessOptions'
>
>
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler
/**
* @deprecated moved to `features.customElement`.
*/
customElements?: boolean | string | RegExp | (string | RegExp)[]
}
```
## Asset URL handling
When `@vitejs/plugin-vue` compiles the `<template>` blocks in SFCs, it also converts any encountered asset URLs into ESM imports.
For example, the following template snippet:
```vue
<img src="../image.png" />
```
Is the same as:
```vue
<script setup>
import _imports_0 from '../image.png'
</script>
<img :src="_imports_0" />
```
By default the following tag/attribute combinations are transformed, and can be configured using the `template.transformAssetUrls` option.
```js
{
video: ['src', 'poster'],
source: ['src'],
img: ['src'],
image: ['xlink:href', 'href'],
use: ['xlink:href', 'href']
}
```
Note that only attribute values that are static strings are transformed. Otherwise, you'd need to import the asset manually, e.g. `import imgUrl from '../image.png'`.
## Example for passing options to `vue/compiler-sfc`:
```ts
import vue from '@vitejs/plugin-vue'
export default {
plugins: [
vue({
template: {
compilerOptions: {
// ...
},
transformAssetUrls: {
// ...
},
},
}),
],
}
```
## Example for transforming custom blocks
```ts
import vue from '@vitejs/plugin-vue'
import yaml from 'js-yaml'
const vueI18nPlugin = {
name: 'vue-i18n',
transform(code, id) {
// if .vue file don't have <i18n> block, just return
if (!/vue&type=i18n/.test(id)) {
return
}
// parse yaml
if (/\.ya?ml$/.test(id)) {
code = JSON.stringify(yaml.load(code.trim()))
}
// mount the value on the i18n property of the component instance
return `export default Comp => {
Comp.i18n = ${code}
}`
},
}
export default {
plugins: [vue(), vueI18nPlugin],
}
```
Create a file named `Demo.vue`, add `lang="yaml"` to the `<i18n>` blocks, then you can use the syntax of `YAML`:
```vue
<template>Hello</template>
<i18n lang="yaml">
message: 'world'
fullWord: 'hello world'
</i18n>
```
`message` is mounted on the i18n property of the component instance, you can use like this:
```vue
<script setup lang="ts">
import Demo from 'components/Demo.vue'
</script>
<template>
<Demo /> {{ Demo.i18n.message }}
<div>{{ Demo.i18n.fullWord }}</div>
</template>
```
## Using Vue SFCs as Custom Elements
> Requires `vue@^3.2.0` & `@vitejs/plugin-vue@^1.4.0`
Vue 3.2 introduces the `defineCustomElement` method, which works with SFCs. By default, `<style>` tags inside SFCs are extracted and merged into CSS files during build. However when shipping a library of custom elements, it may be desirable to inline the styles as JavaScript strings and inject them into the custom elements' shadow root instead.
Starting in 1.4.0, files ending with `*.ce.vue` will be compiled in "custom elements" mode: its `<style>` tags are compiled into inlined CSS strings and attached to the component as its `styles` property:
```js
import { defineCustomElement } from 'vue'
import Example from './Example.ce.vue'
console.log(Example.styles) // ['/* css content */']
// register
customElements.define('my-example', defineCustomElement(Example))
```
Note in custom elements mode there is no need to use `<style scoped>` since the CSS is already scoped inside the shadow DOM.
The `customElement` plugin option can be used to configure the behavior:
- `{ customElement: true }` will import all `*.vue` files in custom element mode.
- Use a string or regex pattern to change how files should be loaded as Custom Elements (this check is applied after `include` and `exclude` matches).
## License
MIT
+2975
View File
File diff suppressed because it is too large Load Diff
+98
View File
@@ -0,0 +1,98 @@
import { ViteDevServer, Plugin } from 'vite';
import * as _compiler from 'vue/compiler-sfc';
import { SFCScriptCompileOptions, SFCTemplateCompileOptions, SFCStyleCompileOptions } from 'vue/compiler-sfc';
interface VueQuery {
vue?: boolean;
src?: string;
type?: 'script' | 'template' | 'style' | 'custom';
index?: number;
lang?: string;
raw?: boolean;
url?: boolean;
scoped?: boolean;
id?: string;
}
declare function parseVueRequest(id: string): {
filename: string;
query: VueQuery;
};
interface Options {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
/**
* In Vite, this option follows Vite's config.
*/
isProduction?: boolean;
script?: Partial<Omit<SFCScriptCompileOptions, 'id' | 'isProd' | 'inlineTemplate' | 'templateOptions' | 'sourceMap' | 'genDefaultAs' | 'customElement' | 'defineModel' | 'propsDestructure'>> & {
/**
* @deprecated defineModel is now a stable feature and always enabled if
* using Vue 3.4 or above.
*/
defineModel?: boolean;
};
template?: Partial<Omit<SFCTemplateCompileOptions, 'id' | 'source' | 'ast' | 'filename' | 'scoped' | 'slotted' | 'isProd' | 'inMap' | 'ssr' | 'ssrCssVars' | 'preprocessLang'>>;
style?: Partial<Omit<SFCStyleCompileOptions, 'filename' | 'id' | 'isProd' | 'source' | 'scoped' | 'cssDevSourcemap' | 'postcssOptions' | 'map' | 'postcssPlugins' | 'preprocessCustomRequire' | 'preprocessLang' | 'preprocessOptions'>>;
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler;
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean;
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean;
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean;
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean;
};
/**
* @deprecated moved to `features.customElement`.
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
}
interface ResolvedOptions extends Options {
compiler: typeof _compiler;
root: string;
sourceMap: boolean;
cssDevSourcemap: boolean;
devServer?: ViteDevServer;
devToolsEnabled?: boolean;
}
interface Api {
get options(): ResolvedOptions;
set options(value: ResolvedOptions);
version: string;
}
declare function vuePlugin(rawOptions?: Options): Plugin<Api>;
export { type Api, type Options, type ResolvedOptions, type VueQuery, vuePlugin as default, parseVueRequest };
+98
View File
@@ -0,0 +1,98 @@
import { ViteDevServer, Plugin } from 'vite';
import * as _compiler from 'vue/compiler-sfc';
import { SFCScriptCompileOptions, SFCTemplateCompileOptions, SFCStyleCompileOptions } from 'vue/compiler-sfc';
interface VueQuery {
vue?: boolean;
src?: string;
type?: 'script' | 'template' | 'style' | 'custom';
index?: number;
lang?: string;
raw?: boolean;
url?: boolean;
scoped?: boolean;
id?: string;
}
declare function parseVueRequest(id: string): {
filename: string;
query: VueQuery;
};
interface Options {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
/**
* In Vite, this option follows Vite's config.
*/
isProduction?: boolean;
script?: Partial<Omit<SFCScriptCompileOptions, 'id' | 'isProd' | 'inlineTemplate' | 'templateOptions' | 'sourceMap' | 'genDefaultAs' | 'customElement' | 'defineModel' | 'propsDestructure'>> & {
/**
* @deprecated defineModel is now a stable feature and always enabled if
* using Vue 3.4 or above.
*/
defineModel?: boolean;
};
template?: Partial<Omit<SFCTemplateCompileOptions, 'id' | 'source' | 'ast' | 'filename' | 'scoped' | 'slotted' | 'isProd' | 'inMap' | 'ssr' | 'ssrCssVars' | 'preprocessLang'>>;
style?: Partial<Omit<SFCStyleCompileOptions, 'filename' | 'id' | 'isProd' | 'source' | 'scoped' | 'cssDevSourcemap' | 'postcssOptions' | 'map' | 'postcssPlugins' | 'preprocessCustomRequire' | 'preprocessLang' | 'preprocessOptions'>>;
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler;
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean;
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean;
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean;
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean;
};
/**
* @deprecated moved to `features.customElement`.
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
}
interface ResolvedOptions extends Options {
compiler: typeof _compiler;
root: string;
sourceMap: boolean;
cssDevSourcemap: boolean;
devServer?: ViteDevServer;
devToolsEnabled?: boolean;
}
interface Api {
get options(): ResolvedOptions;
set options(value: ResolvedOptions);
version: string;
}
declare function vuePlugin(rawOptions?: Options): Plugin<Api>;
export { type Api, type Options, type ResolvedOptions, type VueQuery, vuePlugin as default, parseVueRequest };
+98
View File
@@ -0,0 +1,98 @@
import { ViteDevServer, Plugin } from 'vite';
import * as _compiler from 'vue/compiler-sfc';
import { SFCScriptCompileOptions, SFCTemplateCompileOptions, SFCStyleCompileOptions } from 'vue/compiler-sfc';
interface VueQuery {
vue?: boolean;
src?: string;
type?: 'script' | 'template' | 'style' | 'custom';
index?: number;
lang?: string;
raw?: boolean;
url?: boolean;
scoped?: boolean;
id?: string;
}
declare function parseVueRequest(id: string): {
filename: string;
query: VueQuery;
};
interface Options {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
/**
* In Vite, this option follows Vite's config.
*/
isProduction?: boolean;
script?: Partial<Omit<SFCScriptCompileOptions, 'id' | 'isProd' | 'inlineTemplate' | 'templateOptions' | 'sourceMap' | 'genDefaultAs' | 'customElement' | 'defineModel' | 'propsDestructure'>> & {
/**
* @deprecated defineModel is now a stable feature and always enabled if
* using Vue 3.4 or above.
*/
defineModel?: boolean;
};
template?: Partial<Omit<SFCTemplateCompileOptions, 'id' | 'source' | 'ast' | 'filename' | 'scoped' | 'slotted' | 'isProd' | 'inMap' | 'ssr' | 'ssrCssVars' | 'preprocessLang'>>;
style?: Partial<Omit<SFCStyleCompileOptions, 'filename' | 'id' | 'isProd' | 'source' | 'scoped' | 'cssDevSourcemap' | 'postcssOptions' | 'map' | 'postcssPlugins' | 'preprocessCustomRequire' | 'preprocessLang' | 'preprocessOptions'>>;
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler;
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean;
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean;
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean;
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean;
};
/**
* @deprecated moved to `features.customElement`.
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
}
interface ResolvedOptions extends Options {
compiler: typeof _compiler;
root: string;
sourceMap: boolean;
cssDevSourcemap: boolean;
devServer?: ViteDevServer;
devToolsEnabled?: boolean;
}
interface Api {
get options(): ResolvedOptions;
set options(value: ResolvedOptions);
version: string;
}
declare function vuePlugin(rawOptions?: Options): Plugin<Api>;
export { type Api, type Options, type ResolvedOptions, type VueQuery, vuePlugin as default, parseVueRequest };
+2961
View File
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
{
"name": "@vitejs/plugin-vue",
"version": "5.1.0",
"license": "MIT",
"author": "Evan You",
"files": [
"dist"
],
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vitejs/vite-plugin-vue.git",
"directory": "packages/plugin-vue"
},
"bugs": {
"url": "https://github.com/vitejs/vite-plugin-vue/issues"
},
"homepage": "https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#readme",
"peerDependencies": {
"vite": "^5.0.0",
"vue": "^3.2.25"
},
"devDependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"debug": "^4.3.5",
"rollup": "^4.19.0",
"slash": "^5.1.0",
"source-map-js": "^1.2.0",
"vite": "^5.3.4",
"vue": "^3.4.29"
},
"scripts": {
"dev": "unbuild --stub",
"build": "unbuild && pnpm run patch-cjs",
"patch-cjs": "tsx ../../scripts/patchCJS.ts"
}
}