diff --git a/docs/config/ssr-options.md b/docs/config/ssr-options.md index 83f90b02c92a37..0b06ac673a209d 100644 --- a/docs/config/ssr-options.md +++ b/docs/config/ssr-options.md @@ -32,3 +32,9 @@ Build target for the SSR server. - **Experimental** Build format for the SSR server. Since Vite v3 the SSR build generates ESM by default. `'cjs'` can be selected to generate a CJS build, but it isn't recommended. The option is left marked as experimental to give users more time to update to ESM. CJS builds requires complex externalization heuristics that aren't present in the ESM format. + +## ssr.fileExtension + +- **Type:** `'js' | 'cjs' | 'mjs'` + +File extension of generated bundles. When not specified, it will infer from root package.json's "type" field. diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 705465400ca5ca..9f22e54d9d5b61 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -21,7 +21,7 @@ import commonjsPlugin from '@rollup/plugin-commonjs' import type { RollupCommonJSOptions } from 'types/commonjs' import type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' import type { TransformOptions } from 'esbuild' -import type { InlineConfig, ResolvedConfig } from './config' +import type { InlineConfig, JsExt, ResolvedConfig } from './config' import { isDepsOptimizerEnabled, resolveConfig } from './config' import { buildReporterPlugin } from './plugins/reporter' import { buildEsbuildPlugin } from './plugins/esbuild' @@ -451,8 +451,10 @@ async function doBuild( const format = output.format || (cjsSsrBuild ? 'cjs' : 'es') const jsExt = (ssr && config.ssr?.target !== 'webworker') || libOptions - ? resolveOutputJsExtension(format, getPkgJson(config.root)?.type) + ? config.ssr?.fileExtension || + resolveOutputJsExtension(format, getPkgJson(config.root)?.type) : 'js' + return { dir: outDir, // Default format is 'es' for regular and for SSR builds @@ -606,8 +608,6 @@ function getPkgName(name: string) { return name?.startsWith('@') ? name.split('/')[1] : name } -type JsExt = 'js' | 'cjs' | 'mjs' - function resolveOutputJsExtension( format: ModuleFormat, type: string = 'commonjs' diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index a9e6ba33f1d0ba..72e51142d14bcb 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -230,6 +230,8 @@ export interface ExperimentalOptions { importGlobRestoreExtension?: boolean } +export type JsExt = 'js' | 'cjs' | 'mjs' + export interface ResolveWorkerOptions { format: 'es' | 'iife' plugins: Plugin[] diff --git a/packages/vite/src/node/ssr/index.ts b/packages/vite/src/node/ssr/index.ts index 84f050ff8e41d4..3583b43d730938 100644 --- a/packages/vite/src/node/ssr/index.ts +++ b/packages/vite/src/node/ssr/index.ts @@ -1,3 +1,5 @@ +import type { JsExt } from '..' + export type SSRTarget = 'node' | 'webworker' export type SSRFormat = 'esm' | 'cjs' @@ -7,7 +9,7 @@ export interface SSROptions { /** * Define the target for the ssr build. The browser field in package.json * is ignored for node but used if webworker is the target - * Default: 'node' + * @default 'node' */ target?: SSRTarget /** @@ -18,6 +20,11 @@ export interface SSROptions { * @experimental */ format?: SSRFormat + /** + * File extension of generated bundles + * Will infer from root package.json's "type" field if not specified + */ + fileExtension?: JsExt } export interface ResolvedSSROptions extends SSROptions {