diff --git a/integration/svg-in-node-modules-test.ts b/integration/svg-in-node-modules-test.ts new file mode 100644 index 00000000000..96e604c02b8 --- /dev/null +++ b/integration/svg-in-node-modules-test.ts @@ -0,0 +1,48 @@ +import { test, expect } from "@playwright/test"; + +import { PlaywrightFixture } from "./helpers/playwright-fixture"; +import type { Fixture, AppFixture } from "./helpers/create-fixture"; +import { createAppFixture, createFixture, js } from "./helpers/create-fixture"; + +let fixture: Fixture; +let appFixture: AppFixture; + +test.beforeEach(async ({ context }) => { + await context.route(/_data/, async (route) => { + await new Promise((resolve) => setTimeout(resolve, 50)); + route.continue(); + }); +}); + +test.beforeAll(async () => { + fixture = await createFixture({ + files: { + "app/routes/_index.tsx": js` + import imgSrc from "getos/imgs/logo.svg"; + + export default function () { + return ( +
+ example img +
+ ) + } + `, + }, + }); + + appFixture = await createAppFixture(fixture); +}); + +test.afterAll(() => { + appFixture.close(); +}); + +test("renders SVG images imported from node_modules", async ({ page }) => { + let app = new PlaywrightFixture(appFixture, page); + // You can test any request your app might get using `fixture`. + await app.goto("/"); + expect(await page.getByTestId("example-svg").getAttribute("src")).toMatch( + /\/build\/_assets\/logo-.*\.svg/ + ); +}); diff --git a/packages/remix-dev/compiler/server/plugins/bareImports.ts b/packages/remix-dev/compiler/server/plugins/bareImports.ts index cbe99bab0f0..a4e1851248a 100644 --- a/packages/remix-dev/compiler/server/plugins/bareImports.ts +++ b/packages/remix-dev/compiler/server/plugins/bareImports.ts @@ -10,6 +10,7 @@ import { isCssSideEffectImportPath } from "../../plugins/cssSideEffectImports"; import { createMatchPath } from "../../utils/tsconfig"; import { detectPackageManager } from "../../../cli/detectPackageManager"; import type { Context } from "../../context"; +import { getLoaderForFile } from "../../utils/loaders"; /** * A plugin responsible for resolving bare module ids based on server target. @@ -59,8 +60,23 @@ export function serverBareModulesPlugin(ctx: Context): Plugin { return undefined; } - // Always bundle CSS files so we get immutable fingerprinted asset URLs. - if (path.endsWith(".css")) { + // Skip assets that are treated as files (.css, .svg, .png, etc.). + // Otherwise, esbuild would emit code that would attempt to require() + // or import these files --- which aren't JavaScript! + let loader; + try { + loader = getLoaderForFile(path); + } catch (e) { + if ( + !( + e instanceof Error && + e.message.startsWith("Cannot get loader for file") + ) + ) { + throw e; + } + } + if (loader === "file") { return undefined; }