@stylexswc/nextjs-plugin 0.17.0-rc.3 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,7 +43,7 @@ npm install --save-dev @stylexswc/nextjs-plugin
43
43
 
44
44
  ## Usage
45
45
 
46
- This plugin supports both Webpack and Turbopack configurations in Next.js.
46
+ This plugin supports Webpack, Rspack, and Turbopack configurations in Next.js.
47
47
 
48
48
  ### Using with Webpack
49
49
 
@@ -59,6 +59,36 @@ module.exports = stylexPlugin({
59
59
  });
60
60
  ```
61
61
 
62
+ ### Using with Rspack
63
+
64
+ For Next.js with [Rspack](https://rspack.rs), use the `/rspack` export. It applies the
65
+ experimental [`next-rspack`](https://www.npmjs.com/package/next-rspack) adapter for you —
66
+ no manual `withRspack` composition needed:
67
+
68
+ ```typescript
69
+ import stylexPlugin from '@stylexswc/nextjs-plugin/rspack';
70
+
71
+ module.exports = stylexPlugin({
72
+ // StyleX options here
73
+ })({
74
+ // Next.js config here
75
+ });
76
+ ```
77
+
78
+ > [!NOTE]
79
+ > Run `next dev` and `next build` without the `--webpack`/`--turbopack` flags. For
80
+ > `next start`, set `NEXT_RSPACK=true` in the environment (the production server only
81
+ > serves prebuilt output, but it still evaluates the config).
82
+
83
+ The Rspack integration extracts StyleX CSS from both Server and Client Components, with
84
+ the same options as the Webpack plugin, plus `stylexPackages` from
85
+ [`@stylexswc/rspack-plugin`](https://github.com/Dwlad90/stylex-swc-plugin/tree/develop/packages/rspack-plugin).
86
+
87
+ > [!NOTE]
88
+ > Packages listed in `transpilePackages` are automatically added to the `stylexPackages`
89
+ > allowlist, so StyleX source shipped in `node_modules` (e.g. `@stylexjs/open-props`) is
90
+ > picked up without extra configuration.
91
+
62
92
  ### Using with Turbopack
63
93
 
64
94
  > [!IMPORTANT]
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,gCAAgC,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAuFpE,QAAA,MAAM,UAAU,GACb,gBAAgB,kBAAkB,MAClC,aAAY,UAAe,KAAG,UAsJ9B,CAAC;AAEJ,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,gCAAgC,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAuFpE,QAAA,MAAM,UAAU,GACb,gBAAgB,kBAAkB,MAClC,aAAY,UAAe,KAAG,UAiK9B,CAAC;AAEJ,eAAe,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -191,8 +191,16 @@ const withStyleX = (pluginOptions) => (nextConfig = {}) => {
191
191
  }));
192
192
  }
193
193
  }
194
+ // Packages in transpilePackages ship untransformed source (Next requirement
195
+ // for StyleX-authoring packages), so they are exactly the node_modules
196
+ // packages the stylex-loader must process
197
+ const stylexPackages = Array.from(new Set([
198
+ ...(pluginOptions?.stylexPackages ?? webpack_plugin_1.DEFAULT_STYLEX_PACKAGES),
199
+ ...(nextConfig.transpilePackages ?? []),
200
+ ]));
194
201
  config.plugins.push(new webpack_plugin_1.default({
195
202
  ...pluginOptions,
203
+ stylexPackages,
196
204
  rsOptions: {
197
205
  ...pluginOptions?.rsOptions,
198
206
  dev: ctx.dev,
@@ -0,0 +1,5 @@
1
+ import type { NextConfig } from 'next/dist/server/config-shared';
2
+ import type { StyleXPluginOption } from '@stylexswc/rspack-plugin';
3
+ declare const withStyleX: (pluginOptions?: StyleXPluginOption) => (nextConfig?: NextConfig) => NextConfig;
4
+ export default withStyleX;
5
+ //# sourceMappingURL=rspack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rspack.d.ts","sourceRoot":"","sources":["../src/rspack.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,gCAAgC,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AA+EnE,QAAA,MAAM,UAAU,GACb,gBAAgB,kBAAkB,MAClC,aAAY,UAAe,KAAG,UAwL9B,CAAC;AAEJ,eAAe,UAAU,CAAC"}
package/dist/rspack.js ADDED
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const browserslist_1 = __importDefault(require("next/dist/compiled/browserslist"));
40
+ const css_1 = require("next/dist/build/webpack/config/blocks/css");
41
+ const get_rspack_1 = require("next/dist/shared/lib/get-rspack");
42
+ const rspack_plugin_1 = __importStar(require("@stylexswc/rspack-plugin"));
43
+ const next_rspack_1 = __importDefault(require("next-rspack"));
44
+ // Adopted from https://github.com/vercel/next.js/blob/1f1632979c78b3edfe59fd85d8cce62efcdee688/packages/next/build/webpack-config.ts#L60-L72
45
+ const getSupportedBrowsers = (dir, isDevelopment) => {
46
+ try {
47
+ return browserslist_1.default.loadConfig({
48
+ path: dir,
49
+ env: isDevelopment ? 'development' : 'production',
50
+ });
51
+ }
52
+ catch {
53
+ // Ignore
54
+ }
55
+ };
56
+ /**
57
+ * Resolves CssExtractRspackPlugin from the exact module instance Next.js uses
58
+ * (`next-rspack/rspack-core`), so the `instanceof` dedup check below cannot be
59
+ * defeated by a second copy of @rspack/core
60
+ */
61
+ const getCssExtractPlugin = () => {
62
+ const rspackCore = (0, get_rspack_1.getRspackCore)();
63
+ const plugin = rspackCore.rspack?.CssExtractRspackPlugin ?? rspackCore.CssExtractRspackPlugin;
64
+ if (!plugin) {
65
+ throw new Error('@stylexswc/nextjs-plugin/rspack: CssExtractRspackPlugin not found in next-rspack/rspack-core.');
66
+ }
67
+ return plugin;
68
+ };
69
+ // Adopt from Next.js' getGlobalCssLoader
70
+ // https://github.com/vercel/next.js/blob/d61b0761efae09bd9cb1201ff134ed8950d9deca/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
71
+ function getStyleXVirtualCssLoader(ctx, cssExtractPlugin, postcss) {
72
+ const loaders = [];
73
+ // Adopt from Next.js' getClientStyleLoader
74
+ // https://github.com/vercel/next.js/blob/56d35ede8ed2ab25fa8e29583d4e81e3e76a0e29/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L18
75
+ if (!ctx.isServer) {
76
+ loaders.push({
77
+ loader: cssExtractPlugin.loader,
78
+ options: {
79
+ publicPath: `${ctx.config.assetPrefix}/_next/`,
80
+ esModule: false,
81
+ },
82
+ });
83
+ }
84
+ // We don't actually use postcss-loader or css-loader to run against
85
+ // the stylex css (which doesn't exist yet).
86
+ // We use this loader to run against the virtual dummy css.
87
+ loaders.push({
88
+ // https://github.com/vercel/next.js/blob/0572e218afe130656be53f7367bf18c4ea389f7d/packages/next/build/webpack/config/blocks/css/loaders/global.ts#L29-L38
89
+ loader: require.resolve('next/dist/build/webpack/loaders/css-loader/src'),
90
+ options: {
91
+ // https://github.com/vercel/next.js/blob/88a5f263f11cb55907f0d89a4cd53647ee8e96ac/packages/next/build/webpack/config/blocks/css/index.ts#L142-L147
92
+ postcss,
93
+ importLoaders: 1,
94
+ modules: false,
95
+ },
96
+ });
97
+ return loaders;
98
+ }
99
+ const withStyleX = (pluginOptions) => (nextConfig = {}) => {
100
+ // Scoped per `withStyleX(...)` call rather than module-level, so it doesn't
101
+ // leak across unrelated Next.js configs sharing this process (e.g. a
102
+ // monorepo building multiple apps, or repeated calls in tests).
103
+ let count = 0;
104
+ // `withRspack` switches Next.js to the Rspack bundler for this config
105
+ // (sets NEXT_RSPACK); applied to the final config object so users don't
106
+ // have to compose `next-rspack` themselves
107
+ return (0, next_rspack_1.default)({
108
+ ...nextConfig,
109
+ webpack(config, ctx) {
110
+ if (!process.env.NEXT_RSPACK) {
111
+ throw new Error([
112
+ '@stylexswc/nextjs-plugin/rspack requires Next.js to run with Rspack.',
113
+ 'Run `next dev`/`next build` without the `--webpack` or `--turbopack` flags',
114
+ '(set NEXT_RSPACK=true for `next start`),',
115
+ 'or use `@stylexswc/nextjs-plugin` for the default webpack bundler.',
116
+ ].join(' '));
117
+ }
118
+ if (typeof nextConfig.webpack === 'function') {
119
+ config = nextConfig.webpack(config, ctx);
120
+ }
121
+ const { buildId, dev, isServer } = ctx;
122
+ if (pluginOptions?.rsOptions?.debug || process.env.STYLEX_DEBUG) {
123
+ console.log([
124
+ '!!!GETTING RSPACK CONFIG!!!',
125
+ '======================',
126
+ `Count: ${++count}`,
127
+ `Build ID: ${buildId}`,
128
+ `Server: ${isServer}`,
129
+ `Env: ${dev ? 'dev' : 'prod'}`,
130
+ ].join('\n'));
131
+ }
132
+ config.optimization ||= {};
133
+ config.optimization.splitChunks ||= {};
134
+ config.optimization.splitChunks.cacheGroups ||= {};
135
+ const extractCSS = pluginOptions?.extractCSS ?? true;
136
+ config.plugins ??= [];
137
+ let lazyPostCSSPromise = null;
138
+ const postcss = () => {
139
+ lazyPostCSSPromise ||= (0, css_1.lazyPostCSS)(ctx.dir, getSupportedBrowsers(ctx.dir, ctx.dev), nextConfig?.experimental?.disablePostcssPresetEnv, nextConfig?.experimental?.useLightningcss);
140
+ return lazyPostCSSPromise;
141
+ };
142
+ if (extractCSS) {
143
+ const CssExtractPlugin = getCssExtractPlugin();
144
+ // Based on https://github.com/vercel/next.js/blob/88a5f263f11cb55907f0d89a4cd53647ee8e96ac/packages/next/build/webpack/config/helpers.ts#L12-L18
145
+ const cssContainerRule = config.module?.rules?.find(rule => typeof rule === 'object' &&
146
+ rule !== null &&
147
+ Array.isArray(rule.oneOf) &&
148
+ rule.oneOf.some(setRule => setRule &&
149
+ setRule.test instanceof RegExp &&
150
+ typeof setRule.test.test === 'function' &&
151
+ setRule.test.test('filename.css')));
152
+ const cssRules = cssContainerRule?.oneOf;
153
+ if (!cssRules) {
154
+ throw new Error([
155
+ "@stylexswc/nextjs-plugin/rspack: could not find Next.js' css oneOf rules",
156
+ 'in the Rspack config. StyleX CSS extraction cannot be wired up —',
157
+ 'this likely indicates an incompatible Next.js version. Please report this issue.',
158
+ ].join(' '));
159
+ }
160
+ // Here we matches virtual css file emitted by StyleXPlugin
161
+ cssRules.unshift({
162
+ test: rspack_plugin_1.VIRTUAL_CSS_PATTERN,
163
+ use: getStyleXVirtualCssLoader(ctx, CssExtractPlugin, postcss),
164
+ });
165
+ // StyleX needs to emit the css file on both server and client, both during
166
+ // the development and production.
167
+ // However, Next.js only adds CssExtractRspackPlugin on the client.
168
+ //
169
+ // The instanceof check prevents multiple extract plugins from being added
170
+ // (which would cause RealContentHashPlugin to panic)
171
+ if (!config.plugins.some((plugin) => plugin instanceof CssExtractPlugin)) {
172
+ // HMR reloads the CSS file when the content changes but does not use
173
+ // the new file name, which means it can't contain a hash.
174
+ const filename = ctx.dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
175
+ config.plugins.push(new CssExtractPlugin({
176
+ filename,
177
+ chunkFilename: filename,
178
+ // Next.js guarantees that CSS order "doesn't matter", due to imposed
179
+ // restrictions:
180
+ // 1. Global CSS can only be defined in a single entrypoint (_app)
181
+ // 2. CSS Modules generate scoped class names by default and cannot
182
+ // include Global CSS (:global() selector).
183
+ //
184
+ // While not a perfect guarantee (e.g. liberal use of `:global()`
185
+ // selector), this assumption is required to code-split CSS.
186
+ //
187
+ // As for StyleX, the CSS is always atomic (so classes are always unique),
188
+ // and StyleX Plugin will always sort the css based on media query and pseudo
189
+ // selector.
190
+ //
191
+ // If this warning were to trigger, it'd be unactionable by the user,
192
+ // but likely not valid -- so just disable it.
193
+ ignoreOrder: true,
194
+ }));
195
+ }
196
+ }
197
+ // Packages in transpilePackages ship untransformed source (Next requirement
198
+ // for StyleX-authoring packages), so they are exactly the node_modules
199
+ // packages the stylex-loader must process
200
+ const stylexPackages = Array.from(new Set([
201
+ ...(pluginOptions?.stylexPackages ?? rspack_plugin_1.DEFAULT_STYLEX_PACKAGES),
202
+ ...(nextConfig.transpilePackages ?? []),
203
+ ]));
204
+ config.plugins.push(new rspack_plugin_1.default({
205
+ ...pluginOptions,
206
+ stylexPackages,
207
+ rsOptions: {
208
+ ...pluginOptions?.rsOptions,
209
+ dev: ctx.dev,
210
+ },
211
+ // Enforce nextjsMode to true
212
+ nextjsMode: true,
213
+ ...(extractCSS
214
+ ? {
215
+ async transformCss(css, filePath) {
216
+ const { postcssWithPlugins } = await postcss();
217
+ const result = await postcssWithPlugins.process(css, {
218
+ from: filePath,
219
+ map: {
220
+ inline: false,
221
+ annotation: false,
222
+ },
223
+ });
224
+ if (typeof pluginOptions?.transformCss === 'function') {
225
+ return pluginOptions.transformCss(result.css, filePath);
226
+ }
227
+ return result.css;
228
+ },
229
+ }
230
+ : { transformCss: undefined }),
231
+ }));
232
+ return config;
233
+ },
234
+ });
235
+ };
236
+ exports.default = withStyleX;
237
+ module.exports = withStyleX;
238
+ module.exports.default = withStyleX;
package/package.json CHANGED
@@ -1,43 +1,22 @@
1
1
  {
2
2
  "name": "@stylexswc/nextjs-plugin",
3
3
  "description": "StyleX NextJS plugin with NAPI-RS compiler",
4
- "version": "0.17.0-rc.3",
5
- "private": false,
6
- "license": "MIT",
7
- "sideEffects": false,
8
- "exports": {
9
- "./turbopack": {
10
- "types": "./dist/turbopack.d.ts",
11
- "import": "./dist/turbopack.js",
12
- "require": "./dist/turbopack.js"
13
- },
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js",
17
- "require": "./dist/index.js"
18
- },
19
- "./package.json": "./package.json"
20
- },
21
- "files": [
22
- "dist"
23
- ],
24
- "publishConfig": {
25
- "registry": "https://registry.npmjs.org/",
26
- "access": "public"
27
- },
4
+ "version": "0.17.0",
28
5
  "config": {
29
6
  "scripty": {
30
7
  "path": "../../scripts/packages"
31
8
  }
32
9
  },
33
10
  "dependencies": {
34
- "@stylexswc/rs-compiler": "0.17.0-rc.3",
35
- "@stylexswc/turbopack-plugin": "0.17.0-rc.3",
36
- "@stylexswc/webpack-plugin": "0.17.0-rc.3"
11
+ "@stylexswc/rs-compiler": "0.17.0",
12
+ "@stylexswc/rspack-plugin": "0.17.0",
13
+ "@stylexswc/turbopack-plugin": "0.17.0",
14
+ "@stylexswc/webpack-plugin": "0.17.0",
15
+ "next-rspack": "^16.2.9"
37
16
  },
38
17
  "devDependencies": {
39
- "@stylexswc/eslint-config": "0.17.0-rc.3",
40
- "@stylexswc/typescript-config": "0.17.0-rc.3",
18
+ "@stylexswc/eslint-config": "0.17.0",
19
+ "@stylexswc/typescript-config": "0.17.0",
41
20
  "@types/node": "^26.1.0",
42
21
  "next": "^16.2.9",
43
22
  "postcss": "^8.5.16",
@@ -45,9 +24,27 @@
45
24
  "react-dom": "^19.2.7",
46
25
  "webpack": "^5.108.3"
47
26
  },
48
- "peerDependencies": {
49
- "next": ">=15.0.0"
27
+ "exports": {
28
+ "./turbopack": {
29
+ "types": "./dist/turbopack.d.ts",
30
+ "import": "./dist/turbopack.js",
31
+ "require": "./dist/turbopack.js"
32
+ },
33
+ "./rspack": {
34
+ "types": "./dist/rspack.d.ts",
35
+ "import": "./dist/rspack.js",
36
+ "require": "./dist/rspack.js"
37
+ },
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js",
41
+ "require": "./dist/index.js"
42
+ },
43
+ "./package.json": "./package.json"
50
44
  },
45
+ "files": [
46
+ "dist"
47
+ ],
51
48
  "keywords": [
52
49
  "next",
53
50
  "nextjs",
@@ -55,8 +52,24 @@
55
52
  "stylex",
56
53
  "swc"
57
54
  ],
55
+ "license": "MIT",
58
56
  "main": "dist/index.js",
57
+ "peerDependencies": {
58
+ "next": ">=15.0.0",
59
+ "next-rspack": "^16.2.9"
60
+ },
61
+ "peerDependenciesMeta": {
62
+ "next-rspack": {
63
+ "optional": true
64
+ }
65
+ },
66
+ "private": false,
67
+ "publishConfig": {
68
+ "registry": "https://registry.npmjs.org/",
69
+ "access": "public"
70
+ },
59
71
  "repository": "https://github.com/Dwlad90/stylex-swc-plugin",
72
+ "sideEffects": false,
60
73
  "scripts": {
61
74
  "build": "scripty --ts",
62
75
  "check:artifacts": "scripty",