@stylexjs/unplugin 0.17.0 → 0.17.2

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
@@ -1,9 +1,10 @@
1
1
  # @stylexjs/unplugin
2
2
 
3
- Universal bundler plugin for StyleX built on top of unplugin. It compiles StyleX at build time, aggregates CSS from all transformed modules, and appends the result into an existing CSS asset produced by your bundler.
3
+ Universal bundler plugin for StyleX built on top of `unplugin`. It compiles StyleX at build time, aggregates CSS from all transformed modules, and appends the result into an existing CSS asset produced by your bundler (or emits a stable fallback when none exists).
4
4
 
5
- - Works with Vite/Rollup and Webpack/Rspack via unplugin.
6
- - Ensures a single CSS output for StyleX by injecting into one existing CSS file.
5
+ - Adapters for Vite/Rollup, Webpack/Rspack, and esbuild.
6
+ - Designed to keep StyleX output consolidated and deterministic.
7
+ - Dev helpers expose virtual modules for hot CSS reloads: `virtual:stylex:runtime` (JS) and `/virtual:stylex.css` (CSS) or `virtual:stylex:css-only` (JS shim).
7
8
 
8
9
  ## Install
9
10
 
@@ -11,56 +12,123 @@ Universal bundler plugin for StyleX built on top of unplugin. It compiles StyleX
11
12
  npm i -D @stylexjs/unplugin
12
13
  ```
13
14
 
14
- ## Usage
15
+ ## Usage by bundler
15
16
 
16
- Vite:
17
+ ### Vite
17
18
 
18
- ```js
19
+ ```ts
19
20
  // vite.config.ts
20
- import { defineConfig } from 'vite'
21
- import stylex from '@stylexjs/unplugin'
21
+ import { defineConfig } from 'vite';
22
+ import react from '@vitejs/plugin-react';
23
+ import stylex from '@stylexjs/unplugin';
22
24
 
23
25
  export default defineConfig({
24
- plugins: [stylex()]
25
- })
26
+ plugins: [
27
+ // devMode: 'full' | 'css-only' | 'off'
28
+ // externalPackages: ['lib-using-stylex'] // optional manual include
29
+ stylex.vite(),
30
+ react(),
31
+ ],
32
+ });
33
+ ```
34
+
35
+ Notes:
36
+ - The plugin auto-discovers installed packages that depend on `@stylexjs/stylex` (or any configured `importSources`) and excludes them from `optimizeDeps`/`ssr.optimizeDeps` so their StyleX code is transformed. Use `externalPackages` to force-deopt additional deps.
37
+ - `devMode: 'full'` injects a lightweight runtime that refetches the dev CSS endpoint on HMR. `css-only` serves just the CSS endpoint. `off` disables dev middleware/virtual modules.
38
+ - In dev, inject the virtual CSS + runtime from your HTML shell. If a `<script src="/@id/virtual:stylex:runtime">` tag is blocked by CORS (some frameworks proxy assets differently), call `import('virtual:stylex:runtime')` or `import('virtual:stylex:css-only')` from a tiny client shim instead.
39
+ - Ensure your app produces a CSS asset (default Vite behavior). If none exists, the plugin writes `stylex.css` in the output.
40
+
41
+ Dev HTML injection (baseline):
42
+
43
+ ```html
44
+ <!-- Add in your HTML shell when import.meta.env.DEV -->
45
+ <link rel="stylesheet" href="/virtual:stylex.css" />
46
+ <script type="module">
47
+ import('virtual:stylex:runtime'); // or 'virtual:stylex:css-only' if you only need CSS
48
+ </script>
26
49
  ```
27
50
 
28
- Rollup:
51
+ If your environment can safely load the runtime via a virtual module ID, replace
52
+ the inline script with `<script type="module" src="/@id/virtual:stylex:runtime">`.
53
+
54
+ ### Rollup
29
55
 
30
56
  ```js
31
57
  // rollup.config.mjs
32
- import stylex from '@stylexjs/unplugin'
58
+ import stylex from '@stylexjs/unplugin';
33
59
 
34
60
  export default {
35
- // ...
36
- plugins: [stylex()],
37
- }
61
+ plugins: [stylex.rollup()],
62
+ };
38
63
  ```
39
64
 
