Skip to content

fix: Ensure Windows path compatibility in web platform transformation#860

Open
dmitryshostak wants to merge 1 commit intonativewind:mainfrom
dmitryshostak:main
Open

fix: Ensure Windows path compatibility in web platform transformation#860
dmitryshostak wants to merge 1 commit intonativewind:mainfrom
dmitryshostak:main

Conversation

@dmitryshostak
Copy link
Copy Markdown

This PR fixes an issue where Windows paths were not correctly handled in the Metro transformer's web platform transformation, causing incorrect runtime module resolution.

It's a duplicate of #854, but with a better naming so we don't break it again. ❗

@marklawlor could you please merge it ASAP as we're using nativewind in production and we hate to patch it :)

The related issue - #784 (comment)

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 29, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
nativewind ✅ Ready (Inspect) Visit Preview Mar 29, 2024 8:05pm

@yjose
Copy link
Copy Markdown
Contributor

yjose commented Mar 31, 2024

@marklawlor We encountered the same issue on Windows as well, and the fix appears to be working as expected. 🙏

@Alejandro-M-Cruz
Copy link
Copy Markdown

Alejandro-M-Cruz commented Apr 22, 2024

Same here. It would be great if it could be merged soon. By the way, great work by @marklawlor and all contributors, Nativewind is amazing

@aaronksaunders
Copy link
Copy Markdown

@dmitryshostak how can i use this branch in my project now? I am blocked.

@Alejandro-M-Cruz
Copy link
Copy Markdown

Alejandro-M-Cruz commented Apr 27, 2024

Hi, @aaronksaunders. I think there are ways to install a dependency from a pull request / fork, but at least it didn't seem to work for me. I created this simple PHP script that applies the fix once the nativewind package has been installed. I run it whenever I install my front-end dependencies. You can easily translate the script to whatever language you prefer.

<?php

$filePath = 'front-end/node_modules/nativewind/dist/metro/transformer.js';
$content = file_get_contents($filePath);

$issue = '`require(\'${config.nativewind.output}\');`';

if (! str_contains($content, $issue)) {
    echo 'NativeWind fix already applied!';
    return;
}

$fix = '`require(\'${config.nativewind.output.replace(/\\\\/g, \'\\\\\\\\\')}\');`';

$result = str_replace($issue, $fix, $content);

file_put_contents($filePath, $result);

echo 'NativeWind fix applied successfully!';

@rickychan0611
Copy link
Copy Markdown

rickychan0611 commented Apr 28, 2024

Inspired by @Alejandro-M-Cruz, I've created JavaScript instead. You can place it in the root directory of your project.

To integrate this script with your application, add the following entry to your package.json. This will ensure the script runs every time you start your program:

 "scripts": {
    "start": "node fix.js && expo start"
  },

Here is the JavaScript script:

// fix.js
const fs = require('fs');
const path = require('path');

const filePath = path.join('.', 'node_modules', 'nativewind', 'dist', 'metro', 'transformer.js');

fs.readFile(filePath, 'utf8', (err, content) => {
    if (err) {
        console.error(err);
        return;
    }

    const issue = '`require(\'${config.nativewind.output}\');`';

    if (!content.includes(issue)) {
        console.log('NativeWind fix already applied!');
        return;
    }

    const fix = '`require(\'${config.nativewind.output.replace(/\\\\/g, \'\\\\\\\\\')}\');`';
    const result = content.replace(issue, fix);

    fs.writeFile(filePath, result, 'utf8', (err) => {
        if (err) {
            console.error(err);
            return;
        }
        console.log('NativeWind fix applied successfully!');
    });
});

This setup allows the fix.js script to batch process necessary adjustments automatically whenever you initiate your project with expo start.

@dmitryshostak
Copy link
Copy Markdown
Author

@rickychan0611 great! the only thing - I would add it to postinstall :) 👍

@SakuZN
Copy link
Copy Markdown

SakuZN commented May 27, 2024

The script by @rickychan0611 works but in my end first install and run of the web script will cause the following error:

Web Bundling failed 31297ms C:\path\index.js (2280 modules)
Unable to resolve "C:\path\node_modules\.cache\nativewind\global.css" from "app\global.css"

Metro error: Unable to resolve module C:\path\node_modules\.cache\nativewind\global.css from C:\Users\ZachNoche\WebstormProjects\seriousmd-loyalty-card\app\global.css:

None of these files exist:
  * node_modules\.cache\nativewind\global.css(.web.ts|.ts|.web.tsx|.tsx|.web.mjs|.mjs|.web.js|.js|.web.jsx|.jsx|.web.json|.json|.web.cjs|.cjs|.web.scss|.scss|.web.sass|.sass|.web.css|.css|.web.css|.css)
  * node_modules\.cache\nativewind\global.css\index(.web.ts|.ts|.web.tsx|.tsx|.web.mjs|.mjs|.web.js|.js|.web.jsx|.jsx|.web.json|.json|.web.cjs|.cjs|.web.scss|.scss|.web.sass|.sass|.web.css|.css|.web.css|.css)
> 1 | @tailwind base;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2 | @tailwind components;
  3 | @tailwind utilities;


Call Stack
  MetroBundlerDevServer.getStaticResourcesAsync (node_modules/@expo/cli/src/start/server/metro/MetroBundlerDevServer.ts)
  processTicksAndRejections (node:internal/process/task_queues)
  MetroBundlerDevServer.getStaticPageAsync (node_modules/@expo/cli/src/start/server/metro/MetroBundlerDevServer.ts)
  getHtml (node_modules/@expo/cli/src/start/server/metro/createServerRouteMiddleware.ts)
  handler (node_modules/@expo/server/src/index.ts)
  <unknown> (node_modules/@expo/server/src/vendor/http.ts)

