Skip to content
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

[v4] compile nextra/components, nextra/hooks and nextra-theme-blog source code with react-compiler #3742

Merged
merged 58 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5faa5ca
improve
dimaMachina Nov 26, 2024
bddce10
aa
dimaMachina Nov 26, 2024
66c7f40
aa
dimaMachina Nov 26, 2024
b0268e9
aa
dimaMachina Nov 26, 2024
81599b8
aa
dimaMachina Nov 26, 2024
6d0e322
more
dimaMachina Nov 26, 2024
ceb7a96
more
dimaMachina Nov 26, 2024
489651b
more
dimaMachina Nov 26, 2024
755bece
more
dimaMachina Nov 26, 2024
cb613ee
react compiler
dimaMachina Nov 26, 2024
638fe58
react compiler
dimaMachina Nov 26, 2024
8ebf255
react compiler
dimaMachina Nov 26, 2024
3d99511
react com
dimaMachina Nov 26, 2024
e7cd60b
react com
dimaMachina Nov 26, 2024
73e0dcb
react compiler
dimaMachina Nov 26, 2024
6a44593
react com
dimaMachina Nov 26, 2024
e5859d6
react com
dimaMachina Nov 26, 2024
06e4f58
react compiler
dimaMachina Nov 26, 2024
eb03aa9
react com
dimaMachina Nov 26, 2024
17626f8
more
dimaMachina Nov 26, 2024
6b5c888
react com
dimaMachina Nov 26, 2024
be30672
react com
dimaMachina Nov 26, 2024
065f952
react com
dimaMachina Nov 26, 2024
2bced6e
react com
dimaMachina Nov 26, 2024
a9509d0
react com
dimaMachina Nov 26, 2024
da71979
aa
dimaMachina Nov 26, 2024
8e07320
aa
dimaMachina Nov 26, 2024
15193fe
aa
dimaMachina Nov 26, 2024
e6ae847
aa
dimaMachina Nov 26, 2024
c1a25ad
better name
dimaMachina Nov 26, 2024
1346d27
fix build
dimaMachina Nov 26, 2024
4080732
fix xx
dimaMachina Nov 26, 2024
5d3a310
moreee
dimaMachina Nov 26, 2024
34650a3
moreee
dimaMachina Nov 26, 2024
e4bfa39
Update packages/nextra/src/client/mdx-components/pre/copy-to-clipboar…
dimaMachina Nov 26, 2024
bd06009
should log on windows now
dimaMachina Nov 26, 2024
a9d8d8f
missed this
dimaMachina Nov 26, 2024
8256cc4
check with use 'use no memo' comments either files were optimized or not
dimaMachina Nov 27, 2024
843e096
more
dimaMachina Nov 27, 2024
1b82cd7
more
dimaMachina Nov 27, 2024
e38ae3f
more
dimaMachina Nov 27, 2024
e8b0681
more
dimaMachina Nov 27, 2024
50d5d40
more
dimaMachina Nov 27, 2024
e45c95a
more
dimaMachina Nov 27, 2024
8991c58
more
dimaMachina Nov 27, 2024
6e8718b
more
dimaMachina Nov 27, 2024
48251c1
more
dimaMachina Nov 27, 2024
bf73ecd
more
dimaMachina Nov 27, 2024
64351a8
more
dimaMachina Nov 27, 2024
4f22e63
more
dimaMachina Nov 27, 2024
50db331
more
dimaMachina Nov 27, 2024
19cd949
more
dimaMachina Nov 27, 2024
6203409
more
dimaMachina Nov 27, 2024
22ac642
more
dimaMachina Nov 27, 2024
7f114c2
yoyo
dimaMachina Nov 27, 2024
fa1373d
pnpm dedupe
dimaMachina Nov 27, 2024
1f83666
aa
dimaMachina Nov 27, 2024
c53ee9b
`react-compiler-runtime` should be direct dependency for nextra/nextr…
dimaMachina Nov 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/violet-walls-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'nextra': minor
---

