Skip to content

Commit c550a62

Browse files
authored
[v4] Make CSS optimization and minification configurable (#13130)
* only run Lightning CSS when passing `--minify` to the CLI * only optimize the CSS when creating a production build * add `optimize` option to PostCSS plugin - The optimize option can be set to `true`, which will optimize (unnesting, adding browser prefixes, lowering values) and minify - The optimize option can also be set to `{ minify: false }`, which will optimize but not minify. * default `optimize` option to the true for `NODE_ENV=production` * add `--optimize` flag to CLI This will only optimize the CSS output without minification. * update `--minify` description * update changelog
1 parent 7132875 commit c550a62

File tree

5 files changed

+51
-16
lines changed

5 files changed

+51
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
### Added
1919

2020
- Add Android builds ([#13115](https://github.com/tailwindlabs/tailwindcss/pull/13115))
21+
- Make CSS optimization and minification configurable ([#13130](https://github.com/tailwindlabs/tailwindcss/pull/13130))
2122

2223
## [4.0.0-alpha.6] - 2024-03-07
2324

packages/@tailwindcss-cli/src/commands/build/index.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ export function options() {
4646
},
4747
'--minify': {
4848
type: 'boolean',
49-
description: 'Minify the output',
49+
description: 'Optimize and minify the output',
5050
alias: '-m',
5151
},
52+
'--optimize': {
53+
type: 'boolean',
54+
description: 'Optimize the output without minifying',
55+
},
5256
'--cwd': {
5357
type: 'string',
5458
description: 'The current working directory',
@@ -96,10 +100,15 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
96100
)
97101

98102
// Compile the input
99-
let result = optimizeCss(compile(input, candidates), {
100-
file: args['--input'] ?? 'input.css',
101-
minify: args['--minify'],
102-
})
103+
let result = compile(input, candidates)
104+
105+
// Optimize the output
106+
if (args['--minify'] || args['--optimize']) {
107+
result = optimizeCss(result, {
108+
file: args['--input'] ?? 'input.css',
109+
minify: args['--minify'] ?? false,
110+
})
111+
}
103112

104113
// Write the output
105114
if (args['--output']) {
@@ -184,10 +193,15 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
184193
}
185194

186195
// Compile the input
187-
let result = optimizeCss(compile(input, candidates), {
188-
file: args['--input'] ?? 'input.css',
189-
minify: args['--minify'],
190-
})
196+
let result = compile(input, candidates)
197+
198+
// Optimize the output
199+
if (args['--minify'] || args['--optimize']) {
200+
result = optimizeCss(result, {
201+
file: args['--input'] ?? 'input.css',
202+
minify: args['--minify'] ?? false,
203+
})
204+
}
191205

192206
// Write the output
193207
if (args['--output']) {

packages/@tailwindcss-postcss/src/index.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ beforeEach(async () => {
1818
})
1919

2020
test("`@import 'tailwindcss'` is replaced with the generated CSS", async () => {
21-
let processor = postcss([tailwindcss({ base: `${__dirname}/fixtures/example-project` })])
21+
let processor = postcss([
22+
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
23+
])
2224

2325
let result = await processor.process(`@import 'tailwindcss'`, { from: INPUT_CSS_PATH })
2426

@@ -47,7 +49,9 @@ test("`@import 'tailwindcss'` is replaced with the generated CSS", async () => {
4749
})
4850

4951
test('output is optimized by Lightning CSS', async () => {
50-
let processor = postcss([tailwindcss({ base: `${__dirname}/fixtures/example-project` })])
52+
let processor = postcss([
53+
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
54+
])
5155

5256
// `@apply` is used because Lightning is skipped if neither `@tailwind` nor
5357
// `@apply` is used.
@@ -82,7 +86,9 @@ test('output is optimized by Lightning CSS', async () => {
8286
})
8387

8488
test('@apply can be used without emitting the theme in the CSS file', async () => {
85-
let processor = postcss([tailwindcss({ base: `${__dirname}/fixtures/example-project` })])
89+
let processor = postcss([
90+
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
91+
])
8692

8793
// `@apply` is used because Lightning is skipped if neither `@tailwind` nor
8894
// `@apply` is used.
@@ -112,7 +118,7 @@ describe('processing without specifying a base path', () => {
112118
afterEach(() => unlink(filepath))
113119

114120
test('the current working directory is used by default', async () => {
115-
let processor = postcss([tailwindcss()])
121+
let processor = postcss([tailwindcss({ optimize: { minify: false } })])
116122

117123
let result = await processor.process(`@import "tailwindcss"`, { from: INPUT_CSS_PATH })
118124

packages/@tailwindcss-postcss/src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ import { compile, optimizeCss } from 'tailwindcss'
66
type PluginOptions = {
77
// The base directory to scan for class candidates.
88
base?: string
9+
10+
// Optimize the output CSS.
11+
optimize?: boolean | { minify?: boolean }
912
}
1013

1114
function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
1215
let base = opts.base ?? process.cwd()
16+
let optimize = opts.optimize ?? process.env.NODE_ENV === 'production'
1317

1418
return {
1519
postcssPlugin: 'tailwindcss-v4',
@@ -38,7 +42,13 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
3842

3943
function replaceCss(css: string) {
4044
root.removeAll()
41-
root.append(postcss.parse(optimizeCss(css), result.opts))
45+
let output = css
46+
if (optimize) {
47+
output = optimizeCss(output, {
48+
minify: typeof optimize === 'object' ? optimize.minify : false,
49+
})
50+
}
51+
root.append(postcss.parse(output, result.opts))
4252
}
4353

4454
// No `@tailwind` means we don't have to look for candidates

packages/@tailwindcss-vite/src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ export default function tailwindcss(): Plugin[] {
6161
}
6262

6363
function generateCss(css: string) {
64-
return optimizeCss(compile(css, Array.from(candidates)), { minify })
64+
return compile(css, Array.from(candidates))
65+
}
66+
67+
function generateOptimizedCss(css: string) {
68+
return optimizeCss(generateCss(css), { minify })
6569
}
6670

6771
// In dev mode, there isn't a hook to signal that we've seen all files. We use
@@ -168,7 +172,7 @@ export default function tailwindcss(): Plugin[] {
168172
rawSource instanceof Uint8Array ? new TextDecoder().decode(rawSource) : rawSource
169173

170174
if (source.includes('@tailwind')) {
171-
item.source = generateCss(source)
175+
item.source = generateOptimizedCss(source)
172176
}
173177
}
174178
},

0 commit comments

Comments
 (0)