Introduce
You can check the example introduced here.
When developing with React and CSS Modules, you may find that the styling part is not type-safe. Introducing a more type-safe styling method.
For that purpose, I created two libraries, so I will introduce them.
-
vite-plugin-sass-dts
- When dev or build is started, the type definition of css, scss, sass file is automatically created.
-
classnames-generics
- classnames You can use the library more type-safely.
It is assumed that vite, React and TypeScript are installed.
Install
npm i classnames-generics
npm i -D viet-plugin-sass-dts
Set the plugin in the vite.config.ts
file.
vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import sassDts from "vite-plugin-sass-dts";
import path from "path";
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles" as common;`,
importer(...args) {
if (args[0] !== "@/styles") {
return;
}
return {
file: `${path.resolve(
__dirname,
"./src/assets/styles"
)}`,
};
},
},
},
},
plugins: [
react(),
sassDts({
allGenerate: true,
global: {
generate: true,
outFile: path.resolve(__dirname, "./src/style.d.ts"),
},
}),
],
});
Start vite
npm run dev
Implement and save the scss
file
src/App.module.scss
.header-1 {
background-color: common.$primary;
.active {
background-color: black;
}
}
src/assets/styles/_index.scss
$primary: violet;
.row {
display: flex;
}
A type definition file is automatically created in the same directory as the saved scss
file.
src/App.module.scss.d.ts
import globalClassNames from './style.d'
declare const classNames: typeof globalClassNames & {
readonly 'header-1': 'header-1';
readonly 'active': 'active';
};
export = classNames;
src/style.d.ts
declare const classNames: {
readonly 'row': 'row';
};
export = classNames;
Implement components using type definitions
src/App.tsx
import { VFC } from "react";
import styles from "./App.module.scss";
import { classNamesFunc } from "classnames-generics";
const classNames = classNamesFunc<keyof typeof styles>();
type Props = {
active: boolean;
};
export const App: VFC<Props> = (props) => {
return (
<header
className={classNames(
styles["header-1"],
{ [styles.active]: props.active },
styles.row
)}
>
vite-plugin-sass-dts-example
</header>
);
};
Complementation is also effective, so you can expect an improvement in development speed.
Tips
You can create a type definition for an already created scss file by passing options at build time.
vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import sassDts from "vite-plugin-sass-dts";
export default defineConfig({
plugins: [react(), sassDts({ allGenerate: true })],
});
Build vite
npm run build
I'm waiting for your feedback.
Top comments (0)