diff --git a/.changeset/brown-pillows-write.md b/.changeset/brown-pillows-write.md new file mode 100644 index 000000000..424f21f45 --- /dev/null +++ b/.changeset/brown-pillows-write.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Fix `ERR_UNSUPPORTED_ESM_URL_SCHEME` errors when bundling on Windows diff --git a/packages/repack/src/commands/common/config/getMinimizerConfig.ts b/packages/repack/src/commands/common/config/getMinimizerConfig.ts index 2dfa8eb79..3b7d0e5c5 100644 --- a/packages/repack/src/commands/common/config/getMinimizerConfig.ts +++ b/packages/repack/src/commands/common/config/getMinimizerConfig.ts @@ -1,4 +1,6 @@ import semver from 'semver'; +import type TerserPlugin from 'terser-webpack-plugin'; +import { importDefaultESM } from '../../../helpers/index.js'; // prefer `terser-webpack-plugin` installed in the project root to the one shipped with Re.Pack async function getTerserPlugin(rootDir: string) { @@ -10,8 +12,8 @@ async function getTerserPlugin(rootDir: string) { } catch { terserPluginPath = require.resolve('terser-webpack-plugin'); } - const plugin = await import(terserPluginPath); - return 'default' in plugin ? plugin.default : plugin; + const plugin = await importDefaultESM(terserPluginPath); + return plugin; } async function getTerserConfig(rootDir: string) { diff --git a/packages/repack/src/commands/common/getDevMiddleware.ts b/packages/repack/src/commands/common/getDevMiddleware.ts index 52237116c..6755d98fc 100644 --- a/packages/repack/src/commands/common/getDevMiddleware.ts +++ b/packages/repack/src/commands/common/getDevMiddleware.ts @@ -1,3 +1,5 @@ +import url from 'node:url'; + export async function getDevMiddleware(reactNativePath: string) { const reactNativeCommunityCliPluginPath = require.resolve( '@react-native/community-cli-plugin', @@ -8,5 +10,7 @@ export async function getDevMiddleware(reactNativePath: string) { paths: [reactNativeCommunityCliPluginPath], }); - return import(devMiddlewarePath); + // use fileURL to import correctly on both Windows & MacOS + const { href: fileUrl } = url.pathToFileURL(devMiddlewarePath); + return await import(fileUrl); } diff --git a/packages/repack/src/helpers/helpers.ts b/packages/repack/src/helpers/helpers.ts index 1cccb6e62..d508f30ec 100644 --- a/packages/repack/src/helpers/helpers.ts +++ b/packages/repack/src/helpers/helpers.ts @@ -1,4 +1,5 @@ import os from 'node:os'; +import url from 'node:url'; import type { Compiler as RspackCompiler } from '@rspack/core'; import type { Compiler as WebpackCompiler } from 'webpack'; @@ -60,3 +61,9 @@ export function moveElementBefore( // Insert source element right before the target element array.splice(targetIndex, 0, moveElement); } + +export async function importDefaultESM(absolutePath: string): Promise { + const { href: fileUrl } = url.pathToFileURL(absolutePath); + const module = await import(fileUrl); + return 'default' in module ? module.default : module; +} diff --git a/packages/repack/src/loaders/babelLoader/utils.ts b/packages/repack/src/loaders/babelLoader/utils.ts index 5b448d3cd..670897a32 100644 --- a/packages/repack/src/loaders/babelLoader/utils.ts +++ b/packages/repack/src/loaders/babelLoader/utils.ts @@ -1,4 +1,5 @@ import type { ParseResult } from '@babel/core'; +import { importDefaultESM } from '../../helpers/index.js'; interface HermesParser { parse: ( @@ -46,7 +47,7 @@ export async function loadHermesParser( const hermesParserPath = providedHermesParserPath ?? resolveHermesParser(projectRoot ?? process.cwd()); - const hermesParser = await import(hermesParserPath); + const hermesParser = await importDefaultESM(hermesParserPath); return hermesParser; } catch (e) { console.error(e); diff --git a/packages/repack/src/loaders/babelSwcLoader/utils.ts b/packages/repack/src/loaders/babelSwcLoader/utils.ts index 44c33c3d8..10e19ba26 100644 --- a/packages/repack/src/loaders/babelSwcLoader/utils.ts +++ b/packages/repack/src/loaders/babelSwcLoader/utils.ts @@ -4,6 +4,8 @@ import type { SwcLoaderParserConfig, experiments, } from '@rspack/core'; +import type Rspack from '@rspack/core'; +import { importDefaultESM } from '../../helpers/index.js'; type Swc = (typeof experiments)['swc']; type Logger = ReturnType; @@ -136,26 +138,16 @@ async function getSwcModule(loaderContext: LoaderContext): Promise { // use optional chaining to avoid type errors when there is no experiments.swc const rspackCorePath = safelyResolve('@rspack/core', projectRoot); if (rspackCorePath && !isWebpack) { - const rspack = await import(rspackCorePath); - if ('default' in rspack) { - return rspack.default?.experiments?.swc ?? null; - } - if (rspack) { - return rspack?.experiments?.swc ?? null; - } + const rspack = await importDefaultESM(rspackCorePath); + return rspack.experiments?.swc ?? null; } } // fallback to checking for `@swc/core` installed in the project // this can be in both webpack & rspack projects const swcCorePath = safelyResolve('@swc/core', projectRoot); if (swcCorePath) { - const swc = await import(swcCorePath); - if ('default' in swc) { - return swc.default as Swc; - } - if (swc) { - return swc as Swc; - } + const swc = await importDefaultESM(swcCorePath); + return swc; } // at this point, we've tried all possible ways to get swc and failed return null;