Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 30, 2022 09:44 am GMT

Supporting SASS in your TS React project using TSC and esbuild

What a mouthful, right? Supporting SASS in your TS React project using TSC and esbuild... and this is not even the full title which tells what will soon happen here. Its because its a little bit complicated, though the implementation is rather simple. Let me explain

We all know SASS and its benefits, and until native CSS will support nesting, to say the least, I dont see it going anywhere (and SASS has a lot more to offer).

My Components package currently supports regular plain-old CSS (not that theres anything wrong with it), and I thought it was a good time to introduce SASS to it, but the package is not a ordinary Webpack-build-that-s#!t-for-me. Im using TSC (TypeScript Compiler) to generate the artifacts -
What it means is that TSC is compiling 2 versions of the component, ESM and CJS. Once we have these, were taking the ESM outcome and bundling it using esbuild. You can read more about it here, but if to put it visually:

Image description

You can argue that this does not make much sense for a components package and you'll be right, but we can take this package as an example for a React project written in TS with a build process which results in a JS bundle and a CSS file.

The build script looks like this:

"build": "tsc --project tsconfig.esm.json & tsc --project tsconfig.cjs.json && yarn bundle","bundle": "node ../../esbuild.config.js",

And the esbuild.config.js looks like this:

const cssPlugin = require('./esbuild.css.plugin');require('esbuild')   .build({       entryPoints: ['dist/esm/index.js'],       bundle: true,       minify: true,       sourcemap: true,       outfile: 'dist/main/index.js',       plugins: [cssPlugin],   })   .catch(() => process.exit(1));

What is this cssPlugin?
The CSS plugin here helps us convert the CSS files paths, since TSC does not deal with them and therefore they are not to be found under the dist/esm directory, so what this custom plugin does is identifying the import and redirect it to where the file is at. This saves us the "copy" of .css files to the dist/esm directory, but come to think of it, I realize I need to copy these anyhow. not relevant for now ;)

Its always good to define our goals before jumping into coding, and in this case:

  • Have our components style as a SASS file
  • Make sure that Storybook (yes, Storybook) is still working as it used to
  • Have the esbuild bundling process create the final CSS file from the SASS file, and place it with the JS bundle under the dist/main directory

Before we start, know that you can find all the code under this GitHub repo.

Here we go :)

First we rename the index.css file into a index.scss one. We also change the import in the component accordingly:

. . .import './index.scss';

Storybook

Because I like tormenting myself, I run Storybook to make sure that were still getting our CSS styles and sure enough were getting an error:

ModuleParseError: Module parse failed: Unexpected token (8:0)You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders|  */| > .selected {

Why? Because Storybook does not know how to handle this SASS file. In order for it to handle SASS we need to use a plugin called storybook-addon-sass-postcss. You can read more details on how to install and use it here. Once installed and set in the Storybook addons, it appears that Storybook is working as expected.

Now what about the bundling?

esbuild bundling

For bundling we need to have esbuild take care of our SASS file. If I run the build now, this is the result Im getting:

 [ERROR] Could not resolve "./index.scss"    dist/esm/src/Pagination/index.js:4:7:      4  import './index.scss';                ~~~~~~~~~~~~~~

The plugin Ive mentioned earlier, which takes care of redirecting the paths for imported CSS, is only looking for .css, but we would like it to look for .scss as well. I will change the regex for that. Here is the result plugin:

const path = require('path');module.exports = {   name: 'css',   setup(build) {       // Redirect all paths css, scss or sass       build.onResolve({filter: /.\.s[ac]ss$/}, (args) => {           const path1 = args.resolveDir.replace('/dist/esm', '');           return {path: path.join(path1, args.path)};       });   },};

Running the build again and were getting another error, but this time its encouraging. The error claims that there is no Loader to deal with the .scss file:

 [ERROR] No loader is configured for ".scss" files: src/Pagination/index.scss    dist/esm/src/Pagination/index.js:4:7:      4  import './index.scss';                ~~~~~~~~~~~~~~

Great news :)
For that we need to install a loader for esbuild that can take care of the .scss file. Were going to use the esbuild-sass-plugin to do that. Im installing it with yarn add -D esbuild-sass-plugin and add it to my esbuild.config.js like so:

const cssPlugin = require('./esbuild.css.plugin');const {sassPlugin} = require('esbuild-sass-plugin');require('esbuild')   .build({       entryPoints: ['dist/esm/index.js'],       bundle: true,       minify: true,       sourcemap: true,       outfile: 'dist/main/index.js',       plugins: [cssPlugin, sassPlugin()],   })   .catch(() => process.exit(1));

Running the build now and Boom! We have it - the dist/main directory holds a processed CSS file generated from the .scss file. Nice :)

Not that complicated after all. Im messing a bit with the SASS file, just to make sure the nesting works as expected and indeed it works well:

.pagination {    font-size: large;    .selected {        font-weight: bolder;        color: blue;    }    button {        border: none;        background-color: aqua;        border-radius: 5px;        padding: 10px;        &:hover {            background-color: darkmagenta;        }        &:active {            background-color: aqua;        }        &:disabled {            background-color: lightgray;        }    }}

Image description

As mentioned before, you can find all the code under this GitHub repo, and as always, if you have any questions or comments please leave them in the comments section below so that we can all learn from them :)

Hey! for more content like the one you've just read check out @mattibarzeev on Twitter

Photo by Karim MANJRA on Unsplash


Original Link: https://dev.to/mbarzeev/supporting-sass-in-your-ts-react-project-using-tsc-and-esbuild-1l1l

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To