Skip to content

Commit

Permalink
Plugin Refactor to work better with Vite CSS pipeline (#64)
Browse files Browse the repository at this point in the history
* Prepare experimental version of the plugin

* New experimental plugin

* Don't call waitForRequestsIdle during SSR

* Update demos to use latest Vite and the @stylex stylesheet; rule

* Fix typechecking

* Upgrade storybook

* Tests

* Qwik fix tests

* Remove tests that don't make sense anymore

* Remove runtimeInjectionTests

* Changeset

* Enter prerelease mode and version packages

* Compile StyleX before Vite CSS plugin

* changeset

* Version

* Apply 5f9bd3e to experimental

* Rename to main

* Bump versions

* README update

* Exit prerelease

* Exit prerelease mode and version packages
  • Loading branch information
HorusGoul authored Jun 11, 2024
1 parent 8b3bad4 commit 63ff3d1
Show file tree
Hide file tree
Showing 39 changed files with 3,180 additions and 3,786 deletions.
48 changes: 40 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ pnpm add --save-dev vite-plugin-stylex

## Setup

For a basic SPA setup, you only need to add the plugin to your Vite config:
### Plugin configuration

Add the plugin to your Vite config:

```ts
// ... other imports
Expand All @@ -33,6 +35,24 @@ export default defineConfig({
});
```

### Including StyleX styles in your project

Create a CSS file in your project and add the following:

```css
/* stylex.css */
@stylex stylesheet;

/* You can use other styles here */
```

Finally, import the CSS file in your entrypoint:

```ts
// index.tsx or however your entrypoint is named
import "./stylex.css";
```

### Extra steps for frameworks or SSR

Other setups may require extra steps to get StyleX working. For example, Remix requires you to import the CSS output in your root component.
Expand Down Expand Up @@ -60,6 +80,18 @@ Other setups may require extra steps to get StyleX working. For example, Remix r
import "./index.css";
```

> [!NOTE]
> You might also want to import the CSS file using url import syntax in your `app/root.tsx` file, and then return it
> from the links array
>
> ```ts
> import stylexCSS from "./stylex.css?url";
>
> export const links = () => [{ rel: "stylesheet", href: stylexCSS }];
>
> ...
> ```
#### SvelteKit
Create a `+layout.svelte` file in your `src/routes` directory:
Expand Down Expand Up @@ -117,22 +149,22 @@ Open the `src/global.css` file and add the following:
Add an import source in your Vite config, like so:

```ts
import { defineConfig } from 'vite';
import styleX from 'vite-plugin-stylex';
import { defineConfig } from "vite";
import styleX from "vite-plugin-stylex";

export default defineConfig({
plugins: [
// ...other plugins
styleX({
importSources: [
{
from: 'react-strict-dom',
as: 'css',
from: "react-strict-dom",
as: "css",
},
],
})
]
})
}),
],
});
```

#### Other Frameworks
Expand Down
9 changes: 5 additions & 4 deletions apps/qwik-demo/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "qwik-demo",
"version": "0.0.0",
"description": "App with Routing built-in ready to create your app",
"engines": {
"node": ">=15.0.0"
Expand All @@ -24,17 +25,17 @@
"test": "tsx --test test/*.test.ts"
},
"devDependencies": {
"@builder.io/qwik": "^1.3.1",
"@builder.io/qwik-city": "^1.3.1",
"@builder.io/qwik": "^1.5.1",
"@builder.io/qwik-city": "^1.5.1",
"@types/node": "^20.10.3",
"typescript": "^5.3.2",
"undici": "^5.26.0",
"vite": "^5.0.6",
"vite": "^5.2.7",
"vite-tsconfig-paths": "^4.2.1"
},
"dependencies": {
"@internal/test-utils": "workspace:^",
"@stylexjs/stylex": "^0.5.1",
"@stylexjs/stylex": "^0.6.1",
"tsx": "^4.6.2",
"vite-plugin-stylex": "workspace:^"
}
Expand Down
15 changes: 2 additions & 13 deletions apps/qwik-demo/test/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,17 @@ describe("build output", () => {
let publicAssetsDir: string;

before(async () => {
publicAssetsDir = path.join(VITE_ROOT, "dist", "assets");
publicAssetsDir = path.join(VITE_ROOT, "dist", "build");

cp.spawnSync("pnpm", ["build"], {
cwd: VITE_ROOT,
env: process.env,
});
});

test("built assets should contain a stylex stylesheet", async () => {
const files = await fs.readdir(publicAssetsDir);
const stylexFile = files.some(
(file) => file.includes("stylex") && file.endsWith(".css")
);

assert.ok(stylexFile, "an stylex file should exist in the build output");
});

test("stylex stylesheet contains the expected styles", async () => {
const files = await fs.readdir(publicAssetsDir);
const stylexFile = files.find(
(file) => file.includes("stylex") && file.endsWith(".css")
);
const stylexFile = files.find((file) => file.endsWith(".css"));
const stylexCss = await fs.readFile(
path.join(publicAssetsDir, stylexFile!),
"utf-8"
Expand Down
4 changes: 2 additions & 2 deletions apps/react-strict-dom-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@stylexjs/open-props": "^0.3.0",
"@stylexjs/stylex": "^0.5.1",
"@stylexjs/stylex": "^0.6.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-strict-dom": "^0.0.3"
Expand All @@ -23,7 +23,7 @@
"@vitejs/plugin-react": "^4.2.0",
"tsx": "^4.6.2",
"typescript": "^5.2.2",
"vite": "^4.5.1",
"vite": "^5.2.7",
"vite-plugin-stylex": "workspace:*"
}
}
1 change: 1 addition & 0 deletions apps/react-strict-dom-demo/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@stylex stylesheet;
1 change: 1 addition & 0 deletions apps/react-strict-dom-demo/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
Expand Down
21 changes: 3 additions & 18 deletions apps/react-strict-dom-demo/test/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,31 +47,16 @@ describe("build output", () => {
test("built assets should contain a stylex stylesheet", async () => {
const files = await fs.readdir(path.join(tempDir, "assets"));
const stylexFile = files.some(
(file) => file.includes("stylex") && file.endsWith(".css")
(file) => file.includes("index") && file.endsWith(".css")
);

assert.ok(stylexFile, "an stylex file should exist in the build output");
});

test("index.html contains a link to the stylex stylesheet", async () => {
const indexHtml = await fs.readFile(
path.join(tempDir, "index.html"),
"utf-8"
);
const stylexLink = indexHtml.includes(
`<link rel="stylesheet" href="/assets/stylex.`
);

