References https://github.com/tailwindlabs/tailwindcss/pull/19391. References https://github.com/tailwindlabs/tailwindcss/pull/16274. Right now, when using the standalone build of the TailwindCSS CLI, you cannot use a custom `NODE_PATH`, but you can when using it via Node.js directly. A custom NODE_PATH allows you to resolve imports from multiple locations. For example, in [Phoenix LiveView](https://github.com/phoenixframework/phoenix_live_view/), we have a feature where you can write scripts in templates that we extract at compile time to a custom folder and users can import those in their application bundle by saying ```javascript import { hooks as colocatedHooks } from "phoenix-colocated/my_app" ``` where the "phoenix-colocated" folder lives in a different location than the usual `node_modules` folder. This works fine with the default esbuild setup, as it respects `NODE_PATH`, so we can pass it a custom location. We want to also support colocating CSS in templates soon, but the same approach doesn't work with the standalone Tailwind CLI we ship with default Phoenix projects. It works when running Tailwind through Node.js, but we don't want to tell users they need to install it, just to use the feature. This patch changes the lookup logic for the standalone CLI to also account for `NODE_PATH`. Note that you can pass multiple paths, that are split according the the OS PATH separator. --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import { createHash } from 'node:crypto'
|
|
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
import * as path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
|
|
// Workaround for Bun binary downloads failing on Windows CI when
|
|
// USERPROFILE is passed through by Turborepo.
|
|
//
|
|
// Unfortunately, setting this at runtime doesn't appear to work so we have to
|
|
// spawn a new process without the env var.
|
|
if (process.env.NESTED_BUILD !== '1' && process.env.USERPROFILE && process.env.USERPROFILE !== '') {
|
|
let result = await Bun.$`bun ${fileURLToPath(import.meta.url)}`.env({
|
|
USERPROFILE: '',
|
|
NESTED_BUILD: '1',
|
|
})
|
|
|
|
process.exit(result.exitCode)
|
|
}
|
|
|
|
// We use baseline builds for all x64 platforms to ensure compatibility with
|
|
// older hardware.
|
|
let builds: { target: Bun.Build.Target; name: string }[] = [
|
|
{ name: 'tailwindcss-linux-arm64', target: 'bun-linux-arm64' },
|
|
{ name: 'tailwindcss-linux-arm64-musl', target: 'bun-linux-arm64-musl' },
|
|
// @ts-expect-error: Either the types are wrong or the runtime needs to be updated
|
|
// to accept a `-glibc` at the end like the types suggest.
|
|
{ name: 'tailwindcss-linux-x64', target: 'bun-linux-x64-baseline' },
|
|
{ name: 'tailwindcss-linux-x64-musl', target: 'bun-linux-x64-baseline-musl' },
|
|
{ name: 'tailwindcss-macos-arm64', target: 'bun-darwin-arm64' },
|
|
{ name: 'tailwindcss-macos-x64', target: 'bun-darwin-x64-baseline' },
|
|
{ name: 'tailwindcss-windows-x64.exe', target: 'bun-windows-x64-baseline' },
|
|
]
|
|
|
|
let summary: { target: Bun.Build.Target; name: string; sum: string }[] = []
|
|
|
|
// Build platform binaries and checksum them.
|
|
let start = process.hrtime.bigint()
|
|
for (let { target, name } of builds) {
|
|
let outfile = path.resolve(__dirname, `../dist/${name}`)
|
|
|
|
let result = await Bun.build({
|
|
entrypoints: ['./src/index.ts'],
|
|
target: 'node',
|
|
minify: {
|
|
whitespace: false,
|
|
syntax: true,
|
|
identifiers: false,
|
|
keepNames: true,
|
|
},
|
|
|
|
define: {
|
|
// This ensures only necessary binaries are bundled for linux targets
|
|
// It reduces binary size since no runtime selection is necessary
|
|
'process.env.PLATFORM_LIBC': JSON.stringify(target.includes('-musl') ? 'musl' : 'glibc'),
|
|
|
|
// This prevents the WASI build from being bundled with the binary
|
|
'process.env.NAPI_RS_FORCE_WASI': JSON.stringify(''),
|
|
|
|
// This simplifies the Oxide loading code a small amount
|
|
'process.env.NAPI_RS_NATIVE_LIBRARY_PATH': JSON.stringify(''),
|
|
},
|
|
|
|
compile: {
|
|
target,
|
|
outfile,
|
|
|
|
// Disable .env loading
|
|
autoloadDotenv: false,
|
|
|
|
// Disable bunfig.toml loading
|
|
autoloadBunfig: false,
|
|
},
|
|
|
|
plugins: [
|
|
{
|
|
name: 'tailwindcss-plugin',
|
|
setup(build) {
|
|
build.onLoad({ filter: /tailwindcss-oxide\.wasi\.cjs$/ }, async (args) => {
|
|
return { contents: '' }
|
|
})
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
let entry = result.outputs.find((output) => output.kind === 'entry-point')
|
|
if (!entry) throw new Error(`Build failed for ${target}`)
|
|
|
|
let content = await readFile(outfile)
|
|
|
|
summary.push({
|
|
target,
|
|
name,
|
|
sum: createHash('sha256').update(content).digest('hex'),
|
|
})
|
|
}
|
|
|
|
await mkdir(path.resolve(__dirname, '../dist'), { recursive: true })
|
|
|
|
// Write the checksums to a file
|
|
let sumsFile = path.resolve(__dirname, '../dist/sha256sums.txt')
|
|
let sums = summary.map(({ name, sum }) => `${sum} ./${name}`)
|
|
|
|
await writeFile(sumsFile, sums.join('\n') + '\n')
|
|
|
|
console.table(summary.map(({ target, sum }) => ({ target, sum })))
|
|
|
|
let elapsed = process.hrtime.bigint() - start
|
|
console.log(`Build completed in ${(Number(elapsed) / 1e6).toFixed(0)}ms`)
|