However, if I stop the server and run the web script again, it now works as normal. Anyone know why?

@rickychan0611
Copy link
Copy Markdown

However, if I stop the server and run the web script again, it now works as normal. Anyone know why?

You need to clear the cache when starting the server
yarn start -c

@rickychan0611
Copy link
Copy Markdown

As native-wind is no longer maintained, I have switched to tailwind-react-native-classnames. It is also much faster

@shawnmclean
Copy link
Copy Markdown

As native-wind is no longer maintained, I have switched to tailwind-react-native-classnames. It is also much faster

for real?

the guy announced it or just stopped merging PRs?

@a0m0rajab
Copy link
Copy Markdown

@rickychan0611 it's not no-longer maintained, check this: #600

@guibzo
Copy link
Copy Markdown

guibzo commented Jun 29, 2024

@marklawlor please merge this 💔

@guibzo
Copy link
Copy Markdown

guibzo commented Jul 22, 2024

For now, since this didn't got merged yet, got it to work other way, here is how:

Created in the root of the project a fix.js with the following code

/* 
  This is used to fix a bug in Metro that prevents NativeWind from being applied on web in Windows, which crashes the compiler.
  See: https://github.com/nativewind/nativewind/pull/860
*/

const fs = require('fs')
const path = require('path')

const filePath = path.join('.', 'node_modules', 'nativewind', 'dist', 'metro', 'transformer.js')

fs.readFile(filePath, 'utf8', (err, content) => {
  if (err) {
    console.error(err)
    return
  }

  const cjsIssue = "`require('${config.nativewind.output}');`"
  const ecsIssue = "`import '${config.nativewind.output}'`"

  if (!content.includes(cjsIssue) && !content.includes(ecsIssue)) {
    return console.log('🎉 NativeWind fix already applied!')
  }

  const fix = "`require('${config.nativewind.output.replace(/\\\\/g, '\\\\\\\\')}');`"

  let updatedContent = content.replace(cjsIssue, fix)
  updatedContent = updatedContent.replace(ecsIssue, fix)

  fs.writeFile(filePath, updatedContent, 'utf8', (err) => {
    if (err) {
      return console.error(err)
    }
    console.log('🎉 NativeWind fix applied successfully!')
  })
})

Then I added postinstall to run it:
image

Versions are
"nativewind": "^4.0.1",
"tailwindcss": "^3.4.4",

@guibzo guibzo mentioned this pull request Jul 22, 2024
@shawnmclean
Copy link
Copy Markdown

@guibzo nice patch!

Have you ever used pnpm patch before? It does something like this.

@guibzo
Copy link
Copy Markdown

guibzo commented Aug 2, 2024

@guibzo nice patch!

Have you ever used pnpm patch before? It does something like this.

I did not, but probably it would work as well as with postinstall.

@vedantb2
Copy link
Copy Markdown

vedantb2 commented Aug 8, 2024

please merge this

@Dev-mininos
Copy link
Copy Markdown

i tried this patch but it didn't work for me while using flatlist component

@manssorr
Copy link
Copy Markdown

We create this patch using patch-package.
by one of our team members @amrya200t

create: patches/nativewind+4.0.36.patch

diff --git a/node_modules/nativewind/dist/metro/transformer.js b/node_modules/nativewind/dist/metro/transformer.js
index 75f0c40..9b6d303 100644
--- a/node_modules/nativewind/dist/metro/transformer.js
+++ b/node_modules/nativewind/dist/metro/transformer.js
@@ -11,7 +11,8 @@ const transformer_1 = require("react-native-css-interop/metro/transformer");
 async function transform(config, projectRoot, filename, data, options) {
     if (path_1.default.resolve(process.cwd(), filename) === config.nativewind.input) {
         if (options.platform === "web") {
-            return metro_transform_worker_1.default.transform(config, projectRoot, filename, Buffer.from(`require('${config.nativewind.output}');`, "utf8"), options);
+            const windowsCompatibleOutputPath = config.nativewind.output.replace(/\\/g, '\\\\');
+            return metro_transform_worker_1.default.transform(config, projectRoot, filename, Buffer.from(`require('${windowsCompatibleOutputPath}');`, "utf8"), options);
         }
         else {
             const css = config.nativewind.css[options.platform ?? "native"] ??

then add to package.json

{
  "scripts": {
    // ... your scripts
    "postinstall": "patch-package"
  }
  // ... rest of package.json properties
}

@Abu-ellil
Copy link
Copy Markdown

This is how it worked for me
Step 1: install PostCSS and the necessary plugins. You can do this using Yarn or npm:

Using Yarn

yarn add postcss postcss-cli tailwindcss autoprefixer cssnano --dev

Using npm

npm install postcss postcss-cli tailwindcss autoprefixer cssnano --save-dev

2: Create a file named postcss.config.js in the root of your project with the following content:

module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
require('cssnano')({
preset: 'default',
}),
],
};

Step 3: Create a script to build your CSS. In your package.json, add a script to run PostCSS:

"scripts": {
"build:css": "postcss global.css -o build.css"
}

yarn build:css

will find new file created called:
"build.css"

will use it in metro config

const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, { input: './build.css' });

@danstepanov
Copy link
Copy Markdown
Member

This file seems to no longer exist, I'll check on this with Mark

@danstepanov danstepanov added the help wanted Extra attention is needed label Mar 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.