DEV Community

GihanRangana
GihanRangana

Posted on • Edited on

How to Use a Sass/SCSS with Expo SDK v48 and TypeScript

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

"dependencies": {
    "react-native": "gihanrangana/react-native#v0.71.3"
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure the babel.config.js

Now we need to update babel.config.js file as follows

//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"] },
            ],
        ],
    };
};
Enter fullscreen mode Exit fullscreen mode

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:

//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 });
    }
};
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

// 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;
Enter fullscreen mode Exit fullscreen mode

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

//index.js
import { registerRootComponent } from "expo";
import App from "./src/App";

registerRootComponent(App)
Enter fullscreen mode Exit fullscreen mode

Update package.json as follows:

"main": "index.js",
Enter fullscreen mode Exit fullscreen mode

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

Create App.scss inside the src directory

/*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;
}
Enter fullscreen mode Exit fullscreen mode

Update App.tsx as follows:

// 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now run the app with npm start, you will get output like this

Expo SDK v48 Sass Transformer Typescript

See this repo to get better understand about this configuration:
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.

Top comments (3)

Collapse
 
themillenniumfalcon profile image
Nishank Priydarshi

following the tutorial, I am still getting this error:
Unable to resolve "./App.scss" from "src\App.jsx"

Collapse
 
gihanrangana profile image
GihanRangana

ah you are using js right, try this with ts

Collapse
 
gihanrangana profile image
GihanRangana

can you share the repo?