diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d6c346..5720567a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Add swcImplementation option + +Pass a custom SWC implementation. This can be used to keep a stable version of SWC instead of using package manager overrides, at the cost of installing it twice. + ## 3.6.0 ### Add parserConfig option diff --git a/README.md b/README.md index 8fd6191a..2e191853 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,10 @@ react({ }); ``` +### swcImplementation + +Advanced. Pass a custom SWC implementation. This can be used to keep a stable version of SWC instead of using package manager overrides, at the cost of installing it twice. + ## Consistent components exports For React refresh to work correctly, your file should only export React components. The best explanation I've read is the one from the [Gatsby docs](https://www.gatsbyjs.com/docs/reference/local-development/fast-refresh/#how-it-works). diff --git a/src/index.ts b/src/index.ts index 4eaa8b26..85f1d82b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,10 +3,10 @@ import { dirname, join } from "path"; import { fileURLToPath } from "url"; import { SourceMapPayload } from "module"; import { - Output, - ParserConfig, - ReactConfig, - JscTarget, + type Output, + type ParserConfig, + type ReactConfig, + type JscTarget, transform, } from "@swc/core"; import { PluginOption, UserConfig, BuildOptions } from "vite"; @@ -58,6 +58,12 @@ type Options = { * Exclusion of node_modules should be handled by the function if needed. */ parserConfig?: (id: string) => ParserConfig | undefined; + /** + * Advanced. Pass a custom SWC implementation. + * This can be used to keep a stable version of SWC instead of using + * package manager overrides, at the cost of installing it twice. + */ + swcImplementation?: any; }; const isWebContainer = globalThis.process?.versions?.webcontainer; @@ -72,6 +78,10 @@ const react = (_options?: Options): PluginOption[] => { : undefined, devTarget: _options?.devTarget ?? "es2020", parserConfig: _options?.parserConfig, + transformFn: + (_options?.swcImplementation?.transform as + | typeof transform + | undefined) ?? transform, }; return [ @@ -130,6 +140,7 @@ const react = (_options?: Options): PluginOption[] => { const refresh = !transformOptions?.ssr && !hmrDisabled; const result = await transformWithOptions( + options.transformFn, id, code, options.devTarget, @@ -192,10 +203,17 @@ RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => { build: silenceUseClientWarning(userConfig), }), transform: (code, _id) => - transformWithOptions(_id.split("?")[0], code, "esnext", options, { - runtime: "automatic", - importSource: options.jsxImportSource, - }), + transformWithOptions( + options.transformFn, + _id.split("?")[0], + code, + "esnext", + options, + { + runtime: "automatic", + importSource: options.jsxImportSource, + }, + ), } : { name: "vite:react-swc", @@ -215,6 +233,7 @@ RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => { }; const transformWithOptions = async ( + transformFn: typeof transform, id: string, code: string, target: JscTarget, @@ -238,7 +257,7 @@ const transformWithOptions = async ( let result: Output; try { - result = await transform(code, { + result = await transformFn(code, { filename: id, swcrc: false, configFile: false,