Skip to content

Instantly share code, notes, and snippets.

@manuhabitela
Last active September 2, 2022 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manuhabitela/8255a48032db4a8fbd5300d1c44dd08a to your computer and use it in GitHub Desktop.
Save manuhabitela/8255a48032db4a8fbd5300d1c44dd08a to your computer and use it in GitHub Desktop.
Setting up atomizer in a vite project

This is just a copy of a work I won't use right now I guess. Wanted to use atomizer (acss.io) in a vite project and the official plugin didn't work in dev mode. So I tried a few things.

import Atomizer from "atomizer"
import * as fs from "fs"
import type { AtomizerConfig, AtomizerOptions, AtomizerRule, CSSOptions } from "atomizer"
import { createUnplugin } from "unplugin"
export const unplugin = createUnplugin<
AtomizerOptions & {
cssOptions?: CSSOptions // passed to Atomizer.getCSS
config: AtomizerConfig
outputFile?: string
rules?: AtomizerRule[]
}
>((options) => {
let watchMode = false
let devFileStream: null | fs.WriteStream = null
const devClassNames: string[] = []
const buildClassNames = new Map<string, Array<string>>()
const target = options.outputFile || "atomizer.css"
const atomizer = new Atomizer(
{
verbose: options.verbose,
},
options.rules
)
return {
name: "unplugin-atomizer",
enforce: "pre",
vite: {
configResolved(config) {
watchMode = config.command === "serve"
if (watchMode) {
fs.writeFile(target, "", () => {})
devFileStream = fs.createWriteStream(target, {
flags: "a",
})
}
},
closeBundle() {
if (watchMode) {
devFileStream!.end()
}
},
/* Extract atomic css classes from each file that has changed */
transform(content, path) {
// find classic atomizer classes
const classNames = atomizer.findClassNames(content)
// in dev mode, append new classnames in the options.outputFile
// since the idea is that this file is imported in the JS code, HMR will notice the change
if (watchMode) {
// do not add classNames already found earlier
const newClassNames = classNames.filter((className) => {
return devClassNames.includes(className) === false
})
const config = atomizer.getConfig(newClassNames, options.config)
const newCss = atomizer.getCss(config, options.cssOptions)
devClassNames.push(...newClassNames)
devFileStream!.write(newCss)
} else {
buildClassNames.set(path, classNames)
}
return null
},
/* Build final atomizer css file */
buildEnd() {
const classes = Array.from(buildClassNames.values())
.flat()
// remove duplicates
.filter((className, index, array) => {
return className !== "" && array.indexOf(className) === index
})
const config = atomizer.getConfig(classes, options.config)
const css = atomizer.getCss(config, options.cssOptions)
fs.writeFile(target, css, () => {})
},
},
}
})
export default unplugin.vite
module.exports = {
content: ["./src/**/*.{ts,tsx,html}", "./index.html"],
breakPoints: {},
custom: {},
}
/**
* example main file of your app
*
*/
// if you import here the generated css file, it will be converted to a static asset when making a production build
import "./atomic.css"
/** rest of the code */
/**
* example vite config
*
*/
import { defineConfig } from "vite"
import atomizer from "./atomizer-vite-plugin"
import atomizerConfig from "./atomizer.config.cjs"
export default defineConfig(() => ({
plugins: [
atomizer({
config: atomizerConfig,
// the outputFile is the file that will be generated while in dev mode
outputFile: "atomic.css",
}),
]
}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment