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:
"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
//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:
//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:
// 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
//index.js
import { registerRootComponent } from "expo";
import App from "./src/App";
registerRootComponent(App)
Update package.json as follows:
"main": "index.js",
Create directory called
src
and moveApp.tsx
to it.Create
App.scss
inside thesrc
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;
}
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>
);
}
Now run the app with
npm start
, you will get output like this
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)
following the tutorial, I am still getting this error:
Unable to resolve "./App.scss" from "src\App.jsx"
ah you are using js right, try this with ts
can you share the repo?