diff --git a/__tests__/fixtures/cdn-plugin/index.html b/__tests__/fixtures/cdn-plugin/index.html
new file mode 100644
index 0000000..44299c3
--- /dev/null
+++ b/__tests__/fixtures/cdn-plugin/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
\ No newline at end of file
diff --git a/__tests__/fixtures/cdn-plugin/main.js b/__tests__/fixtures/cdn-plugin/main.js
new file mode 100644
index 0000000..fc76027
--- /dev/null
+++ b/__tests__/fixtures/cdn-plugin/main.js
@@ -0,0 +1,15 @@
+/* eslint-disable */
+import { createApp, createVNode, defineComponent } from 'vue'
+
+const App = defineComponent({
+ name: 'Application',
+ setup() {
+ return () => createVNode('div', null, 'hello world')
+ }
+})
+
+createApp(App).mount('#app')
+
+export * from 'vue'
+const version = 'cdn-plugin-test-version'
+export { version }
diff --git a/__tests__/fixtures/external-plugin/button.js b/__tests__/fixtures/external-plugin/button.js
new file mode 100644
index 0000000..a4ccdee
--- /dev/null
+++ b/__tests__/fixtures/external-plugin/button.js
@@ -0,0 +1,8 @@
+import { createVNode, defineComponent } from 'vue'
+
+export default defineComponent({
+ name: 'Button',
+ setup(_, { slots }) {
+ return () => createVNode('button', null, slots)
+ }
+})
diff --git a/__tests__/fixtures/external-plugin/main.js b/__tests__/fixtures/external-plugin/main.js
new file mode 100644
index 0000000..ac1bebf
--- /dev/null
+++ b/__tests__/fixtures/external-plugin/main.js
@@ -0,0 +1,11 @@
+import _Button from './button'
+
+function withInstall(component) {
+ component.install = (app) => {
+ app.component(component.name, component)
+ }
+}
+
+const Button = withInstall(_Button)
+
+export { Button }
diff --git a/__tests__/plugin.spec.ts b/__tests__/plugin.spec.ts
new file mode 100644
index 0000000..fbc78e3
--- /dev/null
+++ b/__tests__/plugin.spec.ts
@@ -0,0 +1,46 @@
+import path from 'path'
+import test from 'ava'
+import { build } from 'vite'
+import { cdn, external } from '../dist'
+
+const defaultWd = __dirname
+
+const fixturePath = path.join(defaultWd, 'fixtures')
+
+test('exteranl plugin', async (t) => {
+ const bundle = await build({
+ plugins: [external({ include: /\.(mjs|js|ts|vue|jsx|tsx)(\?.*|)$/, modules: [{ name: 'vue', global: 'Vue' }] })],
+ logLevel: 'silent',
+ build: {
+ lib: {
+ entry: path.join(fixturePath, 'external-plugin', 'main.js'),
+ formats: ['es']
+ },
+ write: false
+ }
+ })
+
+ const { code } = bundle[0].output[0]
+ const global = /Vue(.)\w+/g
+ const [s, s1] = code.match(global)
+ t.is(s, 'Vue.defineComponent')
+ t.is(s1, 'Vue.createVNode')
+})
+
+test('cdn plugin', async (t) => {
+ const bundle = await build({
+ plugins: [cdn({ modules: [{ name: 'vue' }] })],
+ logLevel: 'silent',
+ root: path.join(fixturePath, 'cdn-plugin'),
+ build: {
+ write: false
+ }
+ })
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignored
+ const { output } = bundle
+ const chunk = output[0]
+ const html = output[1]
+ t.is(/Vue/.test(chunk.code), true)
+ t.is(/https:\/\/cdn\.jsdelivr\.net\/npm\/vue/.test(html.source), true)
+})
diff --git a/package.json b/package.json
index 0b22c6a..699b140 100644
--- a/package.json
+++ b/package.json
@@ -59,6 +59,7 @@
},
"devDependencies": {
"@esbuild-kit/cjs-loader": "^2.4.2",
+ "@nolyfill/es-aggregate-error": "^1.0.20",
"@rollup/plugin-json": "^6.0.0",
"@types/babel__core": "^7.20.1",
"@types/debug": "^4.1.8",
@@ -74,8 +75,7 @@
"tsup": "^7.1.0",
"typescript": "^4.8.3",
"vite": "^3.1.3",
- "vue": "^3.3.4",
- "@nolyfill/es-aggregate-error": "^1.0.20"
+ "vue": "^3.3.4"
},
"dependencies": {
"@babel/core": "^7.22.5",
diff --git a/src/code-gen.ts b/src/code-gen.ts
index bced1a6..941fae5 100644
--- a/src/code-gen.ts
+++ b/src/code-gen.ts
@@ -17,7 +17,7 @@ export class CodeGen {
this.aliasesToDependencies = new Map()
this.dependencies.forEach(({ name, aliases }) => {
this.aliasesToDependencies.set(name, name)
- if (len(aliases)) {
+ if (Array.isArray(aliases) && len(aliases)) {
aliases.forEach((aliase) => this.aliasesToDependencies.set(aliase, name))
}
})
@@ -316,7 +316,6 @@ export async function tryScanGlobalName(code: string) {
const ast = await babelParse(code, { babelrc: false, configFile: false })
const { body } = ast.program
if (!len(body)) return
- // It's enough to extract only the first node
const node = body[0]
// iife only return the first
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
diff --git a/src/index.ts b/src/index.ts
index d569cba..7246835 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,7 +1,7 @@
import { createFilter } from '@rollup/pluginutils'
import type { Plugin } from 'vite'
import _debug from 'debug'
-import { createScanner, getPackageExports } from './scanner'
+import { createScanner, getPackageExports, serializationExportsFields } from './scanner'
import { createInjectScript } from './inject'
import { createCodeGenerator } from './code-gen'
import { isSupportThreads, transformCJSRequire } from './shared'
@@ -102,7 +102,7 @@ function external(opts: ExternalPluginOptions = {}): Plugin {
const defaultWd = process.cwd()
const dependencies = await Promise.all(modules.map(async (module) => {
const exports = await getPackageExports(module, defaultWd)
- return { bindings: exports, ...module }
+ return { bindings: exports, ...module, aliases: serializationExportsFields(module.name, module.aliases) }
})) as ModuleInfo[]
const deps = new Map(dependencies.map(dep => [dep.name, dep]))
debug('scanning done', deps)
@@ -131,4 +131,4 @@ export { cdn, external }
export default cdn
-export type { InjectVisitor, TrackModule, CDNPluginOptions, ExternalPluginOptions } from './interface'
+export type { InjectVisitor, TrackModule, CDNPluginOptions, ExternalPluginOptions, ExternalModule } from './interface'
diff --git a/src/interface.ts b/src/interface.ts
index de0cef5..77bb392 100644
--- a/src/interface.ts
+++ b/src/interface.ts
@@ -29,6 +29,10 @@ export interface IModule extends TrackModule {
resolve?: string | ResolverFunction
}
+export type ExternalModule = Required & {
+ aliases?: Array
+}
+
export interface Serialization {
url?: Set
type?: string
@@ -97,7 +101,7 @@ export type CDNPluginOptions = Pretty<{
}>
export type ExternalPluginOptions = Pretty<{
- modules?: Array>
+ modules?: Array
include?: FilterPattern
exclude?: FilterPattern
}>
diff --git a/src/scanner.ts b/src/scanner.ts
index 1efa44f..1547fb4 100644
--- a/src/scanner.ts
+++ b/src/scanner.ts
@@ -79,7 +79,7 @@ function createWorkerThreads(scannerModule: ScannerModule, defaultWd: string) {
}
-function serializationExportsFields(moduleName: string, aliases = []) {
+export function serializationExportsFields(moduleName: string, aliases = []) {
return aliases.filter(v => v !== '.').map(v => path.posix.join(moduleName, v))
}