Skip to content

Commit

Permalink
fix(vite): does not found CSS placeholder in the generated chunks (#1400
Browse files Browse the repository at this point in the history
)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
Dunqing and antfu committed Aug 11, 2022
1 parent a5f6d96 commit c2cdbd2
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 18 deletions.
39 changes: 23 additions & 16 deletions packages/vite/src/modes/global/build.ts
@@ -1,5 +1,5 @@
import { resolve } from 'path'
import type { Plugin } from 'vite'
import type { Plugin, ResolvedConfig } from 'vite'
import type { GenerateResult, UnocssPluginContext } from '@unocss/core'
import {
HASH_PLACEHOLDER_RE, LAYER_MARK_ALL, LAYER_PLACEHOLDER_RE,
Expand All @@ -18,6 +18,7 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get
const vfsLayers = new Set<string>()
const layerImporterMap = new Map<string, string>()
let tasks: Promise<any>[] = []
let viteConfig: ResolvedConfig

// use maps to differentiate multiple build. using outDir as key
const cssPostPlugins = new Map<string | undefined, Plugin | undefined>()
Expand Down Expand Up @@ -143,14 +144,17 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get
apply(options, { command }) {
return command === 'build' && !options.build?.ssr
},
configResolved(config) {
viteConfig = config
},
enforce: 'post',
// rewrite the css placeholders
async generateBundle(options, bundle) {
const files = Object.entries(bundle)
const cssFiles = files.filter(i => i[0].endsWith('.css'))
const jsFiles = files.filter(i => i[0].endsWith('.js'))
const checkJs = ['umd', 'amd', 'iife'].includes(options.format)
const files = Object.keys(bundle)
.filter(i => i.endsWith('.css') || (checkJs && i.endsWith('.js')))

if (!cssFiles.length && !jsFiles.length)
if (!files.length)
return

if (!vfsLayers.size) {
Expand All @@ -162,23 +166,20 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get
const result = await generateAll()
let replaced = false

for (const [, chunk] of cssFiles) {
for (const file of files) {
const chunk = bundle[file]

if (chunk.type === 'asset' && typeof chunk.source === 'string') {
const css = chunk.source
.replace(HASH_PLACEHOLDER_RE, '')
chunk.source = await replaceAsync(css, LAYER_PLACEHOLDER_RE, async (_, __, layer) => {
replaced = true
const css = layer === LAYER_MARK_ALL
return await applyCssTransform(layer === LAYER_MARK_ALL
? result.getLayers(undefined, Array.from(vfsLayers))
: result.getLayer(layer) || ''
return await applyCssTransform(css, `${chunk.fileName}.css`, options.dir)
: result.getLayer(layer) || '', `${chunk.fileName}.css`, options.dir)
})
}
}

// replace the hash in the js files (iife or umd bundle)
for (const [, chunk] of jsFiles) {
if (chunk.type === 'chunk' && typeof chunk.code === 'string') {
else if (chunk.type === 'chunk' && typeof chunk.code === 'string') {
const js = chunk.code
.replace(HASH_PLACEHOLDER_RE, '')
chunk.code = await replaceAsync(js, LAYER_PLACEHOLDER_RE, async (_, __, layer) => {
Expand All @@ -193,8 +194,14 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get
}
}

if (!replaced)
this.error(new Error('[unocss] does not found CSS placeholder in the generated chunks,\nthis is likely an internal bug of unocss vite plugin'))
if (!replaced) {
let msg = '[unocss] does not found CSS placeholder in the generated chunks'
if (viteConfig.build.lib && checkJs)
msg += '\nIt seems you are building in library mode, it\'s recommanded to set `build.cssCodeSplit` to true.\nSee https://github.com/vitejs/vite/issues/1579'
else
msg += '\nThis is likely an internal bug of unocss vite plugin'
this.error(new Error(msg))
}
},
},
]
Expand Down
40 changes: 38 additions & 2 deletions test/vite.test.ts → test/fixtures.test.ts
Expand Up @@ -4,8 +4,8 @@ import { describe, expect, it } from 'vitest'
import fs from 'fs-extra'
import fg from 'fast-glob'

describe('vite', () => {
it('build', async () => {
describe.concurrent('fixtures', () => {
it('vite client', async () => {
const root = resolve(__dirname, 'fixtures/vite')
await fs.emptyDir(join(root, 'dist'))
await build({
Expand Down Expand Up @@ -41,4 +41,40 @@ describe('vite', () => {
// transformer-compile-class
expect(js).contains('uno-tacwqa')
})

it('vite lib', async () => {
const root = resolve(__dirname, 'fixtures/vite-lib')
await fs.emptyDir(join(root, 'dist'))
await build({
root,
logLevel: 'warn',
build: {
sourcemap: true,
},
})

const files = await fg('dist/**/*.{umd,iife}.js', { cwd: root, absolute: true })

expect(files).toHaveLength(2)

for (const path of files) {
const code = await fs.readFile(path, 'utf-8')
// basic
expect(code).contains('.text-red')
// transformer-variant-group
expect(code).contains('.text-sm')
// transformer-compile-class
expect(code).contains('.uno-tacwqa')
// transformer-directives
expect(code).not.contains('@apply')
expect(code).not.contains('--at-apply')
expect(code).contains('gap:.25rem')
expect(code).contains('gap:.5rem')

// transformer-variant-group
expect(code).contains('text-sm')
// transformer-compile-class
expect(code).contains('uno-tacwqa')
}
})
})
12 changes: 12 additions & 0 deletions test/fixtures/vite-lib/index.html
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
8 changes: 8 additions & 0 deletions test/fixtures/vite-lib/lib/main.css
@@ -0,0 +1,8 @@
.foo {
@apply flex;
@apply gap-1;
}

.bar {
--at-apply: gap-2;
}
19 changes: 19 additions & 0 deletions test/fixtures/vite-lib/lib/main.ts
@@ -0,0 +1,19 @@
import '@unocss/reset/tailwind.css'
import './main.css'
import 'uno.css'

// @unocss-include
const html = String.raw
document.querySelector<HTMLDivElement>('#app')!.innerHTML = html`
<div class="font-sans p4">
<p class="text-red">
Red
</p>
<p class=":uno: text-green text-xl">
Green Large
</p>
<p class="text-(blue sm)">
Blue Small
</p>
</div>
`
8 changes: 8 additions & 0 deletions test/fixtures/vite-lib/package.json
@@ -0,0 +1,8 @@
{
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
22 changes: 22 additions & 0 deletions test/fixtures/vite-lib/unocss.config.ts
@@ -0,0 +1,22 @@
import {
defineConfig,
presetAttributify,
presetIcons,
presetUno,
transformerCompileClass,
transformerDirectives,
transformerVariantGroup,
} from 'unocss'

export default defineConfig({
presets: [
presetAttributify(),
presetUno(),
presetIcons(),
],
transformers: [
transformerCompileClass(),
transformerVariantGroup(),
transformerDirectives(),
],
})
23 changes: 23 additions & 0 deletions test/fixtures/vite-lib/vite.config.ts
@@ -0,0 +1,23 @@
import { resolve } from 'path'
import { defineConfig } from 'vite'
import UnoCSS from '@unocss/vite'

export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'lib/main.ts'),
name: 'MyLib',
fileName: 'my-lib',
formats: [
'cjs',
'es',
'iife',
'umd',
],
},
cssCodeSplit: true,
},
plugins: [
UnoCSS(),
],
})

0 comments on commit c2cdbd2

Please sign in to comment.