diff --git a/docs/en/plugins/vite-plugin-external/usage.md b/docs/en/plugins/vite-plugin-external/usage.md
index f1f1942..b9764ec 100644
--- a/docs/en/plugins/vite-plugin-external/usage.md
+++ b/docs/en/plugins/vite-plugin-external/usage.md
@@ -57,6 +57,34 @@ export default defineConfig({
});
```
+## Dynamic Configuration of ESM format CDN
+
+> Replace specific CDN links with dynamic configuration, and inject `modulepreload` links into the HTML header.
+
+```js
+import react from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+import pluginExternal from 'vite-plugin-external';
+
+export default defineConfig({
+ plugins: [
+ react({
+ jsxRuntime: 'classic'
+ }),
+ pluginExternal({
+ externals(libName) {
+ if (libName === 'react') {
+ return 'https://esm.sh/react@18.3.1';
+ }
+ if (libName === 'react-dom/client') {
+ return 'https://esm.sh/react-dom@18.3.1';
+ }
+ }
+ })
+ ]
+});
+```
+
## Multi-Environment Configuration
> Sometimes development and production environments use different CDNs. You can configure `development` and `production` modes for respective external dependencies.
diff --git a/docs/zh/plugins/vite-plugin-external/usage.md b/docs/zh/plugins/vite-plugin-external/usage.md
index e605d44..12565fc 100644
--- a/docs/zh/plugins/vite-plugin-external/usage.md
+++ b/docs/zh/plugins/vite-plugin-external/usage.md
@@ -59,6 +59,34 @@ export default defineConfig({
});
```
+## 动态配置 ESM 格式 CDN
+
+> 将指定的依赖替换为 CDN 资源, 并在 `index.html` 中添加 `modulepreload` 链接标签
+
+```js
+import react from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+import pluginExternal from 'vite-plugin-external';
+
+export default defineConfig({
+ plugins: [
+ react({
+ jsxRuntime: 'classic'
+ }),
+ pluginExternal({
+ externals(libName) {
+ if (libName === 'react') {
+ return 'https://esm.sh/react@18.3.1';
+ }
+ if (libName === 'react-dom/client') {
+ return 'https://esm.sh/react-dom@18.3.1';
+ }
+ }
+ })
+ ]
+});
+```
+
## 多模式场景配置
> 有时候可能开发环境和生产环境用到的 cdn 不一致。针对这种情况,可以配置 `development` 和 `production` 两个模式,分别对应开发环境和生产环境的外部依赖。
diff --git a/examples/config/vite.external.10.mts b/examples/config/vite.external.10.mts
index f2a35a8..5c765be 100644
--- a/examples/config/vite.external.10.mts
+++ b/examples/config/vite.external.10.mts
@@ -10,15 +10,18 @@ export default defineConfig({
}) as unknown as Plugin,
vitePluginExternal({
logLevel: 'TRACE',
- // interop: 'auto',
- externals(libName) {
- if (libName === 'react') {
- return 'https://esm.sh/react@18.3.1';
- }
- if (libName === 'react-dom/client') {
- return 'https://esm.sh/react-dom@18.3.1';
- }
+ externals: {
+ react: 'https://esm.sh/react@18.3.1',
+ 'react-dom/client': 'https://esm.sh/react-dom@18.3.1'
}
+ // externals(libName) {
+ // if (libName === 'react') {
+ // return 'https://esm.sh/react@18.3.1';
+ // }
+ // if (libName === 'react-dom/client') {
+ // return 'https://esm.sh/react-dom@18.3.1';
+ // }
+ // }
})
],
// resolve: {
diff --git a/examples/vite3-demo/index5.html b/examples/vite3-demo/index5.html
new file mode 100644
index 0000000..cca8bfe
--- /dev/null
+++ b/examples/vite3-demo/index5.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
+
diff --git a/examples/vite3-demo/package.json b/examples/vite3-demo/package.json
index 9670a54..b9f8dab 100644
--- a/examples/vite3-demo/package.json
+++ b/examples/vite3-demo/package.json
@@ -20,6 +20,7 @@
"build:external.7": "vite build --config=../config/vite.external.7.mts",
"build:external.8": "vite build --config=../config/vite.external.8.mts",
"build:external.9": "vite build --config=../config/vite.external.9.mts",
+ "build:external.10": "vite build --config=../config/vite.external.10.mts",
"build:hook-use.1": "vite build --config=../config/vite.hook-use.1.mts",
"build:include-css.1": "vite build --config=../config/vite.include-css.1.mts",
"build:mock-data.1": "vite build --config=../config/vite.mock-data.1.mts",
@@ -34,6 +35,7 @@
"dev:external.6": "vite dev --config=../config/vite.external.6.mts",
"dev:external.7": "vite dev --config=../config/vite.external.7.mts",
"dev:external.8": "vite dev --config=../config/vite.external.8.mts",
+ "dev:external.10": "vite dev --config=../config/vite.external.10.mts",
"dev:mock-data.1": "vite dev --config=../config/vite.mock-data.1.mts",
"dev:mock-data.2": "vite dev --config=../config/vite.mock-data.2.mts",
"dev:mock-data.3": "vite dev --config=../config/vite.mock-data.3.mts",
diff --git a/examples/vite4-demo/index5.html b/examples/vite4-demo/index5.html
new file mode 100644
index 0000000..cca8bfe
--- /dev/null
+++ b/examples/vite4-demo/index5.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
+
diff --git a/examples/vite4-demo/package.json b/examples/vite4-demo/package.json
index 9f7641d..aed65e8 100644
--- a/examples/vite4-demo/package.json
+++ b/examples/vite4-demo/package.json
@@ -20,6 +20,7 @@
"build:external.7": "vite build --config=../config/vite.external.7.mts",
"build:external.8": "vite build --config=../config/vite.external.8.mts",
"build:external.9": "vite build --config=../config/vite.external.9.mts",
+ "build:external.10": "vite build --config=../config/vite.external.10.mts",
"build:hook-use.1": "vite build --config=../config/vite.hook-use.1.mts",
"build:include-css.1": "vite build --config=../config/vite.include-css.1.mts",
"build:mock-data.1": "vite build --config=../config/vite.mock-data.1.mts",
diff --git a/examples/vite5-demo/index5.html b/examples/vite5-demo/index5.html
new file mode 100644
index 0000000..cca8bfe
--- /dev/null
+++ b/examples/vite5-demo/index5.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
+
diff --git a/examples/vite5-demo/package.json b/examples/vite5-demo/package.json
index e2d308b..ddb74dd 100644
--- a/examples/vite5-demo/package.json
+++ b/examples/vite5-demo/package.json
@@ -20,6 +20,7 @@
"build:external.7": "vite build --config=../config/vite.external.7.mts",
"build:external.8": "vite build --config=../config/vite.external.8.mts",
"build:external.9": "vite build --config=../config/vite.external.9.mts",
+ "build:external.10": "vite build --config=../config/vite.external.10.mts",
"build:hook-use.1": "vite build --config=../config/vite.hook-use.1.mts",
"build:include-css.1": "vite build --config=../config/vite.include-css.1.mts",
"build:mock-data.1": "vite build --config=../config/vite.mock-data.1.mts",
diff --git a/packages/vite-plugin-external/README.md b/packages/vite-plugin-external/README.md
index ba44da9..5ebbdde 100644
--- a/packages/vite-plugin-external/README.md
+++ b/packages/vite-plugin-external/README.md
@@ -100,6 +100,27 @@ export default defineConfig({
});
```
+## Changelog
+
+* **6.2.0**
+ * Support links to external resources
+
+* **6.1.0**
+ * Reimplemented external plugin logic for Vite 6.x compatibility
+ * Added optional `rollback` parameter to revert to previous implementation
+ * Added optional `logLevel` parameter to control logging level (values: "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL" | "OFF")
+ * Support to set `externals` as a function
+
+* **6.0.0**
+ * Added optional `externalGlobals` parameter to fix issue [rollup#3188](https://github.com/rollup/rollup/issues/3188)
+
+* **4.3.1**
+ * `externalizeDeps` configuration supports regex patterns
+
+* **4.3.0**
+ * Previous `mode: false` logic replaced with `interop: 'auto'`
+ * Added `nodeBuiltins` and `externalizeDeps` configurations for Node module bundling
+
## Q&A
* Q: Page cannot load after modifying `externals`
diff --git a/packages/vite-plugin-external/package.json b/packages/vite-plugin-external/package.json
index 07d3e7e..47b4bd3 100644
--- a/packages/vite-plugin-external/package.json
+++ b/packages/vite-plugin-external/package.json
@@ -1,6 +1,6 @@
{
"name": "vite-plugin-external",
- "version": "6.2.0",
+ "version": "6.2.1",
"description": "Excludes specified module dependencies from runtime code and built bundles.",
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
diff --git a/packages/vite-plugin-external/src/lib/handleExternals.ts b/packages/vite-plugin-external/src/lib/handleExternals.ts
index 07cbe1d..55e1269 100644
--- a/packages/vite-plugin-external/src/lib/handleExternals.ts
+++ b/packages/vite-plugin-external/src/lib/handleExternals.ts
@@ -69,26 +69,28 @@ export function setExternals(
const rollupOptions: RollupOptions = getValue(config, 'build.rollupOptions', {});
// externalize dependencies for build command
- const { nodeBuiltins, externalizeDeps } = opts;
+ const { nodeBuiltins, externalizeDeps, command } = opts;
- // handle nodejs built-in modules
- if (nodeBuiltins) {
- let builtinModuleArray;
- externalHook.use(builtinModuleArray = builtinModules.map((builtinModule) => {
- return new RegExp(`^(?:node:)?${escapeRegex(builtinModule)}(?:/.+)*$`);
- }));
+ if (command === 'build') {
+ // handle nodejs built-in modules
+ if (nodeBuiltins) {
+ let builtinModuleArray;
+ externalHook.use(builtinModuleArray = builtinModules.map((builtinModule) => {
+ return new RegExp(`^(?:node:)?${escapeRegex(builtinModule)}(?:/.+)*$`);
+ }));
- logger.debug('Externalize nodejs built-in modules:', builtinModuleArray);
- }
+ logger.debug('Externalize nodejs built-in modules:', builtinModuleArray);
+ }
- // externalize given dependencies
- if (externalizeDeps) {
- let deps;
- externalHook.use(deps = externalizeDeps.map((dep) => {
- return types.isRegExp(dep) ? dep : new RegExp(`^${escapeRegex(dep)}(?:/.+)*$`);
- }));
+ // externalize given dependencies
+ if (externalizeDeps) {
+ let deps;
+ externalHook.use(deps = externalizeDeps.map((dep) => {
+ return types.isRegExp(dep) ? dep : new RegExp(`^${escapeRegex(dep)}(?:/.+)*$`);
+ }));
- logger.debug('Externalize given dependencies:', deps);
+ logger.debug('Externalize given dependencies:', deps);
+ }
}
// Merge external dependencies
diff --git a/packages/vp-runtime-helper/package.json b/packages/vp-runtime-helper/package.json
index acb0e63..ec4ab25 100644
--- a/packages/vp-runtime-helper/package.json
+++ b/packages/vp-runtime-helper/package.json
@@ -1,6 +1,6 @@
{
"name": "vp-runtime-helper",
- "version": "1.0.7",
+ "version": "1.0.8",
"description": "Vite plugin runtime helper.",
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
diff --git a/packages/vp-runtime-helper/src/getDepsCacheDir.ts b/packages/vp-runtime-helper/src/depsCache.ts
similarity index 53%
rename from packages/vp-runtime-helper/src/getDepsCacheDir.ts
rename to packages/vp-runtime-helper/src/depsCache.ts
index 9a9272c..d302e3c 100644
--- a/packages/vp-runtime-helper/src/getDepsCacheDir.ts
+++ b/packages/vp-runtime-helper/src/depsCache.ts
@@ -3,7 +3,7 @@ import { resolve as pathResolve } from 'node:path';
import type { ResolvedConfig } from 'vite';
import { normalizePath } from 'vite';
-import { getHash } from './getHash';
+import { getHash } from './hash';
function getDepsCacheSuffix(config: ResolvedConfig, ssr: boolean): string {
let suffix = '';
@@ -27,3 +27,30 @@ function getDepsCacheDirPrefix(config: ResolvedConfig): string {
export function getDepsCacheDir(config: ResolvedConfig, ssr: boolean): string {
return getDepsCacheDirPrefix(config) + getDepsCacheSuffix(config, ssr);
}
+
+const FLATTEN_ID_HASH_LENGTH = 8;
+const FLATTEN_ID_MAX_FILE_LENGTH = 170;
+const limitFlattenIdLength = (
+ id: string,
+ limit: number = FLATTEN_ID_MAX_FILE_LENGTH,
+): string => {
+ if (id.length <= limit) {
+ return id;
+ }
+ return `${id.slice(0, limit - (FLATTEN_ID_HASH_LENGTH + 1))}_${getHash(id)}`;
+};
+
+const replaceSlashOrColonRE = /[/:]/g;
+const replaceDotRE = /\./g;
+const replaceNestedIdRE = /\s*>\s*/g;
+const replaceHashRE = /#/g;
+export function flattenId(id: string): string {
+ const flatId = limitFlattenIdLength(
+ id
+ .replace(replaceSlashOrColonRE, '_')
+ .replace(replaceDotRE, '__')
+ .replace(replaceNestedIdRE, '___')
+ .replace(replaceHashRE, '____'),
+ );
+ return flatId;
+}
diff --git a/packages/vp-runtime-helper/src/devServer.ts b/packages/vp-runtime-helper/src/devServer.ts
new file mode 100644
index 0000000..e2cc1cb
--- /dev/null
+++ b/packages/vp-runtime-helper/src/devServer.ts
@@ -0,0 +1,21 @@
+import type { PreviewServer, ViteDevServer } from 'vite';
+import { normalizePath } from 'vite';
+export function isDevServer(
+ server: ViteDevServer | PreviewServer,
+): server is ViteDevServer {
+ return 'pluginContainer' in server;
+}
+
+const VOLUME_RE = /^[A-Z]:/i;
+export const FS_PREFIX = '/@fs/';
+export function fsPathFromId(id: string): string {
+ const fsPath = normalizePath(
+ id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id,
+ );
+ return fsPath.startsWith('/') || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`;
+}
+
+const postfixRE = /[?#].*$/;
+export function cleanUrl(url: string): string {
+ return url.replace(postfixRE, '');
+}
diff --git a/packages/vp-runtime-helper/src/flattenId.ts b/packages/vp-runtime-helper/src/flattenId.ts
deleted file mode 100644
index 0f2d026..0000000
--- a/packages/vp-runtime-helper/src/flattenId.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { getHash } from './getHash';
-
-
-const FLATTEN_ID_HASH_LENGTH = 8;
-const FLATTEN_ID_MAX_FILE_LENGTH = 170;
-const limitFlattenIdLength = (
- id: string,
- limit: number = FLATTEN_ID_MAX_FILE_LENGTH,
-): string => {
- if (id.length <= limit) {
- return id;
- }
- return `${id.slice(0, limit - (FLATTEN_ID_HASH_LENGTH + 1))}_${getHash(id)}`;
-};
-
-
-const replaceSlashOrColonRE = /[/:]/g;
-const replaceDotRE = /\./g;
-const replaceNestedIdRE = /\s*>\s*/g;
-const replaceHashRE = /#/g;
-export function flattenId(id: string): string {
- const flatId = limitFlattenIdLength(
- id
- .replace(replaceSlashOrColonRE, '_')
- .replace(replaceDotRE, '__')
- .replace(replaceNestedIdRE, '___')
- .replace(replaceHashRE, '____'),
- );
- return flatId;
-}
diff --git a/packages/vp-runtime-helper/src/getHash.ts b/packages/vp-runtime-helper/src/hash.ts
similarity index 100%
rename from packages/vp-runtime-helper/src/getHash.ts
rename to packages/vp-runtime-helper/src/hash.ts
diff --git a/packages/vp-runtime-helper/src/index.ts b/packages/vp-runtime-helper/src/index.ts
index 75f0af6..b6d0432 100644
--- a/packages/vp-runtime-helper/src/index.ts
+++ b/packages/vp-runtime-helper/src/index.ts
@@ -1,7 +1,7 @@
import { isAbsolute, join } from 'node:path';
import figlet from 'figlet';
-import { normalizePath, PreviewServer, ViteDevServer } from 'vite';
+import { normalizePath } from 'vite';
const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
export function escapeRegex(str: string): string {
@@ -21,26 +21,6 @@ export function toAbsolutePath(pth: string, cwd: string): string {
return normalizePath(pth);
}
-const postfixRE = /[?#].*$/;
-export function cleanUrl(url: string): string {
- return url.replace(postfixRE, '');
-}
-
-export function isDevServer(
- server: ViteDevServer | PreviewServer,
-): server is ViteDevServer {
- return 'pluginContainer' in server;
-}
-
-const VOLUME_RE = /^[A-Z]:/i;
-export const FS_PREFIX = '/@fs/';
-export function fsPathFromId(id: string): string {
- const fsPath = normalizePath(
- id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id,
- );
- return fsPath.startsWith('/') || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`;
-}
-
export function sleep(ms: number): Promise {
return new Promise((resolve) => {
setTimeout(resolve, ms);
@@ -48,11 +28,11 @@ export function sleep(ms: number): Promise {
}
export * from './colorful';
-export * from './flattenId';
+export * from './depsCache';
+export * from './devServer';
export * from './generateStarter';
-export * from './getDepsCacheDir';
-export * from './getHash';
-export * from './getRuntimeVersion';
export * from './getValue';
+export * from './hash';
export * from './logger';
+export * from './version';
export type { LogLevel } from 'base-log-factory';
diff --git a/packages/vp-runtime-helper/src/getRuntimeVersion.ts b/packages/vp-runtime-helper/src/version.ts
similarity index 100%
rename from packages/vp-runtime-helper/src/getRuntimeVersion.ts
rename to packages/vp-runtime-helper/src/version.ts