40
- Webpack:
65
+ ### Webpack
41
66
 
42
67
  ```js
43
68
  // webpack.config.js
44
- const stylex = require('@stylexjs/unplugin').default
69
+ const stylex = require('@stylexjs/unplugin').default;
70
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
45
71
 
46
72
  module.exports = {
47
- // ...
48
- plugins: [stylex()],
49
- }
73
+ module: {
74
+ rules: [
75
+ // your JS/TS loader here
76
+ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
77
+ ],
78
+ },
79
+ plugins: [stylex.webpack({ useCSSLayers: true }), new MiniCssExtractPlugin()],
80
+ };
50
81
  ```
51
82
 
52
- ## Options
83
+ ### Rspack
84
+
85
+ ```js
86
+ const rspack = require('@rspack/core');
87
+ const stylex = require('@stylexjs/unplugin').default;
53
88
 
54
- - `dev`: boolean, defaults based on `NODE_ENV`.
89
+ module.exports = {
90
+ plugins: [
91
+ stylex.rspack(),
92
+ new rspack.CssExtractRspackPlugin({ filename: 'index.css' }),
93
+ ],
94
+ };
95
+ ```
96
+
97
+ ### esbuild
98
+
99
+ ```js
100
+ import esbuild from 'esbuild';
101
+ import stylex from '@stylexjs/unplugin';
102
+
103
+ esbuild.build({
104
+ entryPoints: ['src/App.jsx'],
105
+ bundle: true,
106
+ metafile: true, // lets the plugin locate CSS outputs if any
107
+ plugins: [
108
+ stylex.esbuild({
109
+ importSources: ['@stylexjs/stylex'],
110
+ useCSSLayers: true,
111
+ }),
112
+ ],
113
+ });
114
+ ```
115
+
116
+ ## Options (shared)
117
+
118
+ - `dev`: boolean, defaults based on `NODE_ENV`/`BABEL_ENV`.
55
119
  - `importSources`: array of import sources to scan, default `['stylex', '@stylexjs/stylex']`.
56
120
  - `useCSSLayers`: boolean, emit CSS layers.
57
- - `babelConfig`: `{ plugins, presets }` to merge.
58
- - `unstable_moduleResolution`: forward to StyleX Babel plugin.
59
- - `lightningcssOptions`: pass-through options for lightningcss.
60
- - `cssInjectionTarget`: optional `(fileName: string) => boolean` to pick a CSS asset to append to. If not provided, the plugin picks `index.css`, `style.css`, or the first `.css` asset.
121
+ - `babelConfig`: `{ plugins, presets }` to merge into the internal Babel call.
122
+ - `unstable_moduleResolution`: forwarded to the StyleX Babel plugin.
123
+ - `lightningcssOptions`: pass-through options for `lightningcss`.
124
+ - `cssInjectionTarget`: `(fileName: string) => boolean` to pick a CSS asset to append to. Defaults to `index.css`, `style.css`, or the first `.css` asset.
125
+ - `externalPackages`: package names inside `node_modules` that should be treated like app code (useful if they ship StyleX). They are excluded from Vite dependency optimization.
126
+ - `devMode`: `'full' | 'css-only' | 'off'` (Vite only).
127
+ - `devPersistToDisk`: persist collected rules to `node_modules/.stylex/rules.json` in dev so multiple Vite environments can share CSS.
61
128
 
62
129
  ## Notes
63
130
 
64
- - The plugin always aggregates all StyleX CSS across modules in a compilation and injects it into one CSS asset. With multiple outputs (e.g. client/SSR), each output will get its own aggregated CSS.
65
- - If the bundler does not produce any CSS assets, the plugin logs a warning and skips injection.
66
-
131
+ - With multiple outputs (e.g. client/SSR), each output gets its own aggregated StyleX CSS.
132
+ - If the bundler produces no CSS assets, the plugin emits a fallback `stylex.css` (often in `assets/` for Rollup/Vite or alongside esbuild outputs).
133
+ - When using extraction plugins (Webpack/Rspack), ensure they run so there is a CSS asset to append to; otherwise the fallback file is created.
134
+ - Dev HMR CSS hookup: add `<link rel="stylesheet" href="/virtual:stylex.css" />` to your shell in dev. For the JS runtime, prefer `import('virtual:stylex:runtime')` (or `virtual:stylex:css-only` if you only need CSS) from a local client shim when direct `<script src="/@id/virtual:stylex:runtime">` fails due to CORS/proxying.
package/lib/es/index.mjs CHANGED
@@ -7,6 +7,7 @@ import typescriptSyntaxPlugin from '@babel/plugin-syntax-typescript';
7
7
  import path from 'node:path';