assert.ok(
stylexLink,
"index.html should contain a link to the stylex stylesheet"
);
});

test("stylex stylesheet contains the expected styles", async () => {
const files = await fs.readdir(path.join(tempDir, "assets"));
const stylexFile = files.find(
(file) => file.includes("stylex") && file.endsWith(".css")
(file) => file.includes("index") && file.endsWith(".css")
);
const stylexCss = await fs.readFile(
path.join(tempDir, "assets", stylexFile),
Expand All @@ -88,7 +73,7 @@ describe("build output", () => {
test("stylex stylesheet contains styles from @stylexjs/open-props package", async () => {
const files = await fs.readdir(path.join(tempDir, "assets"));
const stylexFile = files.find(
(file) => file.includes("stylex") && file.endsWith(".css")
(file) => file.includes("index") && file.endsWith(".css")
);
const stylexCss = await fs.readFile(
path.join(tempDir, "assets", stylexFile),
Expand Down
9 changes: 0 additions & 9 deletions apps/react-strict-dom-demo/test/dev.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { describe, test, beforeEach, afterEach } from "node:test";
import * as vite from "vite";
import path from "path";
import {
Browser,
openBrowser,
closeBrowser,
runtimeInjectionTest,
hmrTest,
cleanHmrTest,
friendlyClassNameTest,
Expand Down Expand Up @@ -45,13 +43,6 @@ describe("dev", () => {
await closeBrowser(browser);
});

test("runtime injection works", async () => {
const page = await browser.newPage();
await page.goto(serverUrl);

await runtimeInjectionTest(page);
});

test("friendly classnames work", async () => {
const page = await browser.newPage();
await page.goto(serverUrl);
Expand Down
5 changes: 3 additions & 2 deletions apps/remix-css-url-demo/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "remix-css-url-demo",
"version": "0.0.0",
"private": true,
"sideEffects": false,
"type": "module",
Expand All @@ -15,7 +16,7 @@
"@remix-run/react": "^2.8.1",
"@remix-run/serve": "^2.8.1",
"@stylexjs/open-props": "^0.3.0",
"@stylexjs/stylex": "^0.5.1",
"@stylexjs/stylex": "^0.6.1",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand All @@ -29,7 +30,7 @@
"eslint": "^8.38.0",
"tsx": "^4.6.2",
"typescript": "^5.1.6",
"vite": "^5.1.6",
"vite": "^5.2.7",
"vite-plugin-stylex": "workspace:*",
"vite-tsconfig-paths": "^4.3.2"
},
Expand Down
27 changes: 0 additions & 27 deletions apps/remix-css-url-demo/test/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,33 +118,6 @@ describe("build output", () => {
assert.ok(!stylexFile, "stylex file should not be in the build output");
});

test("stylex file should not be in the server build output", async () => {
const files = await fs
.readdir(path.join(tempDir, "build", "server", "assets"))
// Catching if the directory doesn't exist
.catch(() => []);
const stylexFile = files.some(
(file) => file.includes("stylex.") && file.endsWith(".css")
);

assert.ok(!stylexFile, "stylex file should not be in the build output");
});

test("server-build-HASH.css file should not be in the server build output", async () => {
const files = await fs
.readdir(path.join(tempDir, "build", "server", "assets"))
// Catching if the directory doesn't exist
.catch(() => []);
const stylexFile = files.some(
(file) => file.includes("server-build-") && file.endsWith(".css")
);

assert.ok(
!stylexFile,
"server-build-HASH.css file should not be in the build output"
);
});

describe("remix serve", () => {
let child: cp.ChildProcessWithoutNullStreams;
let address: string;
Expand Down
4 changes: 2 additions & 2 deletions apps/remix-css-url-demo/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { Plugin, defineConfig } from "vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import styleX from "vite-plugin-stylex";

Expand All @@ -15,6 +15,6 @@ export default defineConfig({
serverBuildFile: "index.mjs",
}),
tsconfigPaths(),
styleX() as Plugin,
styleX(),
],
});
3 changes: 2 additions & 1 deletion apps/remix-demo/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "remix-demo",
"version": "0.0.0",
"private": true,
"sideEffects": false,
"type": "module",
Expand All @@ -15,7 +16,7 @@
"@remix-run/react": "^2.8.1",
"@remix-run/serve": "^2.8.1",
"@stylexjs/open-props": "^0.3.0",
"@stylexjs/stylex": "^0.5.1",
"@stylexjs/stylex": "^0.6.1",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
36 changes: 0 additions & 36 deletions apps/remix-demo/test/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,42 +109,6 @@ describe("build output", () => {
);
});

test("stylex file should not be in the public build output", async () => {
const files = await fs.readdir(publicAssetsDir);
const stylexFile = files.some(
(file) => file.includes("stylex.") && file.endsWith(".css")
);

assert.ok(!stylexFile, "stylex file should not be in the build output");
});

test("stylex file should not be in the server build output", async () => {
const files = await fs
.readdir(path.join(tempDir, "build", "server", "assets"))
// Catching if the directory doesn't exist
.catch(() => []);
const stylexFile = files.some(
(file) => file.includes("stylex.") && file.endsWith(".css")
);

assert.ok(!stylexFile, "stylex file should not be in the build output");
});

test("server-build-HASH.css file should not be in the server build output", async () => {
const files = await fs
.readdir(path.join(tempDir, "build", "server", "assets"))
// Catching if the directory doesn't exist
.catch(() => []);
const stylexFile = files.some(
(file) => file.includes("server-build-") && file.endsWith(".css")
);

assert.ok(
!stylexFile,
"server-build-HASH.css file should not be in the build output"
);
});

describe("remix serve", () => {
let child: cp.ChildProcessWithoutNullStreams;
let address: string;
Expand Down
2 changes: 1 addition & 1 deletion apps/remix-demo/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default defineConfig({
serverBuildFile: "index.mjs",
}),
tsconfigPaths(),
styleX() as Plugin,
styleX(),
],
css: {
transformer: "lightningcss",
Expand Down
1 change: 1 addition & 0 deletions apps/storybook-demo/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Preview } from "@storybook/react";
import "../src/index.css";

const preview: Preview = {
parameters: {
Expand Down
Loading

0 comments on commit 63ff3d1

Please sign in to comment.