11/* eslint-disable */
22import { versions } from "node:process" ;
3- import { sep } from "node:path" ;
3+ import { dirname , relative , sep } from "node:path" ;
44
55import connect from "connect" ;
66import type { MetroConfig } from "metro-config" ;
77
88import { compile } from "../compiler/compiler" ;
99import { setupTypeScript } from "./typescript" ;
10- import { getInjectionCode } from "./injection-code" ;
10+ import { getNativeInjectionCode , getWebInjectionCode } from "./injection-code" ;
1111import { nativeResolver , webResolver } from "./resolver" ;
1212
1313export interface WithReactNativeCSSOptions {
@@ -85,23 +85,43 @@ export function withReactNativeCSS<
8585 if ( ! bundler . __react_native_css__patched ) {
8686 bundler . __react_native_css__patched = true ;
8787
88- const cssFiles = new Map ( ) ;
88+ const nativeCSSFiles = new Map ( ) ;
89+ const webCSSFiles = new Set < string > ( ) ;
8990
90- const injectionCommonJS = require . resolve ( "../runtime/native/metro" ) ;
91- const injectionFilePaths = [
91+ const nativeInjectionPath = require . resolve (
92+ "../runtime/native/metro" ,
93+ ) ;
94+ const nativeInjectionFilepaths = [
9295 // CommonJS
93- injectionCommonJS ,
96+ nativeInjectionPath ,
9497 // ES Module
95- injectionCommonJS . replace ( `dist${ sep } commonjs` , `dist${ sep } module` ) ,
98+ nativeInjectionPath . replace (
99+ `dist${ sep } commonjs` ,
100+ `dist${ sep } module` ,
101+ ) ,
96102 // TypeScript
97- injectionCommonJS
103+ nativeInjectionPath
104+ . replace ( `dist${ sep } commonjs` , `src` )
105+ . replace ( ".js" , ".ts" ) ,
106+ ] ;
107+
108+ const webInjectionPath = require . resolve ( "../runtime/web/metro" ) ;
109+ const webInjectionFilepaths = [
110+ // CommonJS
111+ webInjectionPath ,
112+ // ES Module
113+ webInjectionPath . replace ( `dist${ sep } commonjs` , `dist${ sep } module` ) ,
114+ // TypeScript
115+ webInjectionPath
98116 . replace ( `dist${ sep } commonjs` , `src` )
99117 . replace ( ".js" , ".ts" ) ,
100118 ] ;
101119
102120 // Keep the original
103121 const transformFile = bundler . transformFile . bind ( bundler ) ;
104122
123+ const watcher = bundler . getWatcher ( ) ;
124+
105125 // Patch with our functionality
106126 bundler . transformFile = async function (
107127 filePath : string ,
@@ -110,53 +130,80 @@ export function withReactNativeCSS<
110130 ) {
111131 const isCss = / \. ( s ? c s s | s a s s ) $ / . test ( filePath ) ;
112132
113- // Handle CSS files on native platforms
114- if ( isCss && transformOptions . platform !== "web" ) {
115- const real = await transformFile (
116- filePath ,
117- {
118- ...transformOptions ,
119- // Force the platform to web for CSS files
120- platform : "web" ,
121- // Let the transformer know that we will handle compilation
122- customTransformOptions : {
123- ...transformOptions . customTransformOptions ,
124- reactNativeCSSCompile : false ,
125- } ,
126- } ,
127- fileBuffer ,
128- ) ;
129-
130- const lastTransform = cssFiles . get ( filePath ) ;
131- const last = lastTransform ?. [ 0 ] ;
132- const next = real . output [ 0 ] . data . css . code . toString ( ) ;
133-
134- // The CSS file has changed, we need to recompile the injection file
135- if ( next !== last ) {
136- cssFiles . set ( filePath , [ next , compile ( next , { } ) ] ) ;
137-
138- bundler . getWatcher ( ) . emit ( "change" , {
139- eventsQueue : injectionFilePaths . map ( ( filePath ) => ( {
140- filePath,
141- metadata : {
142- modifiedTime : Date . now ( ) ,
143- size : 1 , // Can be anything
144- type : "virtual" , // Can be anything
133+ if ( transformOptions . platform === "web" ) {
134+ if ( isCss ) {
135+ webCSSFiles . add ( filePath ) ;
136+ } else if ( webInjectionFilepaths . includes ( filePath ) ) {
137+ fileBuffer = getWebInjectionCode ( Array . from ( webCSSFiles ) ) ;
138+ }
139+
140+ return transformFile ( filePath , transformOptions , fileBuffer ) ;
141+ } else {
142+ // Handle CSS files on native platforms
143+ if ( isCss ) {
144+ const webTransform = await transformFile (
145+ filePath ,
146+ {
147+ ...transformOptions ,
148+ // Force the platform to web for CSS files
149+ platform : "web" ,
150+ // Let the transformer know that we will handle compilation
151+ customTransformOptions : {
152+ ...transformOptions . customTransformOptions ,
153+ reactNativeCSSCompile : false ,
145154 } ,
146- type : "change" ,
147- } ) ) ,
148- } ) ;
155+ } ,
156+ fileBuffer ,
157+ ) ;
158+
159+ const lastTransform = nativeCSSFiles . get ( filePath ) ;
160+ const last = lastTransform ?. [ 0 ] ;
161+ const next = webTransform . output [ 0 ] . data . css . code . toString ( ) ;
162+
163+ // The CSS file has changed, we need to recompile the injection file
164+ if ( next !== last ) {
165+ nativeCSSFiles . set ( filePath , [ next , compile ( next , { } ) ] ) ;
166+
167+ watcher . emit ( "change" , {
168+ eventsQueue : nativeInjectionFilepaths . map ( ( filePath ) => ( {
169+ filePath,
170+ metadata : {
171+ modifiedTime : Date . now ( ) ,
172+ size : 1 , // Can be anything
173+ type : "virtual" , // Can be anything
174+ } ,
175+ type : "change" ,
176+ } ) ) ,
177+ } ) ;
178+ }
179+
180+ const nativeTransform = await transformFile (
181+ filePath ,
182+ transformOptions ,
183+ fileBuffer ,
184+ ) ;
185+
186+ // Tell Expo to skip caching this file
187+ nativeTransform . output [ 0 ] . data . css = {
188+ skipCache : true ,
189+ // Expo requires a `code` property
190+ code : "" ,
191+ } ;
192+
193+ return nativeTransform ;
194+ } else if ( nativeInjectionFilepaths . includes ( filePath ) ) {
195+ // If this is the injection file, we to swap its content with the
196+ // compiled CSS files
197+ fileBuffer = getNativeInjectionCode (
198+ Array . from ( nativeCSSFiles . keys ( ) ) . map ( ( key ) =>
199+ relative ( dirname ( filePath ) , key ) ,
200+ ) ,
201+ Array . from ( nativeCSSFiles . values ( ) ) . map ( ( [ , value ] ) => value ) ,
202+ ) ;
149203 }
150- } else if ( injectionFilePaths . includes ( filePath ) ) {
151- // If this is the injection file, we to swap its content with the
152- // compiled CSS files
153- fileBuffer = getInjectionCode (
154- "./api" ,
155- Array . from ( cssFiles . values ( ) ) . map ( ( [ , value ] ) => value ) ,
156- ) ;
157- }
158204
159- return transformFile ( filePath , transformOptions , fileBuffer ) ;
205+ return transformFile ( filePath , transformOptions , fileBuffer ) ;
206+ }
160207 } ;
161208 }
162209
0 commit comments