How to Use a Sass/SCSS with Expo SDK v48 and TypeScript
Tags: expo, saas, scss, reactnative
Published: 2023-03-08 14:12:54

If you're a mobile app developer using Expo, you're probably already familiar with how easy it is to build a high-quality app with minimal setup. However, if you're used to using Sass/SCSS in your web development workflow, you might be wondering how to incorporate it into your Expo project. In this tutorial, we'll walk you through how to set up Sass/SCSS in your Expo SDK v48 project, using TypeScript.

### Step 1: Create Project with expo v48
The first step you should have to create a expo project with the latest expo v48.

```
npx create-expo-app my-app --template typescript
cd my-app
```

### Step 2: Install Dependencies

Install the dependencies needed for Sass/SCSS to work with Expo SDK v48 and TypeScript. Run the following command in your terminal:

```
npm install babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions node-sass react-native-sass-transformer
```

If you want create `.d.ts` file for your `.scss` files add `react-native-typed-sass-transformer` instead of `react-native-sass-transformer`

### Step 3: Update package.json
In this step we have to update `package.json` to use `react-native` from github repo. This is required to use `className` prop on react native elements. update `react-native` with follows:

```json
"dependencies": {
    "react-native": "gihanrangana/react-native#v0.71.3"
}
```

### Step 4: Configure the babel.config.js
Now we need to update `babel.config.js` file as follows

```js
//babel.config.js
module.exports = function (api) {
    api.cache(true);
    return {
        presets: ['babel-preset-expo'],
        plugins: [
            "react-native-classname-to-style",
            [
                "react-native-platform-specific-extensions",
                { extensions: ["scss", "sass"] },
            ],
        ],
    };
};
```

### Step 5: Configure metro.config.js
In this step we configure the `metro.config.js` to transform styles from `.scss` or `.sass` files.

First create the `transformer.js` file at project root as follows:

```js
//transformer.js
cosnt upstreamTransformer = require("metro-react-native-babel-transformer");
const sassTransformer = require("react-native-sass-transformer");

const theme = (process.cwd() + "/src/styles/Global.scss").replace(/\\/g, "/");

module.exports.transform = function ({ src, filename, options }) {
	if (filename.endsWith(".scss") || filename.endsWith(".sass")) {
		var opts = Object.assign(options, {
			sassOptions: {
				functions: {
					"rem($px)": px => {
						px.setValue(px.getValue() / 16);
						px.setUnit("rem");
						return px;
					}
				}
			}
		});

		src = `@import "${theme}"; \n\n ` + src;

		return sassTransformer.transform({ src, filename, options: opts });
	} else {
		return upstreamTransformer.transform({ src, filename, options });
	}
};
``` 
This file will transform all scss files you import in your project. There is one plus point, 

You can create `Global.scss` files under the `src/styles/` directory. on that file you can create your own sass variables, then you can use any sass variables you declared on `Global.scss` any ware in your project globally without importing.

Now you have to run this command to create `metro.config.js` file:
```
npx expo customize metro.config.js
```

This command will create file called `metro.config.js`, after that update file as follows:

```js
// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname);

const { resolver: { sourceExts } } = config;

config.transformer.babelTransformerPath = require.resolve("./transformer.js");
config.resolver.sourceExts = [...sourceExts, "scss", "sass"];

module.exports = config;
```

Ok great! you are done now with configurations. let's test it now!

> Create file called index.js on root of the project with this content
```js
//index.js
import { registerRootComponent } from "expo";
import App from "./src/App";

registerRootComponent(App)
```
> Update package.json as follows:
```json
"main": "index.js",
```

> Create directory called `src` and move `App.tsx` to it.

> Create `App.scss` inside the `src` directory
 ```scss
/*App.scss*/
.container {
    flex: 1;
    justify-content: center;
    align-items: center;
    background-color: $bg;
    padding: 10px;
}

.text {
    color: $light0;
    font-size: rem(24px);
    text-align: center;
}
```
> Update `App.tsx` as follows:
```tsx
// App.tsx
import { StatusBar } from 'expo-status-bar';
import { Text, View } from 'react-native';

import styles from './App.scss';

export default function App() {
  return (
    <View className={styles.container}>
      <Text className={styles.text}>This is app using scss to create styling the components</Text>
      <StatusBar style="auto" />
    </View>
  );
}
```
> Now run the app with `npm start`, you will get output like this

![Expo SDK v48 Sass Transformer Typescript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42ezetfty3pb306y1n6v.png)

See this repo to get better understand about this configuration:
[expo-sdk-48-sass-transformer-ts](https://github.com/gihanrangana/expo-sdk-48-sass-transformer-ts)

## Conclusion
Using Sass/SCSS with Expo SDK v48 and TypeScript can enhance your mobile app development workflow by allowing you to write more modular and maintainable stylesheets. With just a few simple steps, you can setup babel and metro to handle Sass/SCSS files and include them in your TypeScript project. From there, you can write Sass/SCSS code and import it into your TypeScript files.Overall, incorporating Sass/SCSS into your Expo project can make your styling more efficient, organized, scalable and also you can use same stylesheet from `mobile app to web app` or `web app to mobile app` easily.