Skip to content

Commit

Permalink
feat: add build.cssTarget option (#5132)
Browse files Browse the repository at this point in the history
fixes #4746
fixes #5070
fixes #4930
  • Loading branch information
haoqunjiang authored Oct 9, 2021
1 parent bbb4067 commit b17444f
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 1 deletion.
11 changes: 11 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,17 @@ export default defineConfig({

If disabled, all CSS in the entire project will be extracted into a single CSS file.

### build.cssTarget

- **Type:** `string | string[]`
- **Default:** the same as [`build.target`](/config/#build-target)

This options allows users to set a different browser target for CSS minification from the one used for JavaScript transpilation.

It should only be used when you are targeting a non-mainstream browser.
One example is Android WeChat WebView, which supports most modern JavaScript features but not the [`#RGBA` hexadecimal color notation in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#rgb_colors).
In this case, you need to set `build.cssTarget` to `chrome61` to prevent vite from transform `rgba()` colors into `#RGBA` hexadecimal notations.

### build.sourcemap

- **Type:** `boolean | 'inline' | 'hidden'`
Expand Down
11 changes: 11 additions & 0 deletions packages/playground/css/__tests__/css.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,14 @@ test('inlined', async () => {
// should not insert css
expect(await getColor('.inlined')).toBe('black')
})

test('minify css', async () => {
if (!isBuild) {
return
}

// should keep the rgba() syntax
const cssFile = findAssetFile(/index\.\w+\.css$/)
expect(cssFile).toMatch('rgba(')
expect(cssFile).not.toMatch('#ffff00b3')
})
2 changes: 2 additions & 0 deletions packages/playground/css/main.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import './minify.css'

import css from './imported.css'
text('.imported-css', css)

Expand Down
3 changes: 3 additions & 0 deletions packages/playground/css/minify.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.test-minify {
color: rgba(255, 255, 0, 0.7);
}
3 changes: 3 additions & 0 deletions packages/playground/css/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const path = require('path')
* @type {import('vite').UserConfig}
*/
module.exports = {
build: {
cssTarget: 'chrome61'
},
resolve: {
alias: {
'@': __dirname
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-legacy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ function viteLegacyPlugin(options = {}) {
if (!config.build) {
config.build = {}
}

if (!config.build.cssTarget) {
// Hint for esbuild that we are targeting legacy browsers when minifying CSS.
// Full CSS compat table available at https://github.com/evanw/esbuild/blob/78e04680228cf989bdd7d471e02bbc2c8d345dc9/internal/compat/css_table.go
// But note that only the `HexRGBA` feature affects the minify outcome.
// HSL & rebeccapurple values will be minified away regardless the target.
// So targeting `chrome61` suffices to fix the compatiblity issue.
config.build.cssTarget = 'chrome61'
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ export interface BuildOptions {
* @default true
*/
cssCodeSplit?: boolean
/**
* An optional separate target for CSS minification.
* As esbuild only supports configuring targets to mainstream
* browsers, users may need this option when they are targeting
* a niche browser that comes with most modern JavaScript features
* but has poor CSS support, e.g. Android WeChat WebView, which
* doesn't support the #RGBA syntax.
*/
cssTarget?: TransformOptions['target'] | false
/**
* If `true`, a separate sourcemap file will be created. If 'inline', the
* sourcemap will be appended to the resulting output file as data URI.
Expand Down Expand Up @@ -232,6 +241,7 @@ export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions {
assetsDir: 'assets',
assetsInlineLimit: 4096,
cssCodeSplit: !raw?.lib,
cssTarget: false,
sourcemap: false,
rollupOptions: {},
minify: raw?.ssr ? false : 'esbuild',
Expand Down Expand Up @@ -275,6 +285,10 @@ export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions {
resolved.target = 'es2019'
}

if (!resolved.cssTarget) {
resolved.cssTarget = resolved.target
}

// normalize false string into actual false
if ((resolved.minify as any) === 'false') {
resolved.minify = false
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ async function minifyCSS(css: string, config: ResolvedConfig) {
const { code, warnings } = await transform(css, {
loader: 'css',
minify: true,
target: config.build.target || undefined
target: config.build.cssTarget || undefined
})
if (warnings.length) {
const msgs = await formatMessages(warnings, { kind: 'warning' })
Expand Down

0 comments on commit b17444f

Please sign in to comment.