Skip to content

Commit b8aa825

Browse files
authoredNov 8, 2022
fix: throw missing name error only when 'umd' or 'iife' are used (#9886)
1 parent 0c295e0 commit b8aa825

File tree

2 files changed

+129
-24
lines changed

2 files changed

+129
-24
lines changed
 

‎packages/vite/src/node/__tests__/build.spec.ts

+98-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { resolve } from 'node:path'
22
import { fileURLToPath } from 'node:url'
33
import type { Logger } from 'vite'
4-
import { describe, expect, test } from 'vitest'
4+
import { describe, expect, test, vi } from 'vitest'
5+
import type { OutputOptions } from 'rollup'
56
import type { LibraryFormats, LibraryOptions } from '../build'
67
import { resolveBuildOutputs, resolveLibFilename } from '../build'
8+
import { createLogger } from '../logger'
79

810
const __dirname = resolve(fileURLToPath(import.meta.url), '..')
911

@@ -13,6 +15,101 @@ const baseLibOptions: LibraryOptions = {
1315
entry: 'mylib.js'
1416
}
1517

18+
describe('resolveBuildOutputs', () => {
19+
test('resolves outputs correctly', () => {
20+
const logger = createLogger()
21+
const libOptions: LibraryOptions = { ...baseLibOptions }
22+
const outputs: OutputOptions[] = [{ format: 'es' }]
23+
const resolvedOutputs = resolveBuildOutputs(outputs, libOptions, logger)
24+
25+
expect(resolvedOutputs).toEqual([
26+
{
27+
format: 'es'
28+
}
29+
])
30+
})
31+
32+
test('resolves outputs from lib options', () => {
33+
const logger = createLogger()
34+
const libOptions: LibraryOptions = { ...baseLibOptions, name: 'lib' }
35+
const resolvedOutputs = resolveBuildOutputs(void 0, libOptions, logger)
36+
37+
expect(resolvedOutputs).toEqual([
38+
{
39+
format: 'es'
40+
},
41+
{
42+
format: 'umd'
43+
}
44+
])
45+
})
46+
47+
test('does not change outputs when lib options are missing', () => {
48+
const logger = createLogger()
49+
const outputs: OutputOptions[] = [{ format: 'es' }]
50+
const resolvedOutputs = resolveBuildOutputs(outputs, false, logger)
51+
52+
expect(resolvedOutputs).toEqual(outputs)
53+
})
54+
55+
test('logs a warning when outputs is an array and formats are specified', () => {
56+
const logger = createLogger()
57+
const loggerSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {})
58+
const libOptions: LibraryOptions = {
59+
...baseLibOptions,
60+
formats: ['iife']
61+
}
62+
const outputs: OutputOptions[] = [{ format: 'es' }]
63+
64+
resolveBuildOutputs(outputs, libOptions, logger)
65+
66+
expect(loggerSpy).toHaveBeenCalledWith(
67+
expect.stringContaining('"build.lib.formats" will be ignored because')
68+
)
69+
})
70+
71+
test('throws an error when lib.name is missing on iife format', () => {
72+
const logger = createLogger()
73+
const libOptions: LibraryOptions = {
74+
...baseLibOptions,
75+
formats: ['iife']
76+
}
77+
const resolveBuild = () => resolveBuildOutputs(void 0, libOptions, logger)
78+
79+
expect(resolveBuild).toThrowError(/Option "build\.lib\.name" is required/)
80+
})
81+
82+
test('throws an error when lib.name is missing on umd format', () => {
83+
const logger = createLogger()
84+
const libOptions: LibraryOptions = { ...baseLibOptions, formats: ['umd'] }
85+
const resolveBuild = () => resolveBuildOutputs(void 0, libOptions, logger)
86+
87+
expect(resolveBuild).toThrowError(/Option "build\.lib\.name" is required/)
88+
})
89+
90+
test('throws an error when output.name is missing on iife format', () => {
91+
const logger = createLogger()
92+
const libOptions: LibraryOptions = { ...baseLibOptions }
93+
const outputs: OutputOptions[] = [{ format: 'iife' }]
94+
const resolveBuild = () => resolveBuildOutputs(outputs, libOptions, logger)
95+
96+
expect(resolveBuild).toThrowError(
97+
/Entries in "build\.rollupOptions\.output" must specify "name"/
98+
)
99+
})
100+
101+
test('throws an error when output.name is missing on umd format', () => {
102+
const logger = createLogger()
103+
const libOptions: LibraryOptions = { ...baseLibOptions }
104+
const outputs: OutputOptions[] = [{ format: 'umd' }]
105+
const resolveBuild = () => resolveBuildOutputs(outputs, libOptions, logger)
106+
107+
expect(resolveBuild).toThrowError(
108+
/Entries in "build\.rollupOptions\.output" must specify "name"/
109+
)
110+
})
111+
})
112+
16113
describe('resolveLibFilename', () => {
17114
test('custom filename function', () => {
18115
const filename = resolveLibFilename(

‎packages/vite/src/node/build.ts

+31-23
Original file line numberDiff line numberDiff line change
@@ -783,41 +783,49 @@ export function resolveBuildOutputs(
783783
logger: Logger
784784
): OutputOptions | OutputOptions[] | undefined {
785785
if (libOptions) {
786-
const hasMultipleEntries =
786+
const libHasMultipleEntries =
787787
typeof libOptions.entry !== 'string' &&
788788
Object.values(libOptions.entry).length > 1
789+
const libFormats =
790+
libOptions.formats ||
791+
(libHasMultipleEntries ? ['es', 'cjs'] : ['es', 'umd'])
792+
793+
if (!Array.isArray(outputs)) {
794+
if (libFormats.includes('umd') || libFormats.includes('iife')) {
795+
if (libHasMultipleEntries) {
796+
throw new Error(
797+
'Multiple entry points are not supported when output formats include "umd" or "iife".'
798+
)
799+
}
789800

790-
const formats =
791-
libOptions.formats || (hasMultipleEntries ? ['es', 'cjs'] : ['es', 'umd'])
792-
793-
if (formats.includes('umd') || formats.includes('iife')) {
794-
if (hasMultipleEntries) {
795-
throw new Error(
796-
`Multiple entry points are not supported when output formats include "umd" or "iife".`
797-
)
801+
if (!libOptions.name) {
802+
throw new Error(
803+
'Option "build.lib.name" is required when output formats include "umd" or "iife".'
804+
)
805+
}
798806
}
799807

800-
if (!libOptions.name) {
801-
throw new Error(
802-
`Option "build.lib.name" is required when output formats ` +
803-
`include "umd" or "iife".`
804-
)
805-
}
808+
return libFormats.map((format) => ({ ...outputs, format }))
806809
}
807-
if (!outputs) {
808-
return formats.map((format) => ({ format }))
809-
} else if (!Array.isArray(outputs)) {
810-
return formats.map((format) => ({ ...outputs, format }))
811-
} else if (libOptions.formats) {
812-
// user explicitly specifying own output array
810+
811+
// By this point, we know "outputs" is an Array.
812+
if (libOptions.formats) {
813813
logger.warn(
814814
colors.yellow(
815-
`"build.lib.formats" will be ignored because ` +
816-
`"build.rollupOptions.output" is already an array format`
815+
'"build.lib.formats" will be ignored because "build.rollupOptions.output" is already an array format.'
817816
)
818817
)
819818
}
819+
820+
outputs.forEach((output) => {
821+
if (['umd', 'iife'].includes(output.format!) && !output.name) {
822+
throw new Error(
823+
'Entries in "build.rollupOptions.output" must specify "name" when the format is "umd" or "iife".'
824+
)
825+
}
826+
})
820827
}
828+
821829
return outputs
822830
}
823831

0 commit comments

Comments
 (0)
Please sign in to comment.