mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Fix native ESM config loading in v3 (#18938)
Unfortunately for backwards compatibility purposes (with `loadConfig` at least) we can't switch things to use `import(…)` because there's baked in knowledge that the config is loaded synchronously for v3. This PR does two things: - Defers to `require(…)` which allows newer versions that support `require(esm)` to work natively. This works around the need to switch to `import(…)` for those versions. - Allows newer versions of `postcss-load-config` enabling better ESM+TypeScript support for PostCSS configs in the CLI. We support v4, v5, and v6 of `postcss-load-config` simultaneously so any of those versions should work. I've verified that newer node versions seem to install v6 while earlier ones like Node v14 install v4 of `postcss-load-config`. So this should be a backwards compatible change. - [x] needs tests for `import.meta.resolve(…)` - [x] needs tests for ESM postcss configs Fixes #14152 Fixes #14423
This commit is contained in:
parent
ff52f8caf2
commit
ba55a445cd
2
.github/workflows/ci-stable.yml
vendored
2
.github/workflows/ci-stable.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14, 18]
|
||||
node-version: [14, 18, 20, 22, 24]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14, 18]
|
||||
node-version: [14, 18, 20, 22, 24]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
2
.github/workflows/integration-tests.yml
vendored
2
.github/workflows/integration-tests.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
- vite
|
||||
- webpack-4
|
||||
- webpack-5
|
||||
node-version: [18]
|
||||
node-version: [18, 20]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
|
||||
@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Improve support for raw `supports-[…]` queries in arbitrary values ([#13605](https://github.com/tailwindlabs/tailwindcss/pull/13605))
|
||||
- Fix `require.cache` error when loaded through a TypeScript file in Node 22.18+ ([#18665](https://github.com/tailwindlabs/tailwindcss/pull/18665))
|
||||
- Support `import.meta.resolve(…)` in configs for new enough Node.js versions ([#18938](https://github.com/tailwindlabs/tailwindcss/pull/18938))
|
||||
- Allow using newer versions of `postcss-load-config` for better ESM and TypeScript PostCSS config support with the CLI ([#18938](https://github.com/tailwindlabs/tailwindcss/pull/18938))
|
||||
|
||||
## [3.4.17] - 2024-12-17
|
||||
|
||||
|
||||
@ -207,6 +207,52 @@ describe('Build command', () => {
|
||||
)
|
||||
})
|
||||
|
||||
test('configs support import.meta', async () => {
|
||||
// Skip this test in Node 18 as this only works with
|
||||
// `require(esm)` in Node 20.19+
|
||||
if (process.versions.node.startsWith('18.')) {
|
||||
expect(true).toBe(true)
|
||||
return
|
||||
}
|
||||
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let customConfig = `
|
||||
console.log(import.meta.url)
|
||||
console.log(import.meta.resolve('./tailwind.config.mjs'))
|
||||
export default ${JSON.stringify(
|
||||
{
|
||||
content: ['./src/index.html'],
|
||||
theme: {
|
||||
extend: {
|
||||
fontWeight: {
|
||||
bold: 'BOLD',
|
||||
},
|
||||
},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
},
|
||||
null,
|
||||
2
|
||||
)}
|
||||
`
|
||||
|
||||
await writeInputFile('../tailwind.config.mjs', customConfig)
|
||||
|
||||
await $(`${EXECUTABLE} --output ./dist/main.css --config ./tailwind.config.mjs`)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: BOLD;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
test('--content', async () => {
|
||||
await writeInputFile('other.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
@ -391,6 +437,79 @@ describe('Build command', () => {
|
||||
expect(contents).toContain(`/*# sourceMappingURL`)
|
||||
})
|
||||
|
||||
test('--postcss supports ESM configs', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let customConfig = javascript`
|
||||
import * as path from 'path'
|
||||
import { createRequire } from 'module'
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
export default {
|
||||
map: { inline: true },
|
||||
plugins: [
|
||||
function tailwindcss() {
|
||||
return require(path.resolve('..', '..'))
|
||||
},
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
await removeFile('./postcss.config.js')
|
||||
await writeInputFile('../postcss.config.mjs', customConfig)
|
||||
|
||||
await $(`${EXECUTABLE} --output ./dist/main.css --postcss`)
|
||||
|
||||
let contents = await readOutputFile('main.css')
|
||||
|
||||
expect(contents).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
expect(contents).toContain(`/*# sourceMappingURL`)
|
||||
})
|
||||
|
||||
test('--postcss supports TS configs', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let customConfig = javascript`
|
||||
import * as path from 'path'
|
||||
import { createRequire } from 'module'
|
||||
import type { AcceptedPlugin } from 'postcss'
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
export default {
|
||||
map: { inline: true },
|
||||
plugins: [
|
||||
function tailwindcss() {
|
||||
return require(path.resolve('..', '..'))
|
||||
} as AcceptedPlugin,
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
await removeFile('./postcss.config.js')
|
||||
await writeInputFile('../postcss.config.ts', customConfig)
|
||||
|
||||
await $(`${EXECUTABLE} --output ./dist/main.css --postcss`)
|
||||
|
||||
let contents = await readOutputFile('main.css')
|
||||
|
||||
expect(contents).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
expect(contents).toContain(`/*# sourceMappingURL`)
|
||||
})
|
||||
|
||||
test('postcss-import is supported by default', async () => {
|
||||
cleanupFile('src/test.css')
|
||||
|
||||
|
||||
54
package-lock.json
generated
54
package-lock.json
generated
@ -17,7 +17,7 @@
|
||||
"fast-glob": "^3.3.2",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"jiti": "^1.21.6",
|
||||
"jiti": "^1.21.7",
|
||||
"lilconfig": "^3.1.3",
|
||||
"micromatch": "^4.0.8",
|
||||
"normalize-path": "^3.0.0",
|
||||
@ -26,7 +26,7 @@
|
||||
"postcss": "^8.4.47",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-js": "^4.0.1",
|
||||
"postcss-load-config": "^4.0.2",
|
||||
"postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
|
||||
"postcss-nested": "^6.2.0",
|
||||
"postcss-selector-parser": "^6.1.2",
|
||||
"resolve": "^1.22.8",
|
||||
@ -5446,9 +5446,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "1.21.6",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
|
||||
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
|
||||
"version": "1.21.7",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
||||
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
@ -6518,9 +6518,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-load-config": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
|
||||
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
|
||||
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -6533,21 +6533,28 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lilconfig": "^3.0.0",
|
||||
"yaml": "^2.3.4"
|
||||
"lilconfig": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jiti": ">=1.21.0",
|
||||
"postcss": ">=8.0.9",
|
||||
"ts-node": ">=9.0.0"
|
||||
"tsx": "^4.8.1",
|
||||
"yaml": "^2.4.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"jiti": {
|
||||
"optional": true
|
||||
},
|
||||
"postcss": {
|
||||
"optional": true
|
||||
},
|
||||
"ts-node": {
|
||||
"tsx": {
|
||||
"optional": true
|
||||
},
|
||||
"yaml": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
@ -8186,6 +8193,8 @@
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
||||
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
@ -11832,9 +11841,9 @@
|
||||
}
|
||||
},
|
||||
"jiti": {
|
||||
"version": "1.21.6",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
|
||||
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w=="
|
||||
"version": "1.21.7",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
||||
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
@ -12464,12 +12473,11 @@
|
||||
}
|
||||
},
|
||||
"postcss-load-config": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
|
||||
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
|
||||
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
|
||||
"requires": {
|
||||
"lilconfig": "^3.0.0",
|
||||
"yaml": "^2.3.4"
|
||||
"lilconfig": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"postcss-merge-longhand": {
|
||||
@ -13506,7 +13514,9 @@
|
||||
"yaml": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
||||
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ=="
|
||||
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.7.2",
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
"fast-glob": "^3.3.2",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"jiti": "^1.21.6",
|
||||
"jiti": "^1.21.7",
|
||||
"lilconfig": "^3.1.3",
|
||||
"micromatch": "^4.0.8",
|
||||
"normalize-path": "^3.0.0",
|
||||
@ -81,7 +81,7 @@
|
||||
"postcss": "^8.4.47",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-js": "^4.0.1",
|
||||
"postcss-load-config": "^4.0.2",
|
||||
"postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
|
||||
"postcss-nested": "^6.2.0",
|
||||
"postcss-selector-parser": "^6.1.2",
|
||||
"resolve": "^1.22.8",
|
||||
|
||||
@ -43,10 +43,13 @@ async function loadPostCssPlugins(customPostCssPath) {
|
||||
config.plugins = []
|
||||
}
|
||||
|
||||
// We have to await these because in v5 and v6 of postcss-load-config
|
||||
// these functions return promises while they don't in v4. Awaiting a
|
||||
// non-promise is basically a no-op so this is safe to do.
|
||||
return {
|
||||
file,
|
||||
plugins: loadPlugins(config, file),
|
||||
options: loadOptions(config, file),
|
||||
plugins: await loadPlugins(config, file),
|
||||
options: await loadOptions(config, file),
|
||||
}
|
||||
})()
|
||||
: await postcssrc()
|
||||
|
||||
@ -35,23 +35,8 @@ export function loadConfig(path: string): Config {
|
||||
let config = (function () {
|
||||
if (!path) return {}
|
||||
|
||||
// Always use jiti for now. There is a a bug that occurs in Node v22.12+
|
||||
// where imported files return invalid results
|
||||
return lazyJiti()(path)
|
||||
|
||||
// Always use jiti for ESM or TS files
|
||||
if (
|
||||
path &&
|
||||
(path.endsWith('.mjs') ||
|
||||
path.endsWith('.ts') ||
|
||||
path.endsWith('.cts') ||
|
||||
path.endsWith('.mts'))
|
||||
) {
|
||||
return lazyJiti()(path)
|
||||
}
|
||||
|
||||
try {
|
||||
return path ? require(path) : {}
|
||||
return require(path)
|
||||
} catch {
|
||||
return lazyJiti()(path)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user