From f52d8707d5d28982f7e58f76280a667f3f44d1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Mon, 13 Feb 2023 00:01:10 +0100 Subject: [PATCH] fix: enforce "pre" for builds with SWC plugins (fixes #56) --- CHANGELOG.md | 1 + .../__tests__/emotion-plugin.spec.ts | 61 +++++++++++++++++++ playground/emotion-plugin/index.html | 13 ++++ playground/emotion-plugin/package.json | 21 +++++++ playground/emotion-plugin/public/vite.svg | 1 + playground/emotion-plugin/src/App.css | 26 ++++++++ playground/emotion-plugin/src/App.jsx | 28 +++++++++ playground/emotion-plugin/src/Button.jsx | 30 +++++++++ playground/emotion-plugin/src/index.css | 24 ++++++++ playground/emotion-plugin/src/index.jsx | 10 +++ playground/emotion-plugin/vite.config.js | 11 ++++ pnpm-lock.yaml | 25 ++++++++ src/index.ts | 1 + 13 files changed, 252 insertions(+) create mode 100644 playground/emotion-plugin/__tests__/emotion-plugin.spec.ts create mode 100644 playground/emotion-plugin/index.html create mode 100644 playground/emotion-plugin/package.json create mode 100644 playground/emotion-plugin/public/vite.svg create mode 100644 playground/emotion-plugin/src/App.css create mode 100644 playground/emotion-plugin/src/App.jsx create mode 100644 playground/emotion-plugin/src/Button.jsx create mode 100644 playground/emotion-plugin/src/index.css create mode 100644 playground/emotion-plugin/src/index.jsx create mode 100644 playground/emotion-plugin/vite.config.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eac7e9..18f9ed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Support HMR for MDX (fixes #52) +- Fix: when using plugins, apply SWC before esbuild so that automatic runtime is respected for JSX (fixes #56) - Fix: use jsxImportSource in optimizeDeps ## 3.1.0 diff --git a/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts b/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts new file mode 100644 index 0000000..6034002 --- /dev/null +++ b/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts @@ -0,0 +1,61 @@ +import { expect, test } from "@playwright/test"; +import { + setupDevServer, + setupBuildAndPreview, + setupWaitForLogs, + expectColor, +} from "../../utils"; + +test("Emotion plugin build", async ({ page }) => { + const { testUrl, server } = await setupBuildAndPreview("emotion-plugin"); + await page.goto(testUrl); + + const button = page.locator("button"); + await button.hover(); + await expectColor(button, "color", "#646cff"); + + await button.click(); + await expect(button).toHaveText("count is 1"); + + const code = page.locator("code"); + await expectColor(code, "color", "#646cff"); + + await server.httpServer.close(); +}); + +test("Emotion plugin HMR", async ({ page }) => { + const { testUrl, server, editFile } = await setupDevServer("emotion-plugin"); + const waitForLogs = await setupWaitForLogs(page); + await page.goto(testUrl); + await waitForLogs("[vite] connected."); + + const button = page.locator("button"); + await button.hover(); + await expectColor(button, "color", "#646cff"); + + await button.click(); + await expect(button).toHaveText("count is 1"); + + const code = page.locator("code"); + await expectColor(code, "color", "#646cff"); + + editFile("src/Button.jsx", [ + "background-color: #d26ac2;", + "background-color: #646cff;", + ]); + await waitForLogs("[vite] hot updated: /src/Button.jsx"); + await expect(button).toHaveText("count is 1"); + await expectColor(button, "backgroundColor", "#646cff"); + + editFile("src/App.jsx", ['color="#646cff"', 'color="#d26ac2"']); + await waitForLogs("[vite] hot updated: /src/App.jsx"); + await expect(button).toHaveText("count is 1"); + await expectColor(button, "color", "#d26ac2"); + + editFile("src/Button.jsx", ["color: #646cff;", "color: #d26ac2;"]); + await waitForLogs("[vite] hot updated: /src/Button.jsx"); + await expect(button).toHaveText("count is 1"); + await expectColor(code, "color", "#d26ac2"); + + await server.close(); +}); diff --git a/playground/emotion-plugin/index.html b/playground/emotion-plugin/index.html new file mode 100644 index 0000000..ddf8b7b --- /dev/null +++ b/playground/emotion-plugin/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + Emotion + + +
+ + + diff --git a/playground/emotion-plugin/package.json b/playground/emotion-plugin/package.json new file mode 100644 index 0000000..06e3be9 --- /dev/null +++ b/playground/emotion-plugin/package.json @@ -0,0 +1,21 @@ +{ + "name": "playground-emotion", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.27", + "@types/react-dom": "^18.0.10", + "@vitejs/plugin-react-swc": "../../dist", + "@swc/plugin-emotion": "^2.5.41" + } +} diff --git a/playground/emotion-plugin/public/vite.svg b/playground/emotion-plugin/public/vite.svg new file mode 100644 index 0000000..4dcd77a --- /dev/null +++ b/playground/emotion-plugin/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/playground/emotion-plugin/src/App.css b/playground/emotion-plugin/src/App.css new file mode 100644 index 0000000..e9f861b --- /dev/null +++ b/playground/emotion-plugin/src/App.css @@ -0,0 +1,26 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.emotion:hover { + filter: drop-shadow(0 0 2em #d26ac2aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/playground/emotion-plugin/src/App.jsx b/playground/emotion-plugin/src/App.jsx new file mode 100644 index 0000000..8992acd --- /dev/null +++ b/playground/emotion-plugin/src/App.jsx @@ -0,0 +1,28 @@ +import "./App.css"; +import { Button, StyledCode } from "./Button"; + +export const App = () => ( +
+
+ + Vite logo + + + Emotion logo + +
+
+
+

+ Click on the Vite and Emotion logos to learn more +

+
+); diff --git a/playground/emotion-plugin/src/Button.jsx b/playground/emotion-plugin/src/Button.jsx new file mode 100644 index 0000000..e9b4720 --- /dev/null +++ b/playground/emotion-plugin/src/Button.jsx @@ -0,0 +1,30 @@ +import styled from "@emotion/styled"; +import { css } from "@emotion/react"; +import { useState } from "react"; + +// Ensure HMR of styled component alongside other components +export const StyledCode = styled.code` + color: #646cff; +`; + +export const Button = ({ color }) => { + const [count, setCount] = useState(0); + + return ( + + ); +}; diff --git a/playground/emotion-plugin/src/index.css b/playground/emotion-plugin/src/index.css new file mode 100644 index 0000000..8d79b24 --- /dev/null +++ b/playground/emotion-plugin/src/index.css @@ -0,0 +1,24 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} diff --git a/playground/emotion-plugin/src/index.jsx b/playground/emotion-plugin/src/index.jsx new file mode 100644 index 0000000..7181ef4 --- /dev/null +++ b/playground/emotion-plugin/src/index.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { App } from "./App"; +import "./index.css"; + +createRoot(document.getElementById("root")).render( + + + , +); diff --git a/playground/emotion-plugin/vite.config.js b/playground/emotion-plugin/vite.config.js new file mode 100644 index 0000000..6c9ad99 --- /dev/null +++ b/playground/emotion-plugin/vite.config.js @@ -0,0 +1,11 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; + +export default defineConfig({ + plugins: [ + react({ + jsxImportSource: "@emotion/react", + plugins: [["@swc/plugin-emotion", {}]], + }), + ], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71f2f10..acea29c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,27 @@ importers: '@types/react-dom': 18.0.10 '@vitejs/plugin-react-swc': link:../../dist + playground/emotion-plugin: + specifiers: + '@emotion/react': ^11.10.5 + '@emotion/styled': ^11.10.5 + '@swc/plugin-emotion': ^2.5.41 + '@types/react': ^18.0.27 + '@types/react-dom': ^18.0.10 + '@vitejs/plugin-react-swc': ../../dist + react: ^18.2.0 + react-dom: ^18.2.0 + dependencies: + '@emotion/react': 11.10.5_3stiutgnnbnfnf3uowm5cip22i + '@emotion/styled': 11.10.5_jrh5enlbqfbnumycmktdqgd6se + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + devDependencies: + '@swc/plugin-emotion': 2.5.41 + '@types/react': 18.0.27 + '@types/react-dom': 18.0.10 + '@vitejs/plugin-react-swc': link:../../dist + playground/hmr: specifiers: '@types/react': ^18.0.27 @@ -1052,6 +1073,10 @@ packages: '@swc/core-win32-x64-msvc': 1.3.35 dev: false + /@swc/plugin-emotion/2.5.41: + resolution: {integrity: sha512-1ejfFPMSUseIvbj1AugVKzSUAjREVti3Te00rogRTC0goFuQ4ORIn1YJejJjgW9uNg17t5heaZ4X72+G0BkQ4Q==} + dev: true + /@swc/plugin-styled-components/1.5.40: resolution: {integrity: sha512-T+/24m3idrV+Bk2kTBmW+qnWTwqOxMe+P6q4+2KPgO3mJtbhwuVhgAzo1yCpmjYej26VKjmCPtQk0uouvy/V6w==} dev: true diff --git a/src/index.ts b/src/index.ts index 674c3ce..bbd2984 100644 --- a/src/index.ts +++ b/src/index.ts @@ -121,6 +121,7 @@ import(/* @vite-ignore */ import.meta.url).then((currentExports) => { ? { name: "vite:react-swc", apply: "build", + enforce: "pre", // Run before esbuild transform: (code, _id) => transformWithOptions(_id.split("?")[0], code, options, { useBuiltins: true,