-
Notifications
You must be signed in to change notification settings - Fork 195
(docs) add Next.js setup instructions #343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,9 @@ slug: /learn/setup | |
|
|
||
| <p className="text-xl">Learn how to configure the environment needed to use React Strict DOM.</p> | ||
|
|
||
| * [Expo framework](#expo-framework) - Configure React Strict DOM in an Expo app. | ||
| * [Next.js framework](#nextjs-framework) - Configure React Strict DOM in a Next.js website using App Router. | ||
|
|
||
| ## Expo framework | ||
|
|
||
| [Expo](https://expo.dev/) is a production-grade, cross-platform React framework that is the recommended solution for creating apps with React Strict DOM. The instructions in the rest of this guide are tailored to Expo, but can be adapted by readers to work with other frameworks. | ||
|
|
@@ -147,8 +150,174 @@ export function App() { | |
| } | ||
| ``` | ||
|
|
||
| ## Next.js framework | ||
|
|
||
| [Next.js](https://nextjs.org) is a production-grade, web oriented React framework that is the recommended solution that takes full advantage of React’s architecture to enable full-stack React app. Fully compatible with React Strict DOM. The instructions in the rest of this guide are tailored to Next.js, but can be adapted by readers to work with other frameworks. | ||
|
|
||
| Follow the Next.js instructions on how to [create a new project](https://nextjs.org/docs/app/getting-started/installation). Then follow the steps in the [Installation](/learn/installation) guide to install React Strict DOM. | ||
|
|
||
| ## Babel configuration | ||
|
|
||
| When using Next.js App Router, babel is not the default compiler, but can still be used. | ||
| Create or modify a `babelLoader.config.js` file as follows (note that it's not a `babel.config.js`). This is used to optimize builds and enables static extraction of CSS for web. Learn how to configure the [babel-preset](/api/babel-preset/) in the API docs. | ||
|
|
||
| ```js title="babelLoader.config.js" | ||
| import path from "path"; | ||
|
|
||
| const config = { | ||
| presets: [ | ||
| [ | ||
| "next/dist/compiled/babel/preset-typescript", | ||
| { | ||
| allowNamespaces: true, | ||
| }, | ||
| ], | ||
| [ | ||
| "react-strict-dom/babel-preset", | ||
| { | ||
| debug: true, | ||
| dev: process.env.NODE_ENV === "development", | ||
| rootDir: process.cwd(), | ||
| // if you want to use @/* from tsconfig | ||
| // a patch is required in node_modules/react-strict-dom/babel/preset.js | ||
| // see https://github.com/facebook/react-strict-dom/pull/294 for more information | ||
| // aliases: { | ||
| // "@/*": [path.join(process.cwd(), "*")], | ||
| // }, | ||
| }, | ||
| ], | ||
| ], | ||
| }; | ||
|
|
||
| export default config; | ||
|
|
||
| ``` | ||
|
|
||
| ## PostCSS configuration | ||
|
|
||
| [PostCSS](https://postcss.org/) is a tool for generating CSS. It's enabled by default in Next.js and it's the recommended way to extract React Strict DOM styles to static CSS for web builds. `react-strict-dom/postcss-plugin` can be used to extract styles. Create a `postcss.config.mjs` file as follows. | ||
|
|
||
| ```js title="postcss.config.mjs" | ||
| // note that you need to import manually the babel loader so configuration is shared between next.js & postcss compilation | ||
| import babelLoader from "./babelLoader.config.js"; | ||
|
|
||
| const config = { | ||
| plugins: { | ||
| "react-strict-dom/postcss-plugin": { | ||
| include: [ | ||
| // Include source files to watch for style changes | ||
| 'src/**/*.{js,jsx,mjs,ts,tsx}', | ||
| // List any installed node_modules that include UI built with React Strict DOM | ||
| 'node_modules/<package-name>/*.js' | ||
| ], | ||
| babelConfig: babelLoader, | ||
| useLayers: true, | ||
| }, | ||
| autoprefixer: {}, | ||
| }, | ||
| }; | ||
|
|
||
| export default config; | ||
| ``` | ||
|
|
||
| ## Next.js configuration | ||
|
|
||
| Create or edit the `next.config.js` file as follows. Note that below you will find config for both turbopack or webpack. | ||
|
|
||
| ```js title="next.config.js" | ||
| import type { NextConfig } from "next"; | ||
|
|
||
| import babelLoader from "./babelLoader.config.js"; | ||
|
|
||
| function getBabelLoader() { | ||
| return { | ||
| loader: "babel-loader", | ||
| options: babelLoader, | ||
| }; | ||
| } | ||
|
|
||
| const nextConfig: NextConfig = { | ||
| transpilePackages: ["react-strict-dom"], | ||
|
|
||
| turbopack: { | ||
| rules: { | ||
| "*.{js,jsx,ts,tsx}": { | ||
| loaders: [getBabelLoader()], | ||
| }, | ||
| }, | ||
| }, | ||
|
|
||
| webpack: (config, { webpack }) => { | ||
| config.resolve.mainFields = ["module", "main"]; | ||
|
|
||
| config.module.rules.push({ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add exclude: /node_modules(?!\/react-strict-dom)/, |
||
| test: /\.(js|jsx|ts|tsx)$/, | ||
| use: [getBabelLoader()], | ||
| }); | ||
|
|
||
| return config; | ||
| }, | ||
| }; | ||
|
|
||
| export default nextConfig; | ||
| ``` | ||
|
|
||
| ## App files | ||
|
|
||
| Your app needs to include a CSS file that contains a `@stylex` directive. This acts as a placeholder that is replaced by the generated CSS during builds. | ||
|
|
||
| ```css title="stylex.css" | ||
| /* This directive is used by the react-strict-dom postcss plugin. */ | ||
| /* It is automatically replaced with generated CSS during builds. */ | ||
| @stylex; | ||
| ``` | ||
|
|
||
| Next, import the CSS file in your `layout.tsx` | ||
|
|
||
| ```js title="src/app/layout.tsx" | ||
| // Required for CSS to work on Next.js | ||
| import './stylex.css'; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: { | ||
| children: React.ReactNode | ||
| }) { | ||
| return ( | ||
| <html lang="en"> | ||
| <body>{children}</body> | ||
| </html> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| ## Platform-specific files | ||
|
|
||
| Expo supports [platform-specific extensions](https://docs.expo.dev/router/advanced/platform-specific-modules/#platform-specific-extensions) by default. This allows you to create platform-specific implementations of components, hooks, etc. | ||
|
|
||
| Other frameworks will require bundler configuration when building for each platform, so as to resolve files based on their file extensions. For example, web bundles should package `*.web.js` file extensions but not `*.native.js` files. These specific file name suffixes are recommended conventions already used by the React Native ecosystem (see the Expo docs above.) | ||
|
|
||
| For example, Next.js can easily handle platform-specific extensions with a change in `next.config.js` with the following additions: | ||
|
|
||
| ```js title="next.config.js" | ||
| //... | ||
|
|
||
| const nextConfig: NextConfig = { | ||
| // ... | ||
|
|
||
| turbopack: { | ||
| // ... | ||
|
|
||
| resolveExtensions: [".web.tsx", ".web.ts", ".web.jsx", ".web.js", ".tsx", ".ts", ".jsx", ".js", ".mjs", ".json"], | ||
| }, | ||
|
|
||
| webpack: (config, { webpack }) => { | ||
| // ... | ||
|
|
||
| config.resolve.extensions = [ ".web.js", ".web.jsx", ".web.ts", ".web.tsx", ...config.resolve.extensions]; | ||
| return config; | ||
| }, | ||
| }; | ||
|
|
||
| export default nextConfig; | ||
| ``` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line might not be necessary. We started using Turbopack for development at our company(not Meta) and so far we are using the below config without that line.
Note that there is currently a bug in Next.js that prevents Turbpack loader from running when
middleware.tsexists.We are working around this limitation by excluding top-level
src/*.{ts,tsx}files from being compiled with babel-loader, but this is specific to our setup and probably isn't something we want to recommend here.foreign: trueis meant to exclude node_modules etc but I'm not too sure if this config is correct as it's not documented well. Just something we added to make it work.