compile `nextra/components`, `nextra/hooks`, `nextra-theme-docs` and `nextra-theme-blog` source code with react-compiler
16 changes: 15 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const TAILWIND_CONFIG = {
}
}

const REACT_COMPILER_RESTRICT = {
name: 'react',
importNames: ['memo', 'useCallback', 'useMemo', 'forwardRef']
}

/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
Expand Down Expand Up @@ -144,6 +149,14 @@ module.exports = {
]
}
},
{
files: ['packages/**'],
plugins: ['eslint-plugin-react-compiler'],
rules: {
'no-restricted-imports': ['error', REACT_COMPILER_RESTRICT],
'react-compiler/react-compiler': 'error'
}
},
// ⚙️ nextra-theme-docs
{
...TAILWIND_CONFIG,
Expand All @@ -166,7 +179,8 @@ module.exports = {
...TAILWIND_CONFIG.rules,
'no-restricted-imports': [
'error',
{ name: 'next/link', message: 'Use `<Anchor>` instead' }
{ name: 'next/link', message: 'Use `<Anchor>` instead' },
REACT_COMPILER_RESTRICT
],
// False positive due Tailwind CSS v4
'tailwindcss/no-custom-classname': 'off'
Expand Down
11 changes: 3 additions & 8 deletions docs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextraLogo, VercelLogo } from '@components/icons'
import cn from 'clsx'
import type { Metadata, Viewport } from 'next'
import { Footer, Layout, Link, Navbar } from 'nextra-theme-docs'
import { Footer, Layout, Navbar } from 'nextra-theme-docs'
import { Banner, Head } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import type { FC, ReactNode } from 'react'
Expand Down Expand Up @@ -56,13 +56,8 @@ const RootLayout: FC<{
children: ReactNode
}> = async ({ children }) => {
const banner = (
<Banner storageKey="4.0-release">
<div className="before:content-['🎉_']">
Nextra 4.0 is released.{' '}
<Link href="#" className="after:content-['_→']">
Read more
</Link>
</div>
<Banner dismissible={false}>
🚧 This is WIP documentation for Nextra 4.0
</Banner>
)
const navbar = (
Expand Down
2 changes: 1 addition & 1 deletion docs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const IndexPage: FC = () => {
</Link>
</p>
</div>
<div className="features-container x:border-b bordered">
<div className="features-container x:border-b nextra-border">
<div className="content-container">
<Features>
<Feature
Expand Down
2 changes: 1 addition & 1 deletion examples/blog/app/tags/[tag]/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default async function TagPage(props) {
const params = await props.params
return (
<>
<h1>{generateMetadata({ params }).title}</h1>
<h1>{(await generateMetadata({ params })).title}</h1>
{(await getPosts())
.filter(post =>
post.frontMatter.tags.includes(decodeURIComponent(params.tag))
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"eslint-plugin-deprecation": "3.0.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-react": "7.37.2",
"eslint-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
"eslint-plugin-react-hooks": "5.0.0",
"eslint-plugin-sonarjs": "^2.0.4",
"eslint-plugin-tailwindcss": "3.17.3",
Expand Down
27 changes: 27 additions & 0 deletions packages/esbuild-react-compiler-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "esbuild-react-compiler-plugin",
"version": "0.0.0",
"type": "module",
"description": "",
"author": "Dimitri POSTOLOV",
"license": "ISC",
"private": true,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./package.json": "./package.json"
},
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsup",
"dev": "tsup --watch"
},
"dependencies": {
"react-compiler-webpack": "0.1.2"
},
"devDependencies": {
"@types/node": "^22.0.0"
}
}
5 changes: 5 additions & 0 deletions packages/esbuild-react-compiler-plugin/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module 'react-compiler-webpack/dist/react-compiler-loader.js' {
export default function reactCompilerLoader(
source: string | Buffer
): Promise<void>
}
64 changes: 64 additions & 0 deletions packages/esbuild-react-compiler-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import fs from 'node:fs/promises'
import path from 'node:path'
import reactCompilerLoader from 'react-compiler-webpack/dist/react-compiler-loader.js'
import type { Options } from 'tsup'

const reactCompilerConfig = {
sources(_filename: string) {
return true
},
target: '18'
}

export const reactCompilerPlugin = (
filter: RegExp
): NonNullable<Options['esbuildPlugins']>[number] => ({
name: 'react-compiler',
setup(build) {
build.onLoad({ filter }, async args => {
// Read the file content
const code = await fs.readFile(args.path)
return new Promise<{
contents: string
loader: 'ts' | 'tsx'
}>((resolve, reject) => {
function callback(error: Error | null, result?: string) {
if (!result) {
reject(error)
return
}
// Mark the file as a ts/tsx file
const loader = path.extname(args.path).slice(1) as 'ts' | 'tsx'
const relativePath = path.relative(process.cwd(), args.path)

if (
/^import \{ c as _c } from "react-compiler-runtime";/m.test(result)
) {
console.info(
'🚀 File',
relativePath,
'was optimized with react-compiler'
)
} else if (!/^'use no memo'/m.test(result)) {
console.error(
'❌ File',
relativePath,
'was not optimized with react-compiler'
)
}

resolve({ contents: result, loader })
}

reactCompilerLoader.call(
{
async: () => callback,
getOptions: () => reactCompilerConfig,
resourcePath: args.path
},
code
)
})
})
}
})
16 changes: 16 additions & 0 deletions packages/esbuild-react-compiler-plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es2022",
"module": "ESNext",
"declaration": true,
"noEmit": true,
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"strictNullChecks": true,
"lib": ["esnext", "dom"],
"moduleResolution": "node",
"resolveJsonModule": true
},
"exclude": ["dist"]
}
11 changes: 11 additions & 0 deletions packages/esbuild-react-compiler-plugin/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from 'tsup'
import packageJson from './package.json'

export default defineConfig({
name: packageJson.name,
entry: ['src/**/*.ts'],
format: 'esm',
dts: true,
splitting: process.env.NODE_ENV === 'production',
bundle: false
})
4 changes: 3 additions & 1 deletion packages/nextra-theme-blog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
},
"dependencies": {
"next-themes": "^0.4.0",
"next-view-transitions": "^0.3.0"
"next-view-transitions": "^0.3.0",
"react-compiler-runtime": "19.0.0-beta-df7b47d-20241124"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.0.0-beta.2",
"@tailwindcss/typography": "^0.5.15",
"@types/react": "^18.2.23",
"esbuild-react-compiler-plugin": "workspace:*",
"next": "^15.0.2",
"nextra": "workspace:*",
"postcss": "^8.4.33",
Expand Down
9 changes: 6 additions & 3 deletions packages/nextra-theme-blog/src/components/cusdis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ export const Comments: FC<{
useEffect(() => {
try {
// update the theme for the cusdis iframe when theme changed
window.CUSDIS?.setTheme(resolvedTheme as 'dark' | 'light')
if (window.CUSDIS) {
// window.CUSDIS? doesn't work with react-compiler
window.CUSDIS.setTheme(resolvedTheme as 'dark' | 'light')
}
} catch (error) {
console.error(error)
}
}, [resolvedTheme])

if (!appId) {
console.warn('[nextra/cusdis] `appId` is required')
return
return null
}
if (!mounted) {
return
return null
}

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/nextra-theme-blog/src/components/go-back.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const GoBack: FC = () => {
const segments = usePathname().split('/')

const isNestedPage = segments.length > 2
if (!isNestedPage) return
if (!isNestedPage) return null
return (
<Button
onClick={router.back}
Expand Down
2 changes: 2 additions & 0 deletions packages/nextra-theme-blog/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo'

export { Comments } from './cusdis'
export { Layout, Footer } from './layout'
export { Navbar } from './navbar'
Expand Down
13 changes: 4 additions & 9 deletions packages/nextra-theme-blog/src/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { PageMapItem } from 'nextra'
import { useFSRoute } from 'nextra/hooks'
import { normalizePages } from 'nextra/normalize-pages'
import type { FC, ReactNode } from 'react'
import { useMemo } from 'react'

type NavbarProps = {
children?: ReactNode
Expand All @@ -14,14 +13,10 @@ type NavbarProps = {

export const Navbar: FC<NavbarProps> = ({ children, pageMap }) => {
const pathname = useFSRoute()
const { topLevelNavbarItems } = useMemo(
() =>
normalizePages({
list: pageMap,
route: pathname
}),
[pageMap, pathname]
)
const { topLevelNavbarItems } = normalizePages({
list: pageMap,
route: pathname
})
return (
<header
className="x:mb-8 x:flex x:items-center x:gap-3 x:justify-end"
Expand Down
2 changes: 2 additions & 0 deletions packages/nextra-theme-blog/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo'

export { useMDXComponents } from './mdx-components'
export {
Comments,
Expand Down
2 changes: 2 additions & 0 deletions packages/nextra-theme-blog/src/is-valid-date.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo'

const DATE_RE = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2})?(:\d{2}\.\d{3}Z)?$/
const DATE_RE_WITH_SLASH = /^\d{4}\/\d{1,2}\/\d{1,2}( \d{1,2}:\d{1,2})?$/

Expand Down
3 changes: 3 additions & 0 deletions packages/nextra-theme-blog/src/mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// should be used on server
'use no memo'

/* eslint sort-keys: error */
import {
Callout,
Expand Down
2 changes: 2 additions & 0 deletions packages/nextra-theme-blog/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use no memo'

/* eslint typescript-sort-keys/interface: error */
import type { ReadingTime } from 'nextra'

Expand Down
1 change: 1 addition & 0 deletions packages/nextra-theme-blog/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"strictNullChecks": true,
"jsx": "react-jsx",
"moduleResolution": "bundler",
"types": ["vitest/globals"]
Expand Down
6 changes: 4 additions & 2 deletions packages/nextra-theme-blog/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { reactCompilerPlugin } from 'esbuild-react-compiler-plugin'
import { defineConfig } from 'tsup'
import { defaultEntry } from '../nextra-theme-docs/tsup.config'
import packageJson from './package.json'

export default defineConfig([
{
name: packageJson.name,
entry: [...defaultEntry, '!src/types.ts'],
entry: defaultEntry,
format: 'esm',
dts: true,
outExtension: () => ({ js: '.js' }),
bundle: false
bundle: false,
esbuildPlugins: [reactCompilerPlugin(/\.tsx?$/)]
},
{
name: `${packageJson.name}/css`,
Expand Down
2 changes: 2 additions & 0 deletions packages/nextra-theme-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@headlessui/react": "^2.1.2",
"clsx": "^2.1.0",
"next-themes": "^0.4.0",
"react-compiler-runtime": "19.0.0-beta-df7b47d-20241124",
"scroll-into-view-if-needed": "^3.1.0",
"zod": "^3.22.3",
"zod-validation-error": "^3.0.0",
Expand All @@ -43,6 +44,7 @@
"@testing-library/react": "^16.0.0",
"@types/react": "^18.2.23",
"@vitejs/plugin-react": "^4.1.0",
"esbuild-react-compiler-plugin": "workspace:*",
"jsdom": "^25.0.0",
"next": "^15.0.2",
"nextra": "workspace:*",
Expand Down
4 changes: 2 additions & 2 deletions packages/nextra-theme-docs/src/components/404/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type NotFoundPageProps = {
export const NotFoundPage: FC<NotFoundPageProps> = ({
content = 'Submit an issue about broken link',
labels = 'bug',
children = <H1>404: Page Not Found</H1>,
children,
className
}) => {
return (
Expand All @@ -23,7 +23,7 @@ export const NotFoundPage: FC<NotFoundPageProps> = ({
className
)}
>
{children}
{children || <H1>404: Page Not Found</H1>}
<NotFoundLink labels={labels}>{content}</NotFoundLink>
</div>
)
Expand Down
Loading