Skip to content

Commit

Permalink
fix: get nativewind css injection and css to js working, breaking on …
Browse files Browse the repository at this point in the history
…bundling nativewind properly not transforming wrap-jsx and other require calls using interop
  • Loading branch information
natew committed Jan 14, 2025
1 parent 81c6080 commit bc71952
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 8 deletions.
2 changes: 1 addition & 1 deletion apps/onestack.dev/data/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ We set up `alias` based on environment:

- `react-native` => `react-native-web` for web environments

We also detect if you have a PostCSS config file (js, ts, or json) and set the `css` config:
We also detect if you have a PostCSS config file (js, ts, or json) and set the `css`. The internal logic is something like:

```tsx
{
Expand Down
4 changes: 4 additions & 0 deletions examples/one-tailwind/app/base.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.test {
background-color: red;
}
2 changes: 2 additions & 0 deletions examples/one-tailwind/postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
console.log('using postcss?')

export default {
plugins: {
tailwindcss: {},
Expand Down
2 changes: 1 addition & 1 deletion examples/one-tailwind/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export default {
theme: {
extend: {},
},
resets: [require('nativewind/preset')],
presets: [require('nativewind/preset')],
plugins: [require('tailwindcss-animate'), require('tailwindcss-motion')],
}
71 changes: 65 additions & 6 deletions packages/compiler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
import { resolvePath } from '@vxrn/utils'
import { readFileSync } from 'node:fs'
import { readFile } from 'node:fs/promises'
import { extname, join } from 'node:path'
import { extname, join, relative, resolve, sep } from 'node:path'
import type { PluginOption, UserConfig } from 'vite'
import { debug, runtimePublicPath, validParsers } from './constants'
import { getBabelOptions, transformBabel } from './transformBabel'
import { transformSWC } from './transformSWC'
import type { Environment, GetTransformProps, Options } from './types'
import { cssToReactNativeRuntime } from 'react-native-css-interop/css-to-rn/index.js'
import { configuration } from './configure'
import type { OutputChunk } from 'rollup'

export * from './configure'
export * from './transformBabel'
Expand Down Expand Up @@ -43,6 +44,12 @@ export async function createVXRNCompilerPlugin(

const reactForRNVersion = reactVersion.split('.')[0] as '18' | '19'

const cssTransformCache = new Map<string, string>()

// fix so we can align the diff between vite and rollup id (rollup resolves from root monorepo)
const rollupPath = resolvePath('rollup')
const rollupNodeMods = rollupPath.slice(0, rollupPath.indexOf(sep + 'node_modules'))

return [
{
name: 'one:compiler-resolve-refresh-runtime',
Expand All @@ -57,19 +64,59 @@ export async function createVXRNCompilerPlugin(

{
name: `one:compiler-css-to-js`,
enforce: 'post',
transform(code, id) {

transform(codeIn, id) {
const environment = getEnvName(this.environment.name)
if (configuration.enableNativeCSS && (environment === 'ios' || environment === 'android')) {
if (extname(id) === '.css') {
const data = JSON.stringify(cssToReactNativeRuntime(code, { inlineRem: 16 }))
const data = JSON.stringify(cssToReactNativeRuntime(codeIn, { inlineRem: 16 }))
// TODO were hardcoding the require id we bundle as: nativewind/dist/index.js
// could at least resolve this using resolvePath
const code = `require("nativewind/dist/index.js").StyleSheet.registerCompiled(${data})`
const newId = `${id}.js`

// rollup uses relative to its node_modules parent dir, vite here uses absolute
const cssId = newId.replace(rollupNodeMods + sep, '')
cssTransformCache.set(cssId, code)

return {
code: `require("nativewind").StyleSheet.registerCompiled(${data})`,
code,
id: newId,
map: null,
}
}
}
},

generateBundle(_, bundle) {
const environment = getEnvName(this.environment.name)

if (configuration.enableNativeCSS && (environment === 'ios' || environment === 'android')) {
const rootJSName = Object.keys(bundle).find((i) => {
const chunk = bundle[i]
return chunk.type == 'chunk' && chunk.fileName.match(/.[cm]?js(?:\?.+)?$/) != null
})
if (!rootJSName) {
throw new Error(`Can't find root js, internal one error`)
}

const rootJS = bundle[rootJSName] as OutputChunk

const cssAssets = Object.keys(bundle).filter((i) =>
bundle[i].fileName.endsWith('.css.js')
)

for (const name of cssAssets) {
delete bundle[name]

const jsCSS = cssTransformCache.get(name)
rootJS.code = `
${jsCSS}
${rootJS.code}
`
}
}
},
},

{
Expand Down Expand Up @@ -100,6 +147,19 @@ export async function createVXRNCompilerPlugin(
order: 'pre',
async handler(codeIn, _id) {
let code = codeIn
const environment = getEnvName(this.environment.name)

if (
configuration.enableNativewind &&
(environment === 'ios' || environment === 'android') &&
// it has a hidden special character
_id.includes('one-entry-native')
) {
// ensure we have nativewind import
return `import * as x from 'nativewind'
console.log('got nativewind', typeof x)
${code}`
}

const shouldDebug =
process.env.NODE_ENV === 'development' && codeIn.startsWith('// debug')
Expand All @@ -120,7 +180,6 @@ export async function createVXRNCompilerPlugin(
return
}

const environment = getEnvName(this.environment.name)
const production = process.env.NODE_ENV === 'production'

let id = _id.split('?')[0]
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/transformSWC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ function wrapSourceInRefreshRuntimeNative(
options: Options,
shouldHMR: boolean
) {
// do we need this vite-native-client here? cant we do this on its own?
const prefixCode =
options.mode === 'build'
? `
Expand Down

0 comments on commit bc71952

Please sign in to comment.