Install the Compiler

Adding the compiler to your apps.

For first-timers, we recommend skipping to Configuration and not setting up the compiler until you've gotten familiar. The compiler takes time to set up and is usually only useful in production.

The Tamagui Compiler has plugins available for Webpack, Vite, and Metro (via babel). It also have a specific guide you can follow for Next.js.

Webpack

yarn add tamagui-loader

We have a full example of a plain, webpack-only repo here , which should capture the complete configuration more accurately.

Add tamagui-loader and set up your webpack.config.js:

const { shouldExclude } = require('tamagui-loader')
const tamaguiOptions = {
config: './tamagui.config.ts',
components: ['tamagui'],
importsWhitelist: ['constants.js', 'colors.js'],
logTimings: true,
disableExtraction: process.env.NODE_ENV === 'development',
}
const projectRoot = __dirname
module.exports = {
resolve: {
alias: {
// Resolve react-native to react-native-web
'react-native$': require.resolve('react-native-web'),
'react-native-web$': require.resolve('react-native-web'),
// @tamagui/rnw exports a couple internal hooks from react-native-web
// resolve both to CommonJS so they match
'@tamagui/rnw': require.resolve('@tamagui/rnw'),
// optional, for svg icons
'react-native-svg': require.resolve('@tamagui/react-native-svg'),
}
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
// you'll likely want to adjust this helper function,
// but it serves as a decent start that you can copy/paste from
exclude: path => shouldExclude(path, projectRoot, tamaguiOptions),
use: [
// optionally thread-loader for significantly faster compile!
'thread-loader',
// works nicely alongside esbuild
{
loader: 'esbuild-loader',
options: {
loader: 'tsx',
minify: process.env.NODE_ENV === 'production',
},
},
{
loader: 'tamagui-loader',
options: tamaguiOptions,
},
]
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.TAMAGUI_TARGET': '"web"',
})
]
}
  • importsWhitelist: Tamagui takes a conservative approach to partial evaluation, this field whitelists (matching against both .ts and .js) files to allow files that import them to read and use their values during compilation. Typically colors and constants files.
  • disableExtaction: Useful for faster developer iteration as themes hot reload more reliably.

Next.js

Add @tamagui/next-plugin and configure your next.config.js.

// note next-compose-plugins somewhat unmaintained
// you can use a simple two-liner instead, see:
// https://github.com/cyrilwanner/next-compose-plugins/issues/59#issuecomment-1192523231
const withPlugins = require('next-compose-plugins')
const { withTamagui } = require('@tamagui/next-plugin')
export default withPlugins([
// All options shows are optional, except config:
withTamagui({
// Path to your tamagui.config.ts file:
config: './tamagui.config.ts',
// Your design system (default: "tamagui")
components: ['tamagui'],
// Follow normalized imports matching these file names, attempt to evaluate
// their exports for static extraction
importsWhitelist: ['constants.js', 'colors.js'],
// display detailed output (default true)
logTimings: true,
// disable static extraction, faster to iterate in dev mode (default false)
disableExtraction: process.env.NODE_ENV === 'development',
// disableExtraction only disables optimizations but keeps the debug ability and output
// if you want faster builds, you can disable tamagui entirely with this (default false)
disable: false,
// Exclude react-native-web modules to lighten bundle
excludeReactNativeWebExports: ['Switch', 'ProgressBar', 'Picker'],
// The following options are for more unusual configurations
// By default, we configure webpack to pass anything inside your root or design system
// to the Tamagui loader. If you are importing files from an external package, use this:
shouldExtract: (path: string, projectRoot: string) => {
if (path.includes('../packages/myapp')) {
return true
}
},
// Many packages give difficulty to the nextjs server-side (node) runtime when un-bundled.
// for example, tamagui configures aliases like `react-native` => `react-native-web`.
// if you're running into a module that has errors importing react-native, you'll want to
// use a custom shouldExcludeFromServer function to include it (or override the default).
// this is the exact same return type as webpack.externals.
// returning undefined will let tamagui handle it, boolean or other values to override.
shouldExcludeFromServer: ({ fullPath, request }) => {
if (fullPath.includes('my-module')) {
return `commonjs ${commonjs}`
}
if (request === 'some-hard-to-bundle-package') {
return true
}
}
})
])

Note: If running into issues, the environment variable IGNORE_TS_CONFIG_PATHS to "true" can fix issues with Tamagui being resolved incorrectly.

See the Next.js Guide for more details on setting up your app.

React Native (Metro)

yarn add @tamagui/babel-plugin

Add @tamagui/babel-plugin to your babel.config.js plugins:

// only use babel-plugin for native:
process.env.TAMAGUI_TARGET = 'native'
module.exports = {
plugins: [
[
'@tamagui/babel-plugin',
{
components: ['tamagui'],
config: './tests/lib/tamagui.config.js',
importsWhitelist: ['constants.js', 'colors.js'],
logTimings: true,
disableExtraction: process.env.NODE_ENV === 'development',
}
],
// be sure to set TAMAGUI_TARGET
['transform-inline-environment-variables', {
include: 'TAMAGUI_TARGET'
}]
]
}

We've noticed some issues with @types/react-native version 0.65.5, you'll want to upgrade to at least 0.66.6.

Ensure unimodules support using the old method , or the expo package .

Tamagui uses @expo/match-media and expo-linear-gradient, so you'll want expo installed to support their modules. Add expo-linear-gradient and expo-screen-orientation sub-dependencies to your package.json.

Expo

Check out the Expo guide for more information on setting up Expo.

Compiler options

The webpack loader and Next.js plugin accept the same configuration options:

Props

  • config (required)

    string

    Relative path to your tamagui.config.ts file which should export default the result from createTamagui.

  • components

    string[]

    Default: 

    ['tamagui']

    Array of npm modules containing Tamagui components which youll be using in your app. For example: if you are using the base Tamagui components. This directs the compiler to load and optimize.

  • importsWhitelist

    string[]

    Array of whitelisted file paths (always end in .js) which the compiler may try and import and parse at build-time. It is normalized to ".js" ending for all file extensions (js, jsx, tsx, ts). This usually should be set to something like ['constants.js', 'colors.js'] for example, where you have a couple mostly static files of constants that are used as default values for styles.

  • logTimings

    boolean

    Default: 

    Tamagui outputs information for each file it compiles on how long it took to run, how many components it optimized, and how many it flattened. Set to false to disable these logs.

  • disableExtraction

    boolean

    Disable extraction to CSS completely, instead fully relying on runtime. Setting this to true speed up development as generally your app will hot reload the Tamagui configuration itself.

  • disableDebugAttr

    boolean

    If enabled along with disableExtraction, all parsing will turn off. Normally turning off disableExtraction will keep the helpful debug attributes in DOM

  • Web-only configurations

    If you want autocompleted imports of react-native without having to install all the weight of react-native, you can set react-native version to 0.0.0, and add @types/react-native at the latest version.