diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 3091de5ed980ad..25b752d7512df6 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -438,21 +438,26 @@ async function doBuild( try { const buildOutputOptions = (output: OutputOptions = {}): OutputOptions => { const cjsSsrBuild = ssr && config.ssr?.format === 'cjs' + const format = output.format || (cjsSsrBuild ? 'cjs' : 'es') + const jsExt = + (ssr && config.ssr?.target !== 'webworker') || libOptions + ? resolveOutputJsExtension(format, getPkgJson(config.root)?.type) + : 'js' return { dir: outDir, // Default format is 'es' for regular and for SSR builds - format: cjsSsrBuild ? 'cjs' : 'es', + format, exports: cjsSsrBuild ? 'named' : 'auto', sourcemap: options.sourcemap, name: libOptions ? libOptions.name : undefined, generatedCode: 'es2015', entryFileNames: ssr - ? `[name].js` + ? `[name].${jsExt}` : libOptions - ? resolveLibFilename(libOptions, output.format || 'es', config.root) + ? resolveLibFilename(libOptions, format, config.root, jsExt) : path.posix.join(options.assetsDir, `[name].[hash].js`), chunkFileNames: libOptions - ? `[name].[hash].js` + ? `[name].[hash].${jsExt}` : path.posix.join(options.assetsDir, `[name].[hash].js`), assetFileNames: libOptions ? `[name].[ext]` @@ -591,10 +596,24 @@ function getPkgName(name: string) { return name?.startsWith('@') ? name.split('/')[1] : name } +type JsExt = 'js' | 'cjs' | 'mjs' + +function resolveOutputJsExtension( + format: ModuleFormat, + type: string = 'commonjs' +): JsExt { + if (type === 'module') { + return format === 'cjs' || format === 'umd' ? 'cjs' : 'js' + } else { + return format === 'es' ? 'mjs' : 'js' + } +} + export function resolveLibFilename( libOptions: LibraryOptions, format: ModuleFormat, - root: string + root: string, + extension?: JsExt ): string { if (typeof libOptions.fileName === 'function') { return libOptions.fileName(format) @@ -608,13 +627,7 @@ export function resolveLibFilename( 'Name in package.json is required if option "build.lib.fileName" is not provided.' ) - let extension: string - - if (packageJson?.type === 'module') { - extension = format === 'cjs' || format === 'umd' ? 'cjs' : 'js' - } else { - extension = format === 'es' ? 'mjs' : 'js' - } + extension ??= resolveOutputJsExtension(format, packageJson.type) if (format === 'cjs' || format === 'es') { return `${name}.${extension}` diff --git a/playground/legacy/__tests__/ssr/serve.ts b/playground/legacy/__tests__/ssr/serve.ts index 339b95e690b83a..81669a4891b8ef 100644 --- a/playground/legacy/__tests__/ssr/serve.ts +++ b/playground/legacy/__tests__/ssr/serve.ts @@ -22,7 +22,7 @@ export async function serve(): Promise<{ close(): Promise }> { app.use('/', async (_req, res) => { const { render } = await import( - path.resolve(rootDir, './dist/server/entry-server.js') + path.resolve(rootDir, './dist/server/entry-server.mjs') ) const html = await render() res.status(200).set({ 'Content-Type': 'text/html' }).end(html) diff --git a/playground/lib/__tests__/lib.spec.ts b/playground/lib/__tests__/lib.spec.ts index f8eea2b41847b8..32c6edba1bdeb9 100644 --- a/playground/lib/__tests__/lib.spec.ts +++ b/playground/lib/__tests__/lib.spec.ts @@ -40,13 +40,13 @@ describe.runIf(isBuild)('build', () => { 'hello vite' ) const code = fs.readFileSync( - path.join(testDir, 'dist/lib/dynamic-import-message.es.js'), + path.join(testDir, 'dist/lib/dynamic-import-message.es.mjs'), 'utf-8' ) expect(code).not.toMatch('__vitePreload') // Test that library chunks are hashed - expect(code).toMatch(/await import\("\.\/message.[a-z\d]{8}.js"\)/) + expect(code).toMatch(/await import\("\.\/message.[a-z\d]{8}.mjs"\)/) }) test('@import hoist', async () => { diff --git a/playground/lib/vite.dyimport.config.js b/playground/lib/vite.dyimport.config.js index 1f64018c5850cf..54a84dbe76c24a 100644 --- a/playground/lib/vite.dyimport.config.js +++ b/playground/lib/vite.dyimport.config.js @@ -10,7 +10,7 @@ module.exports = { entry: path.resolve(__dirname, 'src/main2.js'), formats: ['es', 'iife'], name: 'message', - fileName: (format) => `dynamic-import-message.${format}.js` + fileName: (format) => `dynamic-import-message.${format}.mjs` }, outDir: 'dist/lib' }