Overview
Recently, I have been curious about zero-runtime css-in-js libraries and the performance benefits they bring. One such library, relatively new, is vanilla-extract
. Because I like to build projects with nx
, I was curious if there is already support for it but currently there isn't as yet.
This aims to show a quick and easy way to add support for vanilla-extract
in a react/webpack app in an nx workspace.
What is vanilla-extract?
vanilla-extract
is all about zero-runtime style sheets in TypeScript (or JavaScript). If you’ve used Sass or Less in the past, you already know how powerful they can be for things like theming, organization, and preprocessing of your app’s styles.
Setup
Let's create a workspace
Please see below the command to create the nx workspace and the options taken to follow along.
Note: the current version of nx at this time is 15.0.1
npx create-nx-workspace@latest
# Choose your style: Integrated
# What to create in the new workspace: react
# Repository name: vanilla
# Application name: example-web
# Default stylesheet format: CSS
# Enable distributed caching to make your CI faster: No
Install dependencies
npm i @vanilla-extract/css
npm i --save-dev @vanilla-extract/webpack-plugin
Create custom webpack config
In order to add support, we need to do a few things:
- Create a file:
apps/example-web/webpack.config.js
- Add rules for the css generated by vanilla-extract
- Prepend these rules in the rules array already provided by nx
- Replace the rules array
// file: apps/example-web/webpack.config.js
const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (config) => {
const cssRule = config.module.rules.find((rule) =>
rule.test.toString().includes('css')
);
const rulesWithoutCss = config.module.rules.filter(
(rule) => !rule.test.toString().includes('css')
);
const rules = [
...rulesWithoutCss,
{
...cssRule,
oneOf: [
{
test: /\.vanilla\.css$/i, // Targets only CSS files generated by vanilla-extract
use: [
MiniCssExtractPlugin.loader,
{
loader: require.resolve('css-loader'),
options: {
url: false, // Required as image imports should be handled via JS/TS import statements
},
},
],
},
...cssRule.oneOf,
],
},
];
return {
...config,
plugins: [...config.plugins, new VanillaExtractPlugin()],
module: {
...config.module,
rules,
},
};
};
Use the custom webpack config
In the file apps/example-web/project.json
,
find the property webpackConfig
and replace it with
"webpackConfig": "apps/example-web/webpack.config.js",
Create and use your styles
Create file apps/example-web/src/app/app.css.ts
import { style } from '@vanilla-extract/css';
export const container = style({
padding: 10,
background: 'blue',
});
Modify file: apps/example-web/src/app/app.tsx
import { container } from './app.css';
import NxWelcome from './nx-welcome';
export function App() {
return (
<div className={container}>
<NxWelcome title="example-web" />
<div />
</div>
);
}
export default App;
Run the application
npm run start example-web
Thats it!
- You will now see that the page's background is blue. Not the prettiest thing but just to prove it works.
- Upon inspecting the network, you can locate the css file
vendor.css
(at this time and for this example) which has the generated styles
Your next steps
- Try it out
- make your own customisations like changing the exported css file name, etc.
- Leave feedback; I'd love to see how this can be improved.
see sample repository for completed solution
https://github.com/lwhiteley/nx-vanilla-extract-setup
Feature request for nx: https://github.com/nrwl/nx/issues/12771
Top comments (2)
thanks for this!
there's a slight typo in the webpack config - should be
cssRule
instead ofcssRules
.Hey glad you found it helpful.
Thanks for spotting..will adjust