In this post I'll show you how to setup your (universal) Expo app to use Gatsby when targeting web!
🚨 If you find bugs please report them on the expo-cli repo with the
[gatsby]
tag in the title.
Why use Gatsby with Expo?
Here are the main benefits of doing this:
- You can prerender the web part of your Expo app.
- If you use Gatsby already, then now you can share most of your code between web and mobile.
- If you're new to Expo then this also means that you can use complex browser features from the Expo SDK like Camera, Gestures, Permissions, etc. whenever possible in the browser!
⚽️ Tutorial
- Install or update the Expo CLI:
npm i -g expo-cli
- Create a new Expo project:
expo init
- Install the Gatsby plugin:
# yarn
yarn add gatsby gatsby-plugin-react-native-web
# npm
npm install --save gatsby gatsby-plugin-react-native-web
- Create a
gatsby-config.js
and use the plugin:gatsby-config.js
module.exports = {
plugins: [
`gatsby-plugin-react-native-web`,
/* ... */
],
}
- Add
/.cache
and/public
to your.gitignore
- Now create the first page of your Gatsby project:
- Create the pages folder:
mkdir -p src/pages
- Create the file:
- Create the pages folder:
# JS
cp App.js src/pages/index.js
# TS
cp App.tsx src/pages/index.tsx
- Run
yarn gatsby develop
to try it out!- Open the project in the browser
http://localhost:8000/
- Open the project in the browser
Trouble Shooting
If you started your project without the Expo CLI you may also need to do these things:
If you started your project with Gatsby CLI then check out the guide I wrote in the docs: Gatsby Project with Expo.
Install React Native for Web:
yarn add react-native-web
Install the babel preset for React Native web:
# yarn
yarn add --dev babel-preset-expo
# npm
npm install --save-dev babel-preset-expo
- 💡 Even though the name has Expo in it, you can (and should) use it for any React Native project as it provides universal platform support.
- Create a
babel.config.js
and use the Babel preset:babel.config.js
- Create a
module.exports = { presets: ['babel-preset-expo'] }
🏁 New Commands
-
Starting web
- 🚫
expo start:web
- ✅
yarn gatsby develop
- 🚫
-
Building web
- 🚫
expo build:web
- ✅
yarn gatsby build
- 🚫
-
Serving your static project
- 🚫
serve web-build
- ✅
yarn gatsby serve
- 🚫
📁 File Structure
Here is the recommended file structure for a Expo project with Gatsby support.
Expo Gatsby
├── src
│ └── pages ➡️ Routes
│ └── index.tsx ➡️ Entry Point for Gatsby
├── .cache ➡️ Generated Gatsby files (should be ignored)
├── public ➡️ Generated Gatsby files (should be ignored)
├── assets ➡️ All static assets for your project
├── App.tsx ➡️ Entry Point for Mobile apps
├── app.json ➡️ Expo config file
├── gatsby-config.js ➡️ Gatsby config file
└── babel.config.js ➡️ Babel config (should be using `babel-preset-expo`)
👋 Thanks for Reading
I hope you found this article helpful! If you do use this workflow I'd love to hear about how it worked for you 😁 If you didn't, I'd also love to hear! So go tweet some emojis at me :]
Top comments (10)
Issue:
When adding gatsby and react-native-web to an existing expo project with the above instructions,
yarn gatsby develop
will error out. Something about gatsby graphql calls at compile time.Resolution:
Install babel-plugin-remove-graphql-queries plugin and update the babel config file.
yarn add --dev babel-plugin-remove-graphql-queries
Edit:
I found the fix here: github.com/slorber/gatsby-plugin-r...
It's been fixed in 3.0.0-beta.7
Please let me know if you have other issues or if you build something meaningful with the plugin.
You shouldn't need a local babel config anymore (but it can be useful if you are using the same folder as a gatsby app + an Expo app, like in this setup).
It may be worth to read also the plugin's readme, as I've just updated it.
Thanks for this! This got me up and running with SSR in my Typescript Expo project, awesome! However, there is some conflict in Expo's and Gatsby's webpack definitions config which results in
process.env.NODE_ENV
being set to the string "development" in gatsby-ssr.js and in plugins when running gatsby production builds. Workaround:Hi,
I'm maintaining the plugin, can you open an issue about this problem?
I'm not totally able to understand, how is it causing troubles? Does it use react development mode even in production build?
Problem1:
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
at instanceOf (/Users/xxx/projects/expo_boilerplate/node_modules/gatsby-recipes/node_modules/graphql/jsutils/instanceOf.js:28:13)
at isInputObjectType (/Users/xxx/projects/expo_boilerplate/node_modules/gatsby-recipes/node_modules/graphql/type/definition.js:168:34)
at typeMapReducer (/Users/xxx/projects/expo_boilerplate/node_modules/gatsby-recipes/node_modules/graphql/type/schema.js:290:41)
at Array.reduce ()
at typeMapReducer (/Users/xxx/projects/expo_boilerplate/node_modules/gatsby-
recipes/node_modules/graphql/type/schema.js:285:34)
at Array.reduce ()
at new GraphQLSchema (/Users/xxx/projects/expo_boilerplate/node_modules/gatsby-recipes/node_modules/graphql/type/schema.js:145:28)
at Object. (/Users/keung/projects/expo_boilerplate/node_modules/gatsby-recipes/dist/graphql-server/server.js:25614:18)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
Problem2:
hot update was not successful
hot update failed for module "./.cache/app.js". Last file processed: "./.cache/root.js".
Problem3:
"gatsby-plugin-react-native-web": "^3.1.0"
"gatsby": "2.0.0",
it only works on 2.0.0, not 3.0.0
Amazing stuff Evan! I can't wait to try this out.
Great stuff as always @evanbacon
Amazing.
Thank you.
I didint got it. why did You choose Expo?
He works on Expo.
Other reasons why this is cool:
I've used Expo in production for years and it's rock solid. There are a lot of people that think Expo is somehow inferior to a vanilla React Native project. It's mostly the same stuff, and unlike many other frameworks, Expo makes it pretty easy to "eject" if you need it.