Skip to content

Uniwind styles not applied when using Jotai workaround for import.meta (Metro resolveRequest override) #236

Description

@bernardogeneroso

What happened?

I’m using Expo + Uniwind + Jotai.
Jotai requires a Metro workaround to avoid the import.meta error (forcing Metro to resolve the CJS/default entry via unstable_conditionNames). After adding this workaround in metro.config.js, Uniwind stops being applied (className styles don’t work / no styling effect).

If I remove the Jotai workaround, Uniwind works normally.

This repro repository demonstrates the problem.


To use Jotai in this setup, I need a Metro resolveRequest override like (file metro.config.js):

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');
const { withUniwindConfig } = require('uniwind/metro'); 

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

// Add wasm asset support
config.resolver.assetExts.push('wasm');

config.resolver.resolveRequest = (context, moduleName, platform) => {
  switch (moduleName) {
    case 'jotai':
      // Force Metro to use the "default" condition only (CJS),
      // instead of the ESM entry that includes import.meta.
      return context.resolveRequest(
        { ...context, unstable_conditionNames: ['default'] },
        moduleName,
        platform
      );

    default:
      return context.resolveRequest(context, moduleName, platform);
  }
};

config.resolver.unstable_conditionNames = [
  'browser',
  'require',
  'react-native',
]
 
// Add COEP and COOP headers to support SharedArrayBuffer
config.server.enhanceMiddleware = (middleware) => {
  return (req, res, next) => {
    res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
    res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
    middleware(req, res, next);
  };
};

module.exports = withUniwindConfig(config, {  
  // relative path to your global.css file (from previous step)
  cssEntryFile: './src/global.css',
  // (optional) path where we gonna auto-generate typings
  // defaults to project's root
  dtsFile: './src/uniwind-types.d.ts',
  debug: true,
});

And even try like this:

const { getDefaultConfig } = require("expo/metro-config");
const { withUniwindConfig } = require("uniwind/metro");

let config = getDefaultConfig(__dirname);

// 1) Apply Uniwind FIRST (requires let)
config = withUniwindConfig(config, {
  cssEntryFile: "./src/global.css",
  dtsFile: "./src/uniwind-types.d.ts",
  debug: true,
});

// 2) wasm support
config.resolver.assetExts = Array.from(
  new Set([...(config.resolver.assetExts ?? []), "wasm"])
);

// 3) Wrap Uniwind resolver (DON’T bypass it)
const uniwindResolveRequest = config.resolver.resolveRequest;

config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (moduleName === "jotai") {
    return uniwindResolveRequest(
      { ...context, unstable_conditionNames: ["require", "default"] },
      moduleName,
      platform
    );
  }

  return uniwindResolveRequest(context, moduleName, platform);
};

// 4) If you really need global condition names, include default
config.resolver.unstable_conditionNames = [
  "browser",
  "react-native",
  "require",
  "default",
];

// 5) COEP/COOP headers (preserve previous enhancer)
const prevEnhance = config.server.enhanceMiddleware;
config.server.enhanceMiddleware = (middleware) => {
  const nextMiddleware = prevEnhance ? prevEnhance(middleware) : middleware;

  return (req, res, next) => {
    res.setHeader("Cross-Origin-Embedder-Policy", "credentialless");
    res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
    nextMiddleware(req, res, next);
  };
};

module.exports = config;

Steps to Reproduce

  1. Clone repro: https://github.com/bernardogeneroso/test-uniwind
  2. Install deps
  3. Run web: npx expo start --web (or npx expo start -c --web)
  4. Observe: Uniwind styles are not applied when the Jotai Metro workaround is enabled.

Snack or Repository Link

https://github.com/bernardogeneroso/test-uniwind

Uniwind version

1.2.2

React Native Version

0.81.5

Platforms

Web

Expo

Yes

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions