@expo/next-adapter

中文文档
6.0.0发布于 2024/01/08MITTypeScriptCommonJS零依赖近 30 天下载 14.4万

Adapter for using Next.js to bundle Expo web projects

原始使用文档
文档目录9 节
  1. Setup
  2. Dependencies
  3. Transpilation
  4. Next.js configuration
  5. React Native Web styling
  6. Transpiling modules
  7. Notice
  8. Troubleshooting
  9. Cannot use import statement outside a module

👋 Welcome to
@expo/next-adapter

Next.js plugin for using React Native modules


⚠️ Warning: Support for Next.js is unofficial and not a first-class Expo feature.

Setup

Dependencies

Ensure you have expo, next, @expo/next-adapter installed in your project.

Transpilation

Configure Next.js to transform language features:

Next.js with swc. (Recommended)

When using Next.js with SWC, you can configure the babel.config.js to only account for native.

// babel.config.js
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
  };
};

You will also have to force Next.js to use SWC by adding the following to your next.config.js:

// next.config.js
module.exports = {
  experimental: {
    forceSwcTransforms: true,
  },
};
Next.js with Babel. (Not recommended)

Adjust your babel.config.js to conditionally add next/babel when bundling with Webpack for web.

// babel.config.js
module.exports = function (api) {
  // Detect web usage (this may change in the future if Next.js changes the loader)
  const isWeb = api.caller(
    caller =>
      caller && (caller.name === 'babel-loader' || caller.name === 'next-babel-turbo-loader')
  );
  return {
    presets: [
      // Only use next in the browser, it'll break your native project
      isWeb && require('next/babel'),
      'babel-preset-expo',
    ].filter(Boolean),
  };
};

Next.js configuration

Add the following to your next.config.js:

const { withExpo } = require('@expo/next-adapter');

module.exports = withExpo({
  // transpilePackages is a Next.js +13.1 feature.
  // older versions can use next-transpile-modules
  transpilePackages: [
    'react-native',
    'expo',
    // Add more React Native / Expo packages here...
  ],
});

The fully qualified Next.js config may look like:

const { withExpo } = require('@expo/next-adapter');

/** @type {import('next').NextConfig} */
const nextConfig = withExpo({
  reactStrictMode: true,
  swcMinify: true,
  transpilePackages: [
    'react-native',
    'expo',
    // Add more React Native / Expo packages here...
  ],
  experimental: {
    forceSwcTransforms: true,
  },
});

module.exports = nextConfig;

React Native Web styling

The package react-native-web builds on the assumption of reset CSS styles, here's how you reset styles in Next.js using the pages/ directory.

Required pages/_document.js file
import { Children } from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { AppRegistry } from 'react-native';

// Follows the setup for react-native-web:
// https://necolas.github.io/react-native-web/docs/setup/#root-element
// Plus additional React Native scroll and text parity styles for various
// browsers.
// Force Next-generated DOM elements to fill their parent's height
const style = `
html, body, #__next {
  -webkit-overflow-scrolling: touch;
}
#__next {
  display: flex;
  flex-direction: column;
  height: 100%;
}
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}
body {
  /* Allows you to scroll below the viewport; default value is visible */
  overflow-y: auto;
  overscroll-behavior-y: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -ms-overflow-style: scrollbar;
}
`;

export default class MyDocument extends Document {
  static async getInitialProps({ renderPage }) {
    AppRegistry.registerComponent('main', () => Main);
    const { getStyleElement } = AppRegistry.getApplication('main');
    const page = await renderPage();
    const styles = [
      <style key="react-native-style" dangerouslySetInnerHTML={{ __html: style }} />,
      getStyleElement(),
    ];
    return { ...page, styles: Children.toArray(styles) };
  }

  render() {
    return (
      <Html style={{ height: '100%' }}>
        <Head />
        <body style={{ height: '100%', overflow: 'hidden' }}>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
Required pages/_app.js file
import Head from 'next/head';

export default function App({ Component, pageProps }) {
  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </Head>
      <Component {...pageProps} />
    </>
  );
}

Transpiling modules

By default, modules in the React Native ecosystem are not transpiled to run in web browsers. React Native relies on advanced caching in Metro to reload quickly. Next.js uses Webpack, which does not have the same level of caching, so by default, no node modules are transpiled. You will have to manually mark every module you want to transpile with the transpilePackages option in next.config.js:

const { withExpo } = require('@expo/next-adapter');

module.exports = withExpo({
  experimental: {
    transpilePackages: [
      // NOTE: Even though `react-native` is never used in Next.js,
      // you need to list `react-native` because `react-native-web`
      // is aliased to `react-native`. Adding `react-native-web` will not work.
      'react-native',
      'expo',
      // Add more React Native / Expo packages here...
    ],
  },
});

Notice

Using Next.js for the web means you will be bundling with the Next.js Webpack config. This will lead to some core differences in how you develop your app vs your website.

Troubleshooting

Cannot use import statement outside a module

Figure out which module has the import statement and add it to the transpilePackages option in next.config.js:

const { withExpo } = require('@expo/next-adapter');

module.exports = withExpo({
  experimental: {
    transpilePackages: [
      'react-native',
      'expo',
      // Add failing package here, and restart the server...
    ],
  },
});

版本与发布记录

@expo/next-adapter 共发布 181 个版本,首次发布于 2019/10/16;过去 12 个月发布了 0 个版本。

版本发布日期距今
6.0.0latest2024/01/082 年前
5.0.22023/02/073 年前
5.0.12023/01/283 年前
5.0.02023/01/053 年前
4.0.132022/11/014 年前
4.0.122022/08/124 年前

其他发布通道:alpha → 2.1.62-alpha.0。

关于 @expo/next-adapter 的常见问题

@expo/next-adapter 是什么?

Adapter for using Next.js to bundle Expo web projects

如何安装 @expo/next-adapter?

在项目目录运行 npm install @expo/next-adapter,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:expo(>=46)、webpack(^4.46.0 || ^5.74.0)、react-native-web(^0.18 || ^0.19)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@expo/next-adapter 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@expo/next-adapter 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@expo/next-adapter 可以商用吗?

@expo/next-adapter 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@expo/next-adapter 的下载量有多少?

根据 npm 官方下载统计,@expo/next-adapter 在 2026/10/14 – 2026/11/12 这 30 天内被下载 144,100 次,日均约 4,803 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@expo/next-adapter 还在维护吗?

最新版本 6.0.0 发布于 2024/01/08(2 年前);至今共发布 181 个版本,其中过去 12 个月发布了 0 个;首次发布于 2019/10/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。