Initialize Project [commit]
% expo init expo-amplify-starter && cd $_ ✔ Choose a template: › blank (TypeScript)
Restructure Project [commit]
This part is up to you but I prefer to move my code toÂ
src/
 and structure my projects the following way,.expo-shared node_modules src ├── api ├── assets ├── components ├── screens ├── i18n ├── navigation ├── screens ├── services ├── styles ├── utilities ├── App.tsx .gitignore index.js <-- We are about to create this file app.json babel.config.js package.json tsconfig.json yarn.lock
Fix App Entry Point
Since we movedÂ
App.tsx
 from the root directory, which is where Expo expects our App to be, we have to create a new entry point file in the root and point to it.// index.js import { registerRootComponent } from 'expo'; import App from './src/App'; export default registerRootComponent(App);
I'm pretty sure this file needs to be named index.js and be in the root of the directory. I had it different before and although it worked locally, my EAS builds failed.
// package.json { "main": "./index.js", ... }
Fix Asset Paths
Since we moved the assets, we have to also update those paths too.
// app.json { "expo": { ... "icon": "./src/assets/icon.png", "splash": { "image": "./src/assets/splash.png", ... }, ... "android": { "adaptiveIcon": { "foregroundImage": "./src/assets/adaptive-icon.png", ... } }, "web": { "favicon": "./src/assets/favicon.png" } } }
Create Path Aliases [commit]
Path aliases (also called module resolution depending on the tool) are a nice way to import parts of your project without having to specify an exact path. This not only saves you typing but makes it easier to restructure later if need be. Since Expo utilizes different build tools, you have to declare these in multiple places.
import { SomeUtility } from '../../utilities/MyUtility'; // Changes to import { SomeUtility } from '@utilities/MyUtility';
Create Path Aliases for TypeScript
// tsconfig.json { ... "compilerOptions": { ... "baseUrl": "./src", "paths": { "@api/*": ["api/*"], "@assets/*": ["assets/*"], "@components/*": ["components/*"], "@i18n/*": ["i18n/*"], "@navigation/*": ["navigation/*"], "@screens/*": ["screens/*"], "@services/*": ["services/*"], "@styles/*": ["styles/*"], "@utilities/*": ["utiltiies/*"], } }, }
Create Path Aliases for Expo Web
First we have to get access to the webpack configuration. RunÂ
expo customize:web
 and select to generate webpack.config.js
// webpack.config.js const createExpoWebpackConfigAsync = require('@expo/webpack-config'); const path = require('path'); module.exports = async (env, argv) => { const config = await createExpoWebpackConfigAsync(env, argv); config.resolve.alias = { ...config.resolve.alias, '@api': path.resolve(__dirname, 'src/api/'), '@assets': path.resolve(__dirname, 'src/assets/'), '@components': path.resolve(__dirname, 'src/components/'), '@i18n': path.resolve(__dirname, 'src/i18n/'), '@navigation': path.resolve(__dirname, 'src/navigation/'), '@screens': path.resolve(__dirname, 'src/screens/'), '@services': path.resolve(__dirname, 'src/services/'), '@styles': path.resolve(__dirname, 'src/styles/'), '@utilities': path.resolve(__dirname, 'src/utilities/'), }; return config; };
Path Aliases for iOS/android
yarn add -D babel-plugin-module-resolver
// .babelrc.js { presets: [ ... ], plugins: [ ... [ 'module-resolver', { root: ['./'], alias: { '@api': './src/api', '@assets': './src/assets', '@components': './src/components', '@i18n': './src/i18n', '@navigation': './src/navigation', '@screens': './src/screens', '@services': './src/services', '@styles': './src/styles', '@utilities': './src/utilities', }, } ] ] }
Path Aliases for Jest
If you are using Jest you will also have to configure the path aliases for it as well.
// jest.config.js module.exports = { ... moduleNameMapper: { '^@api/(.*)': '<rootDir>/src/api/$1', '^@assets/(.*)': '<rootDir>/src/assets/$1', '^@components/(.*)': '<rootDir>/src/components/$1', '^@i18n/(.*)': '<rootDir>/src/i18n/$1', '^@navigation/(.*)': '<rootDir>/src/navigation/$1', '^@screens/(.*)': '<rootDir>/src/screens/$1', '^@services/(.*)': '<rootDir>/src/services/$1', '^@styles/(.*)': '<rootDir>/src/styles/$1', '^@utilities/(.*)': '<rootDir>/src/utilities/$1', }, };
Test Path Aliases
Okay, now that we have added the aliases to all the files we needed to, let's test it to make sure it is working on iOS, Android, and the web.
// src/utilities/MyUtility export const SomeUtility = () => { return 'Success' };
// src/App.tsx ... import { SomeUtility } from '@utilities/MyUtility'; export default function App() { return ( <View style={styles.container}> <Text>Path Alias: {SomeUtility()}</Text> <StatusBar style="auto" /> </View>); } ...
Test your app withÂ
yarn start -c
 (-c
 clears the cache). You should see "Path Alias: Success" on all the platforms.