8
8
  import fs from 'node:fs';
9
9
  import fsp from 'node:fs/promises';
10
+ import { createRequire } from 'node:module';
10
11
  import { transform as lightningTransform } from 'lightningcss';
11
12
  import browserslist from 'browserslist';
12
13
  import { browserslistToTargets } from 'lightningcss';
@@ -38,7 +39,84 @@ function processCollectedRulesToCSS(rules, options) {
38
39
  });
39
40
  return code.toString();
40
41
  }
41
- const unpluginInstance = createUnplugin((userOptions = {}) => {
42
+ function readJSON(file) {
43
+ try {
44
+ const content = fs.readFileSync(file, 'utf8');
45
+ return JSON.parse(content);
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+ function findNearestPackageJson(startDir) {
51
+ let dir = startDir;
52
+ for (;;) {
53
+ const candidate = path.join(dir, 'package.json');
54
+ if (fs.existsSync(candidate)) return candidate;
55
+ const parent = path.dirname(dir);
56
+ if (parent === dir) break;
57
+ dir = parent;
58
+ }
59
+ return null;
60
+ }
61
+ function toPackageName(importSource) {
62
+ const source = typeof importSource === 'string' ? importSource : importSource?.from;
63
+ if (!source || source.startsWith('.') || source.startsWith('/')) return null;
64
+ if (source.startsWith('@')) {
65
+ const [scope, name] = source.split('/');
66
+ if (scope && name) return `${scope}/${name}`;
67
+ }
68
+ const [pkg] = source.split('/');
69
+ return pkg || null;
70
+ }
71
+ function hasStylexDependency(manifest, targetPackages) {
72
+ if (!manifest || typeof manifest !== 'object') return false;
73
+ const depFields = ['dependencies', 'peerDependencies', 'optionalDependencies'];
74
+ for (const field of depFields) {
75
+ const deps = manifest[field];
76
+ if (!deps || typeof deps !== 'object') continue;
77
+ for (const name of Object.keys(deps)) {
78
+ if (targetPackages.has(name)) return true;
79
+ }
80
+ }
81
+ return false;
82
+ }
83
+ function discoverStylexPackages({
84
+ importSources,
85
+ explicitPackages,
86
+ rootDir,
87
+ resolver
88
+ }) {
89
+ const targetPackages = new Set(importSources.map(toPackageName).filter(Boolean).concat(['@stylexjs/stylex']));
90
+ const found = new Set(explicitPackages || []);
91
+ const pkgJsonPath = findNearestPackageJson(rootDir);
92
+ if (!pkgJsonPath) return Array.from(found);
93
+ const pkgDir = path.dirname(pkgJsonPath);
94
+ const pkgJson = readJSON(pkgJsonPath);
95
+ if (!pkgJson) return Array.from(found);
96
+ const depFields = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
97
+ const deps = new Set();
98
+ for (const field of depFields) {
99
+ const entries = pkgJson[field];
100
+ if (!entries || typeof entries !== 'object') continue;
101
+ for (const name of Object.keys(entries)) deps.add(name);
102
+ }
103
+ for (const dep of deps) {
104
+ let manifestPath = null;
105
+ try {
106
+ manifestPath = resolver.resolve(`${dep}/package.json`, {
107
+ paths: [pkgDir]
108
+ });
109
+ } catch {}
110
+ if (!manifestPath) continue;
111
+ const manifest = readJSON(manifestPath);
112
+ if (hasStylexDependency(manifest, targetPackages)) {
113
+ found.add(dep);
114
+ }
115
+ }
116
+ return Array.from(found);
117
+ }
118
+ const unpluginInstance = createUnplugin((userOptions = {}, metaOptions) => {
119
+ const framework = metaOptions?.framework;
42
120
  const {
43
121
  dev = process.env.NODE_ENV === 'development' || process.env.BABEL_ENV === 'development',
44
122
  unstable_moduleResolution = {
@@ -53,8 +131,10 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
53
131
  useCSSLayers = false,
54
132
  lightningcssOptions,
55
133
  cssInjectionTarget,
134
+ externalPackages = [],
56
135
  devPersistToDisk = false,
57
136
  devMode = 'full',
137
+ treeshakeCompensation = ['vite', 'rollup', 'rolldown'].includes(framework),
58
138
  ...stylexOptions
59
139
  } = userOptions;
60
140
  const stylexRulesById = new Map();
@@ -77,6 +157,14 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
77
157
  }
78
158
  let viteServer = null;
79
159
  let viteOutDir = null;
160
+ const nearestPkgJson = findNearestPackageJson(process.cwd());
161
+ const requireFromCwd = nearestPkgJson ? createRequire(nearestPkgJson) : createRequire(path.join(process.cwd(), 'package.json'));
162
+ const stylexPackages = discoverStylexPackages({
163
+ importSources,
164
+ explicitPackages: externalPackages,
165
+ rootDir: nearestPkgJson ? path.dirname(nearestPkgJson) : process.cwd(),
166
+ resolver: requireFromCwd
167
+ });
80
168
  function findNearestNodeModules(startDir) {
81
169
  let dir = startDir;
82
170
  for (;;) {
@@ -103,6 +191,8 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
103
191
  isTSX: true
104
192
  }], jsxSyntaxPlugin, stylexBabelPlugin.withOptions({
105
193
  ...stylexOptions,
194
+ importSources,
195
+ treeshakeCompensation,
106
196
  dev,
107
197
  unstable_moduleResolution
108
198
  })],
@@ -271,6 +361,23 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
271
361
  } else {}
272
362
  },
273
363
  vite: devMode === 'off' ? undefined : {
364
+ config(config) {
365
+ if (!stylexPackages || stylexPackages.length === 0) return;
366
+ const addExcludes = (existing = []) => Array.from(new Set([...existing, ...stylexPackages]));
367
+ return {
368
+ optimizeDeps: {
369
+ ...(config?.optimizeDeps || {}),
370
+ exclude: addExcludes(config?.optimizeDeps?.exclude || [])
371
+ },
372
+ ssr: {
373
+ ...(config?.ssr || {}),
374
+ optimizeDeps: {
375
+ ...(config?.ssr?.optimizeDeps || {}),
376
+ exclude: addExcludes(config?.ssr?.optimizeDeps?.exclude || [])
377
+ }
378
+ }
379
+ };
380
+ },
274
381
  configResolved(config) {
275
382
  try {
276
383
  viteOutDir = config.build?.outDir || viteOutDir;
@@ -310,15 +417,15 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
310
417
  server.httpServer?.once('close', () => clearInterval(interval));
311
418
  },
312
419
  resolveId(id) {
313
- if (devMode === 'full' && id === 'virtual:stylex:runtime') return id;
314
- if (devMode === 'css-only' && id === 'virtual:stylex:css-only') return id;
420
+ if (devMode === 'full' && id.includes('virtual:stylex:runtime')) return id;
421
+ if (devMode === 'css-only' && id.includes('virtual:stylex:css-only')) return id;
315
422
  return null;
316
423
  },
317
424
  load(id) {
318
- if (devMode === 'full' && id === 'virtual:stylex:runtime') {
425
+ if (devMode === 'full' && id.includes('virtual:stylex:runtime')) {
319
426
  return VIRTUAL_STYLEX_RUNTIME_SCRIPT;
320
427
  }
321
- if (devMode === 'css-only' && id === 'virtual:stylex:css-only') {
428
+ if (devMode === 'css-only' && id.includes('virtual:stylex:css-only')) {
322
429
  return VIRTUAL_STYLEX_CSS_ONLY_SCRIPT;
323
430
  }
324
431
  return null;
@@ -326,24 +433,26 @@ const unpluginInstance = createUnplugin((userOptions = {}) => {
326
433
  transformIndexHtml() {
327
434
  if (devMode !== 'full') return null;
328
435
  if (!viteServer) return null;
436
+ const base = viteServer.config.base ?? '';
329
437
  return [{
330
438
  tag: 'script',
331
439
  attrs: {
332
440
  type: 'module',
333
- src: '/@id/virtual:stylex:runtime'
441
+ src: path.join(base, '/@id/virtual:stylex:runtime')
334
442
  },
335
443
  injectTo: 'head'
336
444
  }, {
337
445
  tag: 'link',
338
446
  attrs: {
339
447
  rel: 'stylesheet',
340
- href: DEV_CSS_PATH
448
+ href: path.join(base, DEV_CSS_PATH)
341
449
  },
342
450
  injectTo: 'head'
343
451
  }];
344
452
  },
345
453
  handleHotUpdate(ctx) {
346
- const cssMod = ctx.server.moduleGraph.getModuleById('virtual:stylex:css-module');
454
+ const base = ctx.server.config.base ?? '';
455
+ const cssMod = ctx.server.moduleGraph.getModuleById(path.join(base, 'virtual:stylex:css-module'));
347
456
  if (cssMod) {
348
457
  ctx.server.moduleGraph.invalidateModule(cssMod);
349
458
  }
package/lib/index.d.ts CHANGED
@@ -1,4 +1,17 @@
1
1
  import { type UnpluginInstance } from 'unplugin';
2
+ import type { Options as StyleXOptions } from '@stylexjs/babel-plugin';
3
+ import type { TransformOptions as LightningcssOptions } from 'lightningcss';
2
4
 
3
5
  export default unplugin;
4
- declare const unplugin: UnpluginInstance<any, boolean>;
6
+
7
+ type UserOptions = StyleXOptions & {
8
+ useCSSLayers?: boolean;
9
+ enableLTRRTLComments?: boolean;
10
+ legacyDisableLayers?: boolean;
11
+ lightningcssOptions?: LightningcssOptions;
12
+ cssInjectionTarget?: (filepath: string) => boolean;
13
+ devPersistToDisk?: boolean;
14
+ devMode?: 'full' | 'css-only' | 'off';
15
+ };
16
+
17
+ declare const unplugin: UnpluginInstance<Partial<UserOptions>, false>;
package/lib/index.js CHANGED
@@ -13,6 +13,7 @@ var _pluginSyntaxTypescript = _interopRequireDefault(require("@babel/plugin-synt
13
13
  var _nodePath = _interopRequireDefault(require("node:path"));
14
14
  var _nodeFs = _interopRequireDefault(require("node:fs"));
15
15
  var _promises = _interopRequireDefault(require("node:fs/promises"));
16
+ var _nodeModule = require("node:module");
16
17
  var _lightningcss = require("lightningcss");
17
18
  var _browserslist = _interopRequireDefault(require("browserslist"));
18
19
  var _devInjectMiddleware = require("./dev-inject-middleware");
@@ -44,7 +45,84 @@ function processCollectedRulesToCSS(rules, options) {
44
45
  });
45
46
  return code.toString();
46
47
  }
47
- const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
48
+ function readJSON(file) {
49
+ try {
50
+ const content = _nodeFs.default.readFileSync(file, 'utf8');
51
+ return JSON.parse(content);
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+ function findNearestPackageJson(startDir) {
57
+ let dir = startDir;
58
+ for (;;) {
59
+ const candidate = _nodePath.default.join(dir, 'package.json');
60
+ if (_nodeFs.default.existsSync(candidate)) return candidate;
61
+ const parent = _nodePath.default.dirname(dir);
62
+ if (parent === dir) break;
63
+ dir = parent;
64
+ }
65
+ return null;
66
+ }
67
+ function toPackageName(importSource) {
68
+ const source = typeof importSource === 'string' ? importSource : importSource?.from;
69
+ if (!source || source.startsWith('.') || source.startsWith('/')) return null;
70
+ if (source.startsWith('@')) {
71
+ const [scope, name] = source.split('/');
72
+ if (scope && name) return `${scope}/${name}`;
73
+ }
74
+ const [pkg] = source.split('/');
75
+ return pkg || null;
76
+ }
77
+ function hasStylexDependency(manifest, targetPackages) {
78
+ if (!manifest || typeof manifest !== 'object') return false;
79
+ const depFields = ['dependencies', 'peerDependencies', 'optionalDependencies'];
80
+ for (const field of depFields) {
81
+ const deps = manifest[field];
82
+ if (!deps || typeof deps !== 'object') continue;
83
+ for (const name of Object.keys(deps)) {
84
+ if (targetPackages.has(name)) return true;
85
+ }
86
+ }
87
+ return false;
88
+ }
89
+ function discoverStylexPackages({
90
+ importSources,
91
+ explicitPackages,
92
+ rootDir,
93
+ resolver
94
+ }) {
95
+ const targetPackages = new Set(importSources.map(toPackageName).filter(Boolean).concat(['@stylexjs/stylex']));
96
+ const found = new Set(explicitPackages || []);
97
+ const pkgJsonPath = findNearestPackageJson(rootDir);
98
+ if (!pkgJsonPath) return Array.from(found);
99
+ const pkgDir = _nodePath.default.dirname(pkgJsonPath);
100
+ const pkgJson = readJSON(pkgJsonPath);
101
+ if (!pkgJson) return Array.from(found);
102
+ const depFields = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
103
+ const deps = new Set();
104
+ for (const field of depFields) {
105
+ const entries = pkgJson[field];
106
+ if (!entries || typeof entries !== 'object') continue;
107
+ for (const name of Object.keys(entries)) deps.add(name);
108
+ }
109
+ for (const dep of deps) {
110
+ let manifestPath = null;
111
+ try {
112
+ manifestPath = resolver.resolve(`${dep}/package.json`, {
113
+ paths: [pkgDir]
114
+ });
115
+ } catch {}
116
+ if (!manifestPath) continue;
117
+ const manifest = readJSON(manifestPath);
118
+ if (hasStylexDependency(manifest, targetPackages)) {
119
+ found.add(dep);
120
+ }
121
+ }
122
+ return Array.from(found);
123
+ }
124
+ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}, metaOptions) => {
125
+ const framework = metaOptions?.framework;
48
126
  const {
49
127
  dev = process.env.NODE_ENV === 'development' || process.env.BABEL_ENV === 'development',
50
128
  unstable_moduleResolution = {
@@ -59,8 +137,10 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
59
137
  useCSSLayers = false,
60
138
  lightningcssOptions,
61
139
  cssInjectionTarget,
140
+ externalPackages = [],
62
141
  devPersistToDisk = false,
63
142
  devMode = 'full',
143
+ treeshakeCompensation = ['vite', 'rollup', 'rolldown'].includes(framework),
64
144
  ...stylexOptions
65
145
  } = userOptions;
66
146
  const stylexRulesById = new Map();
@@ -83,6 +163,14 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
83
163
  }
84
164
  let viteServer = null;
85
165
  let viteOutDir = null;
166
+ const nearestPkgJson = findNearestPackageJson(process.cwd());
167
+ const requireFromCwd = nearestPkgJson ? (0, _nodeModule.createRequire)(nearestPkgJson) : (0, _nodeModule.createRequire)(_nodePath.default.join(process.cwd(), 'package.json'));
168
+ const stylexPackages = discoverStylexPackages({
169
+ importSources,
170
+ explicitPackages: externalPackages,
171
+ rootDir: nearestPkgJson ? _nodePath.default.dirname(nearestPkgJson) : process.cwd(),
172
+ resolver: requireFromCwd
173
+ });
86
174
  function findNearestNodeModules(startDir) {
87
175
  let dir = startDir;
88
176
  for (;;) {
@@ -109,6 +197,8 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
109
197
  isTSX: true
110
198
  }], _pluginSyntaxJsx.default, _babelPlugin.default.withOptions({
111
199
  ...stylexOptions,
200
+ importSources,
201
+ treeshakeCompensation,
112
202
  dev,
113
203
  unstable_moduleResolution
114
204
  })],
@@ -277,6 +367,23 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
277
367
  } else {}
278
368
  },
279
369
  vite: devMode === 'off' ? undefined : {
370
+ config(config) {
371
+ if (!stylexPackages || stylexPackages.length === 0) return;
372
+ const addExcludes = (existing = []) => Array.from(new Set([...existing, ...stylexPackages]));
373
+ return {
374
+ optimizeDeps: {
375
+ ...(config?.optimizeDeps || {}),
376
+ exclude: addExcludes(config?.optimizeDeps?.exclude || [])
377
+ },
378
+ ssr: {
379
+ ...(config?.ssr || {}),
380
+ optimizeDeps: {
381
+ ...(config?.ssr?.optimizeDeps || {}),
382
+ exclude: addExcludes(config?.ssr?.optimizeDeps?.exclude || [])
383
+ }
384
+ }
385
+ };
386
+ },
280
387
  configResolved(config) {
281
388
  try {
282
389
  viteOutDir = config.build?.outDir || viteOutDir;
@@ -316,15 +423,15 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
316
423
  server.httpServer?.once('close', () => clearInterval(interval));
317
424
  },
318
425
  resolveId(id) {
319
- if (devMode === 'full' && id === 'virtual:stylex:runtime') return id;
320
- if (devMode === 'css-only' && id === 'virtual:stylex:css-only') return id;
426
+ if (devMode === 'full' && id.includes('virtual:stylex:runtime')) return id;
427
+ if (devMode === 'css-only' && id.includes('virtual:stylex:css-only')) return id;
321
428
  return null;
322
429
  },
323
430
  load(id) {
324
- if (devMode === 'full' && id === 'virtual:stylex:runtime') {
431
+ if (devMode === 'full' && id.includes('virtual:stylex:runtime')) {
325
432
  return _consts.VIRTUAL_STYLEX_RUNTIME_SCRIPT;
326
433
  }
327
- if (devMode === 'css-only' && id === 'virtual:stylex:css-only') {
434
+ if (devMode === 'css-only' && id.includes('virtual:stylex:css-only')) {
328
435
  return _consts.VIRTUAL_STYLEX_CSS_ONLY_SCRIPT;
329
436
  }
330
437
  return null;
@@ -332,24 +439,26 @@ const unpluginInstance = (0, _unplugin.createUnplugin)((userOptions = {}) => {
332
439
  transformIndexHtml() {
333
440
  if (devMode !== 'full') return null;
334
441
  if (!viteServer) return null;
442
+ const base = viteServer.config.base ?? '';
335
443
  return [{
336
444
  tag: 'script',
337
445
  attrs: {
338
446
  type: 'module',
339
- src: '/@id/virtual:stylex:runtime'
447
+ src: _nodePath.default.join(base, '/@id/virtual:stylex:runtime')
340
448
  },
341
449
  injectTo: 'head'
342
450
  }, {
343
451
  tag: 'link',
344
452
  attrs: {
345
453
  rel: 'stylesheet',
346
- href: _consts.DEV_CSS_PATH
454
+ href: _nodePath.default.join(base, _consts.DEV_CSS_PATH)
347
455
  },
348
456
  injectTo: 'head'
349
457
  }];
350
458
  },
351
459
  handleHotUpdate(ctx) {
352
- const cssMod = ctx.server.moduleGraph.getModuleById('virtual:stylex:css-module');
460
+ const base = ctx.server.config.base ?? '';
461
+ const cssMod = ctx.server.moduleGraph.getModuleById(_nodePath.default.join(base, 'virtual:stylex:css-module'));
353
462
  if (cssMod) {
354
463
  ctx.server.moduleGraph.invalidateModule(cssMod);
355
464
  }
package/package.json CHANGED
@@ -1,10 +1,7 @@
1
1
  {
2
2
  "name": "@stylexjs/unplugin",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "private": false,
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
5
  "description": "Universal bundler plugin for StyleX using unplugin",
9
6
  "license": "MIT",
10
7
  "main": "./lib/index.js",
@@ -31,14 +28,14 @@
31
28
  "test": "jest"
32
29
  },
33
30
  "peerDependencies": {
34
- "unplugin": "^1.7.1"
31
+ "unplugin": "^2.3.11"
35
32
  },
36
33
  "dependencies": {
37
34
  "@babel/core": "^7.26.8",
38
35
  "@babel/plugin-syntax-flow": "^7.26.0",
39
36
  "@babel/plugin-syntax-jsx": "^7.25.9",
40
37
  "@babel/plugin-syntax-typescript": "^7.25.9",
41
- "@stylexjs/babel-plugin": "0.17.0",
38
+ "@stylexjs/babel-plugin": "0.17.2",
42
39
  "browserslist": "^4.24.0",
43
40
  "lightningcss": "^1.29.1"
44
41
  },