From 413f6b77aee57eb235169ba5bd2048152e530073 Mon Sep 17 00:00:00 2001 From: sibbng Date: Mon, 5 Dec 2022 03:25:32 +0300 Subject: [PATCH 1/3] feat(vite): add `watchExternal` option --- examples/astro-vue/.gitignore | 20 +++++ examples/astro-vue/astro.config.ts | 10 +++ examples/astro-vue/package.json | 19 +++++ examples/astro-vue/pnpm-workspace.yaml | 0 examples/astro-vue/src/components/Card.astro | 21 +++++ examples/astro-vue/src/components/Example.vue | 11 +++ examples/astro-vue/src/env.d.ts | 1 + examples/astro-vue/src/layouts/Layout.astro | 19 +++++ examples/astro-vue/src/pages/foo.astro | 15 ++++ examples/astro-vue/src/pages/index.astro | 25 ++++++ examples/astro-vue/tsconfig.json | 10 +++ examples/astro-vue/uno.config.ts | 28 +++++++ packages/astro/src/index.ts | 4 + packages/vite/package.json | 2 + packages/vite/src/modes/global/build.ts | 76 +++++++++++++++++-- packages/vite/src/types.ts | 8 ++ pnpm-lock.yaml | 4 + 17 files changed, 267 insertions(+), 6 deletions(-) create mode 100644 examples/astro-vue/.gitignore create mode 100644 examples/astro-vue/astro.config.ts create mode 100644 examples/astro-vue/package.json create mode 100644 examples/astro-vue/pnpm-workspace.yaml create mode 100644 examples/astro-vue/src/components/Card.astro create mode 100644 examples/astro-vue/src/components/Example.vue create mode 100644 examples/astro-vue/src/env.d.ts create mode 100644 examples/astro-vue/src/layouts/Layout.astro create mode 100644 examples/astro-vue/src/pages/foo.astro create mode 100644 examples/astro-vue/src/pages/index.astro create mode 100644 examples/astro-vue/tsconfig.json create mode 100644 examples/astro-vue/uno.config.ts diff --git a/examples/astro-vue/.gitignore b/examples/astro-vue/.gitignore new file mode 100644 index 0000000000..7329a851d0 --- /dev/null +++ b/examples/astro-vue/.gitignore @@ -0,0 +1,20 @@ +# build output +dist/ +.output/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/examples/astro-vue/astro.config.ts b/examples/astro-vue/astro.config.ts new file mode 100644 index 0000000000..669068cda2 --- /dev/null +++ b/examples/astro-vue/astro.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'astro/config' +import UnoCSS from 'unocss/astro' +import vue from '@astrojs/vue' + +export default defineConfig({ + integrations: [ + vue(), + UnoCSS(), + ], +}) diff --git a/examples/astro-vue/package.json b/examples/astro-vue/package.json new file mode 100644 index 0000000000..abb1dc8ecc --- /dev/null +++ b/examples/astro-vue/package.json @@ -0,0 +1,19 @@ +{ + "name": "unocss-astro", + "private": true, + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "devDependencies": { + "astro": "^1.6.11", + "unocss": "link:../../packages/unocss" + }, + "dependencies": { + "@astrojs/vue": "^1.2.1", + "vue": "^3.2.30" + } +} diff --git a/examples/astro-vue/pnpm-workspace.yaml b/examples/astro-vue/pnpm-workspace.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/astro-vue/src/components/Card.astro b/examples/astro-vue/src/components/Card.astro new file mode 100644 index 0000000000..09730224b7 --- /dev/null +++ b/examples/astro-vue/src/components/Card.astro @@ -0,0 +1,21 @@ +--- +export interface Props { + title: string; + body: string; + href: string; +} + +const { href, title, body } = Astro.props as Props; +--- + +
  • + +

    + {title} + +

    +

    + {body} +

    +
    +
  • diff --git a/examples/astro-vue/src/components/Example.vue b/examples/astro-vue/src/components/Example.vue new file mode 100644 index 0000000000..bb85d1f1de --- /dev/null +++ b/examples/astro-vue/src/components/Example.vue @@ -0,0 +1,11 @@ + + + diff --git a/examples/astro-vue/src/env.d.ts b/examples/astro-vue/src/env.d.ts new file mode 100644 index 0000000000..f964fe0cff --- /dev/null +++ b/examples/astro-vue/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/astro-vue/src/layouts/Layout.astro b/examples/astro-vue/src/layouts/Layout.astro new file mode 100644 index 0000000000..8196555856 --- /dev/null +++ b/examples/astro-vue/src/layouts/Layout.astro @@ -0,0 +1,19 @@ +--- +export interface Props { + title: string; +} + +const { title } = Astro.props as Props; +--- + + + + + + + {title} + + + + + diff --git a/examples/astro-vue/src/pages/foo.astro b/examples/astro-vue/src/pages/foo.astro new file mode 100644 index 0000000000..8988bfcabe --- /dev/null +++ b/examples/astro-vue/src/pages/foo.astro @@ -0,0 +1,15 @@ +--- +import Layout from '../layouts/Layout.astro'; +import Card from '../components/Card.astro'; +--- + + +
    Foo
    + +
    diff --git a/examples/astro-vue/src/pages/index.astro b/examples/astro-vue/src/pages/index.astro new file mode 100644 index 0000000000..7c7fd298a0 --- /dev/null +++ b/examples/astro-vue/src/pages/index.astro @@ -0,0 +1,25 @@ +--- +import Layout from '../layouts/Layout.astro'; +import Card from '../components/Card.astro'; +import Example from '../components/Example.vue'; +--- + + +
    +
    + +
    +

    Welcome to Astro

    +

    + Check out the src/pages directory to get started.
    +

    + +
    +
    diff --git a/examples/astro-vue/tsconfig.json b/examples/astro-vue/tsconfig.json new file mode 100644 index 0000000000..8610f86adc --- /dev/null +++ b/examples/astro-vue/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + } +} diff --git a/examples/astro-vue/uno.config.ts b/examples/astro-vue/uno.config.ts new file mode 100644 index 0000000000..3e140fcf7d --- /dev/null +++ b/examples/astro-vue/uno.config.ts @@ -0,0 +1,28 @@ +import { + defineConfig, + presetIcons, + presetUno, + transformerCompileClass, + transformerDirectives, + transformerVariantGroup, +} from 'unocss' + +export default defineConfig({ + shortcuts: [ + { 'i-logo': 'i-logos-astro w-6em h-6em transform transition-800' }, + ], + transformers: [ + transformerDirectives(), + transformerCompileClass(), + transformerVariantGroup(), + ], + presets: [ + presetUno(), + presetIcons({ + extraProperties: { + 'display': 'inline-block', + 'vertical-align': 'middle', + }, + }), + ], +}) diff --git a/packages/astro/src/index.ts b/packages/astro/src/index.ts index 626a7fb92e..7fbcef011c 100644 --- a/packages/astro/src/index.ts +++ b/packages/astro/src/index.ts @@ -1,3 +1,5 @@ +import { resolve } from 'path' +import { fileURLToPath } from 'url' import type { AstroIntegration } from 'astro' import type { VitePluginConfig } from '@unocss/vite' import VitePlugin from '@unocss/vite' @@ -38,6 +40,8 @@ export default function UnoCSSAstroIntegration( name: 'unocss', hooks: { 'astro:config:setup': async ({ config, injectScript }) => { + options.watchExternal ||= [] + options.watchExternal.push(resolve(fileURLToPath(config.root), 'src/components/**/*').replace(/\\/g, '/')) config.vite.plugins ||= [] config.vite.plugins.push(...VitePlugin(options, defaults) as any) diff --git a/packages/vite/package.json b/packages/vite/package.json index 812be83992..8ab42a6d6d 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -53,6 +53,8 @@ "@unocss/inspector": "workspace:*", "@unocss/scope": "workspace:*", "@unocss/transformer-directives": "workspace:*", + "chokidar": "^3.5.3", + "fast-glob": "^3.2.12", "magic-string": "^0.26.7" }, "devDependencies": { diff --git a/packages/vite/src/modes/global/build.ts b/packages/vite/src/modes/global/build.ts index b8df8270bb..4ab9ef34e2 100644 --- a/packages/vite/src/modes/global/build.ts +++ b/packages/vite/src/modes/global/build.ts @@ -1,7 +1,9 @@ import { resolve } from 'path' +import fs from 'fs' import type { Plugin, ResolvedConfig } from 'vite' import type { GenerateResult, UnocssPluginContext } from '@unocss/core' import type { PluginContext } from 'rollup' +import fg from 'fast-glob' import { HASH_PLACEHOLDER_RE, LAYER_MARK_ALL, LAYER_PLACEHOLDER_RE, RESOLVED_ID_RE, @@ -14,8 +16,10 @@ import { resolveLayer, } from '../../integration' import type { VitePluginConfig } from '../../types' +import { applyTransformers } from '../../../../shared-integration/src/transformers' -export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, getConfig }: UnocssPluginContext): Plugin[] { +export function GlobalModeBuildPlugin(ctx: UnocssPluginContext): Plugin[] { + const { uno, ready, extract, tokens, filter, getConfig } = ctx const vfsLayers = new Set() const layerImporterMap = new Map() let tasks: Promise[] = [] @@ -54,12 +58,15 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get return lastResult } + let replaced = false + return [ { name: 'unocss:global:build:scan', apply: 'build', enforce: 'pre', - buildStart() { + async buildStart() { + vfsLayers.clear() tasks = [] lastTokenSize = 0 lastResult = undefined @@ -143,6 +150,61 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get return null }, }, + { + name: 'unocss:global:content', + enforce: 'pre', + configResolved(config) { + viteConfig = config + }, + async buildStart() { + const { watchExternal } = await getConfig() + if (watchExternal?.length) { + const files = await fg(watchExternal, { cwd: viteConfig.root }) + + const transformAndExtract = async (code: string, file: string) => { + const preTransform = await applyTransformers(ctx, code, file, 'pre') + const defaultTransform = await applyTransformers(ctx, preTransform?.code || code, file) + await applyTransformers(ctx, defaultTransform?.code || preTransform?.code || code, file, 'post') + return extract(preTransform?.code || code) + } + + if (viteConfig.command === 'build') { + files.map(file => + tasks.push(fs.promises.readFile(file, 'utf-8') + .then(async (content) => { + if (filter(content, file)) + return transformAndExtract(content, file) + }), + ), + ) + return + } + + const { watch } = await import('chokidar') + const ignored = ['**/{.git,node_modules}/**'] + const cwd = viteConfig.root + + const watcher = watch(files, { + ignorePermissionErrors: true, + ignored, + cwd, + }) + + watcher.on('all', (type, file) => { + const absolutePath = resolve(cwd, file) + + if (type === 'add' || type === 'change') { + tasks.push(fs.promises.readFile(absolutePath, 'utf-8') + .then((content) => { + if (filter(content, file)) + return transformAndExtract(content, file) + }), + ) + } + }) + } + }, + }, { name: 'unocss:global:build:generate', apply: 'build', @@ -175,9 +237,6 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get { name: 'unocss:global:build:bundle', apply: 'build', - configResolved(config) { - viteConfig = config - }, enforce: 'post', // rewrite the css placeholders async generateBundle(options, bundle) { @@ -189,12 +248,17 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get return if (!vfsLayers.size) { + // If `vfsLayers` is empty and `replaced` is true, that means + // `generateBundle` hook is called on previous build pipeline. e.g. ssr + // Since we already replaced the layers and don't have any more layers + // to replace on current build pipeline, we can skip the warning. + if (replaced) + return const msg = '[unocss] entry module not found, have you add `import \'uno.css\'` in your main entry?' this.warn(msg) return } - let replaced = false const getLayer = (layer: string, input: string, replace = false) => { const re = new RegExp(`#--unocss-layer-start--${layer}--\\{start:${layer}\\}([\\s\\S]*?)#--unocss-layer-end--${layer}--\\{end:${layer}\\}`, 'g') if (replace) diff --git a/packages/vite/src/types.ts b/packages/vite/src/types.ts index ec2ca46b41..1d98683b27 100644 --- a/packages/vite/src/types.ts +++ b/packages/vite/src/types.ts @@ -34,4 +34,12 @@ export interface VitePluginConfig extends UserConfig Date: Mon, 5 Dec 2022 03:58:01 +0300 Subject: [PATCH 2/3] chore: lint --- examples/astro-vue/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/astro-vue/package.json b/examples/astro-vue/package.json index abb1dc8ecc..3f06dda24a 100644 --- a/examples/astro-vue/package.json +++ b/examples/astro-vue/package.json @@ -8,12 +8,12 @@ "preview": "astro preview", "astro": "astro" }, + "dependencies": { + "vue": "^3.2.30" + }, "devDependencies": { + "@astrojs/vue": "^1.2.1", "astro": "^1.6.11", "unocss": "link:../../packages/unocss" - }, - "dependencies": { - "@astrojs/vue": "^1.2.1", - "vue": "^3.2.30" } } From c96bbb61cd4ad50c1f96c51ffeddcb401d1462e2 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 19 Dec 2022 15:23:20 +0100 Subject: [PATCH 3/3] refactor: api --- packages/astro/src/index.ts | 7 ++- packages/core/src/types.ts | 25 ++++++++ packages/shared-integration/src/context.ts | 11 +++- .../shared-integration/src/extra-content.ts | 55 +++++++++++++++++ packages/vite/src/modes/global/build.ts | 60 ++----------------- packages/vite/src/modes/global/dev.ts | 6 +- packages/vite/src/types.ts | 8 --- packages/webpack/package.json | 2 + packages/webpack/src/index.ts | 11 ++-- pnpm-lock.yaml | 4 ++ 10 files changed, 116 insertions(+), 73 deletions(-) create mode 100644 packages/shared-integration/src/extra-content.ts diff --git a/packages/astro/src/index.ts b/packages/astro/src/index.ts index 7fbcef011c..ead5c3ccd2 100644 --- a/packages/astro/src/index.ts +++ b/packages/astro/src/index.ts @@ -40,8 +40,11 @@ export default function UnoCSSAstroIntegration( name: 'unocss', hooks: { 'astro:config:setup': async ({ config, injectScript }) => { - options.watchExternal ||= [] - options.watchExternal.push(resolve(fileURLToPath(config.root), 'src/components/**/*').replace(/\\/g, '/')) + // Adding components to UnoCSS's extra content + options.extraContent ||= {} + options.extraContent.filesystem ||= [] + options.extraContent.filesystem.push(resolve(fileURLToPath(config.root), 'src/components/**/*').replace(/\\/g, '/')) + config.vite.plugins ||= [] config.vite.plugins.push(...VitePlugin(options, defaults) as any) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 33087ea014..e03a135fa8 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -531,6 +531,13 @@ export interface UnocssPluginContext { /** Module IDs that been affected by UnoCSS */ affectedModules: Set + /** Pending promises */ + tasks: Promise[] + /** + * Await all pending tasks + */ + flushTasks(): Promise + filter: (code: string, id: string) => boolean extract: (code: string, id?: string) => Promise @@ -581,6 +588,19 @@ export interface SourceCodeTransformer { transform: (code: MagicString, id: string, ctx: UnocssPluginContext) => Awaitable } +export interface ExtraContentOptions { + /** + * Glob patterns to match the files to be extracted + * In dev mode, the files will be watched and trigger HMR + */ + filesystem?: string[] + + /** + * Plain text to be extracted + */ + plain?: string[] +} + /** * For other modules to aggregate the options */ @@ -611,6 +631,11 @@ export interface PluginOptions { * Custom transformers to the source code */ transformers?: SourceCodeTransformer[] + + /** + * Extra content outside of build pipeline (assets, backend, etc.) to be extracted + */ + extraContent?: ExtraContentOptions } export interface UserConfig extends ConfigBase, UserOnlyOptions, GeneratorOptions, PluginOptions, CliOptions {} diff --git a/packages/shared-integration/src/context.ts b/packages/shared-integration/src/context.ts index 0971c63f7a..d5d5db8252 100644 --- a/packages/shared-integration/src/context.ts +++ b/packages/shared-integration/src/context.ts @@ -23,6 +23,7 @@ export function createContext = UserConfig>( const modules = new BetterMap() const tokens = new Set() + const tasks: Promise[] = [] const affectedModules = new Set() let ready = reloadConfig() @@ -83,7 +84,7 @@ export function createContext = UserConfig>( invalidate() } - const filter = (code: string, id: string) => { + function filter(code: string, id: string) { if (code.includes(IGNORE_COMMENT)) return false return code.includes(INCLUDE_COMMENT) || code.includes(CSS_PLACEHOLDER) || rollupFilter(id.replace(/\?v=\w+$/, '')) @@ -94,6 +95,12 @@ export function createContext = UserConfig>( return rawConfig } + async function flushTasks() { + const _tasks = [...tasks] + await Promise.all(_tasks) + tasks.splice(0, _tasks.length) + } + return { get ready() { return ready @@ -101,6 +108,8 @@ export function createContext = UserConfig>( tokens, modules, affectedModules, + tasks, + flushTasks, invalidate, onInvalidate(fn: () => void) { invalidations.push(fn) diff --git a/packages/shared-integration/src/extra-content.ts b/packages/shared-integration/src/extra-content.ts new file mode 100644 index 0000000000..40e98cde1e --- /dev/null +++ b/packages/shared-integration/src/extra-content.ts @@ -0,0 +1,55 @@ +import fs from 'fs/promises' +import { resolve } from 'path' +import fg from 'fast-glob' +import type { UnocssPluginContext } from '@unocss/core' +import { applyTransformers } from './transformers' + +export async function setupExtraContent(ctx: UnocssPluginContext, shouldWatch = false) { + const { extraContent } = await ctx.getConfig() + const { extract, tasks, root, filter } = ctx + + // plain text + if (extraContent?.plain) { + await Promise.all( + extraContent.plain.map((code, idx) => { + return extract(code, `__extra_content_${idx}__`) + }), + ) + } + + // filesystem + if (extraContent?.filesystem) { + const files = await fg(extraContent.filesystem, { cwd: root }) + + async function extractFile(file: string) { + const code = await fs.readFile(file, 'utf-8') + if (!filter(code, file)) + return + const preTransform = await applyTransformers(ctx, code, file, 'pre') + const defaultTransform = await applyTransformers(ctx, preTransform?.code || code, file) + await applyTransformers(ctx, defaultTransform?.code || preTransform?.code || code, file, 'post') + return await extract(preTransform?.code || code, file) + } + + if (shouldWatch) { + const { watch } = await import('chokidar') + const ignored = ['**/{.git,node_modules}/**'] + + const watcher = watch(files, { + ignorePermissionErrors: true, + ignored, + cwd: root, + ignoreInitial: true, + }) + + watcher.on('all', (type, file) => { + if (type === 'add' || type === 'change') { + const absolutePath = resolve(root, file) + tasks.push(extractFile(absolutePath)) + } + }) + } + + await Promise.all(files.map(extractFile)) + } +} diff --git a/packages/vite/src/modes/global/build.ts b/packages/vite/src/modes/global/build.ts index f0a8b2223f..ac2d964710 100644 --- a/packages/vite/src/modes/global/build.ts +++ b/packages/vite/src/modes/global/build.ts @@ -1,9 +1,7 @@ import { resolve } from 'path' -import fs from 'fs' import type { Plugin, ResolvedConfig } from 'vite' import type { GenerateResult, UnocssPluginContext } from '@unocss/core' import type { PluginContext } from 'rollup' -import fg from 'fast-glob' import { HASH_PLACEHOLDER_RE, LAYER_MARK_ALL, LAYER_PLACEHOLDER_RE, RESOLVED_ID_RE, @@ -16,13 +14,12 @@ import { resolveLayer, } from '../../integration' import type { VitePluginConfig } from '../../types' -import { applyTransformers } from '../../../../shared-integration/src/transformers' +import { setupExtraContent } from '../../../../shared-integration/src/extra-content' export function GlobalModeBuildPlugin(ctx: UnocssPluginContext): Plugin[] { - const { uno, ready, extract, tokens, filter, getConfig } = ctx + const { uno, ready, extract, tokens, filter, getConfig, tasks, flushTasks } = ctx const vfsLayers = new Set() const layerImporterMap = new Map() - let tasks: Promise[] = [] let viteConfig: ResolvedConfig // use maps to differentiate multiple build. using outDir as key @@ -50,7 +47,7 @@ export function GlobalModeBuildPlugin(ctx: UnocssPluginContext let lastTokenSize = 0 let lastResult: GenerateResult | undefined async function generateAll() { - await Promise.all(tasks) + await flushTasks() if (lastResult && lastTokenSize === tokens.size) return lastResult lastResult = await uno.generate(tokens, { minify: true }) @@ -67,7 +64,7 @@ export function GlobalModeBuildPlugin(ctx: UnocssPluginContext enforce: 'pre', async buildStart() { vfsLayers.clear() - tasks = [] + tasks.length = 0 lastTokenSize = 0 lastResult = undefined }, @@ -156,53 +153,8 @@ export function GlobalModeBuildPlugin(ctx: UnocssPluginContext configResolved(config) { viteConfig = config }, - async buildStart() { - const { watchExternal } = await getConfig() - if (watchExternal?.length) { - const files = await fg(watchExternal, { cwd: viteConfig.root }) - - const transformAndExtract = async (code: string, file: string) => { - const preTransform = await applyTransformers(ctx, code, file, 'pre') - const defaultTransform = await applyTransformers(ctx, preTransform?.code || code, file) - await applyTransformers(ctx, defaultTransform?.code || preTransform?.code || code, file, 'post') - return extract(preTransform?.code || code) - } - - if (viteConfig.command === 'build') { - files.map(file => - tasks.push(fs.promises.readFile(file, 'utf-8') - .then(async (content) => { - if (filter(content, file)) - return transformAndExtract(content, file) - }), - ), - ) - return - } - - const { watch } = await import('chokidar') - const ignored = ['**/{.git,node_modules}/**'] - const cwd = viteConfig.root - - const watcher = watch(files, { - ignorePermissionErrors: true, - ignored, - cwd, - }) - - watcher.on('all', (type, file) => { - const absolutePath = resolve(cwd, file) - - if (type === 'add' || type === 'change') { - tasks.push(fs.promises.readFile(absolutePath, 'utf-8') - .then((content) => { - if (filter(content, file)) - return transformAndExtract(content, file) - }), - ) - } - }) - } + buildStart() { + tasks.push(setupExtraContent(ctx, viteConfig.command === 'serve')) }, }, { diff --git a/packages/vite/src/modes/global/dev.ts b/packages/vite/src/modes/global/dev.ts index 8aa5d81519..b11845bc7b 100644 --- a/packages/vite/src/modes/global/dev.ts +++ b/packages/vite/src/modes/global/dev.ts @@ -7,11 +7,9 @@ const WARN_TIMEOUT = 20000 const WS_EVENT_PREFIX = 'unocss:hmr' const HASH_LENGTH = 6 -export function GlobalModeDevPlugin({ uno, tokens, affectedModules, onInvalidate, extract, filter }: UnocssPluginContext): Plugin[] { +export function GlobalModeDevPlugin({ uno, tokens, tasks, flushTasks, affectedModules, onInvalidate, extract, filter }: UnocssPluginContext): Plugin[] { const servers: ViteDevServer[] = [] let base = '' - - const tasks: Promise[] = [] const entries = new Set() let invalidateTimer: any @@ -21,7 +19,7 @@ export function GlobalModeDevPlugin({ uno, tokens, affectedModules, onInvalidate let resolvedWarnTimer: any async function generateCSS(layer: string) { - await Promise.all(tasks) + await flushTasks() let result: GenerateResult let tokensSize = tokens.size do { diff --git a/packages/vite/src/types.ts b/packages/vite/src/types.ts index 1d98683b27..ec2ca46b41 100644 --- a/packages/vite/src/types.ts +++ b/packages/vite/src/types.ts @@ -34,12 +34,4 @@ export interface VitePluginConfig extends UserConfig( ) { return createUnplugin(() => { const ctx = createContext(configOrPath as any, defaults) - const { uno, tokens, filter, extract, onInvalidate } = ctx + const { uno, tokens, filter, extract, onInvalidate, tasks, flushTasks } = ctx let timer: any onInvalidate(() => { @@ -41,7 +42,9 @@ export default function WebpackPlugin( ) } - const tasks: Promise[] = [] + // TODO: detect webpack's watch mode and enable watcher + tasks.push(setupExtraContent(ctx)) + const entries = new Set() const hashes = new Map() @@ -92,7 +95,7 @@ export default function WebpackPlugin( compilation.hooks.optimizeAssets.tapPromise(PLUGIN_NAME, async () => { const files = Object.keys(compilation.assets) - await Promise.all(tasks) + await flushTasks() const result = await uno.generate(tokens, { minify: true }) for (const file of files) { @@ -133,7 +136,7 @@ export default function WebpackPlugin( if (!plugin.__vfsModules) return - await Promise.all(tasks) + await flushTasks() const result = await uno.generate(tokens) if (lastTokenSize === tokens.size) return diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c03466a33e..c3704ac39e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -655,6 +655,8 @@ importers: '@types/webpack-sources': ^3.2.0 '@unocss/config': workspace:* '@unocss/core': workspace:* + chokidar: ^3.5.3 + fast-glob: ^3.2.12 magic-string: ^0.27.0 unplugin: ^1.0.1 webpack: ^5.75.0 @@ -664,6 +666,8 @@ importers: '@rollup/pluginutils': 5.0.2 '@unocss/config': link:../config '@unocss/core': link:../core + chokidar: 3.5.3 + fast-glob: 3.2.12 magic-string: 0.27.0 unplugin: 1.0.1 webpack-sources: 3.2.3