refactor(next/core): reorganize next.js custom transforms for next-swc/turbopack (#60400)
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Adding or Updating Examples
- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
-->
### What?
This PR refactors organization for the rust side packages to build
`next-swc`.
### Why?
We had some historical legacy around package structures, have ambiguous
name for `core` / `next-core`. One contains swc transform visitor for
the next.js, and the other one is new for turbopack's core next.js
features. In addition to that, there was a package dependency chain
prevents to use `core` in the turobpack / next-swc both, so each time
porting a transformer into turbopack it requires to extract new
dependency to be imported in the both place.
PR touches its organization - while PR is large to touch various files,
the crux is summarized at
2cedd06ea5
:
1. `core` becomes `next-custom-transforms`, also this becomes an
agnostic pkg can be imported in turbopack / wasm / next-swc
2. simplify dependency chain to import next-custom-transforms, organized
as below
```mermaid
flowchart TD
C(next-custom-transforms) --> A(napi)
C(next-custom-transforms) --> B(wasm)
D(next-core) --> A(napi)
E(next-build) --> A(napi)
F(next-api) --> A(napi)
C(next-custom-transforms) --> D
D(next-core) --> F(next-api)
D(next-core) --> E(next-build)
```
`impl CustomTransformer` for the each transform still lives in
`next-core`, so turbopack specific dependency is isolated under
`next-core/build/api`.
Closes PACK-2201
Closes PACK-2202
---------
Co-authored-by: hrmny <8845940+ForsakenHarmony@users.noreply.github.com>
This commit is contained in:
parent
7018a65de4
commit
46370d816b
708 changed files with 612 additions and 2085 deletions
25
.github/workflows/build_and_test.yml
vendored
25
.github/workflows/build_and_test.yml
vendored
|
@ -119,29 +119,6 @@ jobs:
|
|||
mold: 'yes'
|
||||
secrets: inherit
|
||||
|
||||
test-cargo-integration:
|
||||
name: test cargo integration
|
||||
needs: ['changes', 'build-next']
|
||||
if: ${{ needs.changes.outputs.docs-only == 'false' }}
|
||||
|
||||
uses: ./.github/workflows/build_reusable.yml
|
||||
with:
|
||||
needsNextest: 'yes'
|
||||
needsRust: 'yes'
|
||||
skipNativeBuild: 'yes'
|
||||
afterBuild: xvfb-run turbo run test-cargo-integration
|
||||
|
||||
test-cargo-bench:
|
||||
name: test cargo benchmarks
|
||||
needs: ['changes', 'build-next']
|
||||
if: ${{ needs.changes.outputs.docs-only == 'false' || needs.changes.outputs.is-release == 'false' }}
|
||||
|
||||
uses: ./.github/workflows/build_reusable.yml
|
||||
with:
|
||||
needsRust: 'yes'
|
||||
skipNativeBuild: 'yes'
|
||||
afterBuild: xvfb-run turbo run test-cargo-bench
|
||||
|
||||
rust-check:
|
||||
name: rust check
|
||||
needs: ['changes', 'build-next']
|
||||
|
@ -373,8 +350,6 @@ jobs:
|
|||
'test-ppr-prod',
|
||||
'test-ppr-integration',
|
||||
'test-cargo-unit',
|
||||
'test-cargo-integration',
|
||||
'test-cargo-bench',
|
||||
'rust-check',
|
||||
'test-next-swc-wasm',
|
||||
'test-turbopack-dev',
|
||||
|
|
67
Cargo.lock
generated
67
Cargo.lock
generated
|
@ -3390,7 +3390,6 @@ dependencies = [
|
|||
"indexmap 1.9.3",
|
||||
"indoc",
|
||||
"next-core",
|
||||
"next-swc",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -3442,11 +3441,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"next-swc",
|
||||
"next-transform-dynamic",
|
||||
"next-transform-font",
|
||||
"next-transform-react-server-components",
|
||||
"next-transform-strip-page-exports",
|
||||
"next-custom-transforms",
|
||||
"once_cell",
|
||||
"qstring",
|
||||
"regex",
|
||||
|
@ -3461,19 +3456,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-swc"
|
||||
name = "next-custom-transforms"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"convert_case 0.5.0",
|
||||
"easy-error",
|
||||
"either",
|
||||
"fxhash",
|
||||
"hex",
|
||||
"next-transform-dynamic",
|
||||
"next-transform-font",
|
||||
"next-transform-react-server-components",
|
||||
"next-visitor-cjs-finder",
|
||||
"once_cell",
|
||||
"pathdiff",
|
||||
"react_remove_properties",
|
||||
|
@ -3483,6 +3475,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sha1 0.10.5",
|
||||
"swc_core",
|
||||
"tracing",
|
||||
"turbopack-binding",
|
||||
"walkdir",
|
||||
|
@ -3502,7 +3495,7 @@ dependencies = [
|
|||
"next-api",
|
||||
"next-build",
|
||||
"next-core",
|
||||
"next-swc",
|
||||
"next-custom-transforms",
|
||||
"once_cell",
|
||||
"sentry",
|
||||
"serde",
|
||||
|
@ -3519,54 +3512,6 @@ dependencies = [
|
|||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-transform-dynamic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pathdiff",
|
||||
"swc_core",
|
||||
"testing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-transform-font"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"swc_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-transform-react-server-components"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"next-visitor-cjs-finder",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"swc_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-transform-strip-page-exports"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
"swc_core",
|
||||
"testing",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "next-visitor-cjs-finder"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"swc_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "node-file-trace"
|
||||
version = "0.1.0"
|
||||
|
@ -8795,7 +8740,7 @@ dependencies = [
|
|||
"console_error_panic_hook",
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"next-swc",
|
||||
"next-custom-transforms",
|
||||
"once_cell",
|
||||
"parking_lot_core 0.8.0",
|
||||
"path-clean",
|
||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -3,17 +3,12 @@ resolver = "2"
|
|||
|
||||
members = [
|
||||
"scripts/send-trace-to-jaeger",
|
||||
"packages/next-swc/crates/core",
|
||||
"packages/next-swc/crates/napi",
|
||||
"packages/next-swc/crates/wasm",
|
||||
"packages/next-swc/crates/next-api",
|
||||
"packages/next-swc/crates/next-build",
|
||||
"packages/next-swc/crates/next-core",
|
||||
"packages/next-swc/crates/next-transform-font",
|
||||
"packages/next-swc/crates/next-transform-dynamic",
|
||||
"packages/next-swc/crates/next-transform-strip-page-exports",
|
||||
"packages/next-swc/crates/next-transform-react-server-components",
|
||||
"packages/next-swc/crates/next-visitor-cjs-finder",
|
||||
"packages/next-swc/crates/next-custom-transforms",
|
||||
]
|
||||
|
||||
[workspace.lints.clippy]
|
||||
|
@ -32,12 +27,7 @@ opt-level = 3
|
|||
next-api = { path = "packages/next-swc/crates/next-api", default-features = false }
|
||||
next-build = { path = "packages/next-swc/crates/next-build", default-features = false }
|
||||
next-core = { path = "packages/next-swc/crates/next-core", default-features = false }
|
||||
next-swc = { path = "packages/next-swc/crates/core" }
|
||||
next-transform-font = { path = "packages/next-swc/crates/next-transform-font" }
|
||||
next-transform-dynamic = { path = "packages/next-swc/crates/next-transform-dynamic" }
|
||||
next-transform-strip-page-exports = { path = "packages/next-swc/crates/next-transform-strip-page-exports" }
|
||||
next-transform-react-server-components = { path = "packages/next-swc/crates/next-transform-react-server-components" }
|
||||
next-visitor-cjs-finder = { path = "packages/next-swc/crates/next-visitor-cjs-finder" }
|
||||
next-custom-transforms = { path = "packages/next-swc/crates/next-custom-transforms" }
|
||||
|
||||
# SWC crates
|
||||
swc_core = { version = "0.87.16", features = [
|
||||
|
|
|
@ -24,3 +24,35 @@ Build the binary to integrate with next.js
|
|||
```
|
||||
pnpm build-native
|
||||
```
|
||||
|
||||
Build wasm bindings to integrate with next.js
|
||||
|
||||
```
|
||||
pnpm build-wasm
|
||||
```
|
||||
|
||||
### Package hierarchies
|
||||
|
||||
`@next/swc` consist of multiple rust packages to enable features. See below for the high level hierarchies.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
C(next-custom-transforms) --> A(napi)
|
||||
C(next-custom-transforms) --> B(wasm)
|
||||
D(next-core) --> A(napi)
|
||||
E(next-build) --> A(napi)
|
||||
F(next-api) --> A(napi)
|
||||
C(next-custom-transforms) --> D
|
||||
D(next-core) --> F(next-api)
|
||||
D(next-core) --> E(next-build)
|
||||
```
|
||||
|
||||
- `next-custom-transforms`: provides next-swc specific SWC transform visitors. Turbopack, and the plain next-swc bidnings (`transform`) use these transforms. Since this is a bottom package can be imported in any place (turbopack / next-swc / wasm), it is important package do not contain specific dependencies. For example, using Turbopack's VC in this package will cause build failures to wasm bindings.
|
||||
- `next-core`: Implements Turbopack features for the next.js core functionality. This is also the place where Turbopack-specific transform providers (implementing `CustomTransformer`) lives, which wraps swc's transformer in the `next-custom-transforms`.
|
||||
- `next-api`: Binding interface to the next.js provides a proper next.js functionaility using `next-core`.
|
||||
- `napi` / `wasm`: The actual binding interfaces, napi for the node.js and wasm for the wasm. Note wasm bindings cannot import packages using turbopack's feature.
|
||||
|
||||
#### To add new swc transforms
|
||||
|
||||
1. Implements a new visitor in `next-custom-transforms`. It is highly encouraged to use `VisitMut` instead of `Fold` for the performance reasons.
|
||||
2. Implements a new `CustomTransformer` under `packages/next-swc/crates/next-core/src/next_shared/transforms` to make Turbopack's ecma transform plugin, then adjust corresponding rules in `packages/next-swc/crates/next-core/src/(next_client|next_server)/context.rs`.
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_INVALID_API: getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export function getServerSideProps() {}
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_INVALID_API: getStaticProps
|
||||
,-[input.js:1:1]
|
||||
1 | export function getStaticProps() {}
|
||||
: ^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_CLIENT_IMPORT: server-only
|
||||
,-[input.js:8:1]
|
||||
8 |
|
||||
9 | import 'server-only'
|
||||
: ^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_CLIENT_DIRECTIVE
|
||||
,-[input.js:3:1]
|
||||
3 | // prettier-ignore
|
||||
4 | 'use client'
|
||||
: ^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_SERVER_IMPORT: client-only
|
||||
,-[input.js:8:1]
|
||||
8 |
|
||||
9 | import 'client-only'
|
||||
: ^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_CLIENT_DIRECTIVE
|
||||
,-[input.js:5:1]
|
||||
5 | // prettier-ignore
|
||||
6 | 'use client'
|
||||
: ^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_INVALID_API: getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export function getServerSideProps() {}
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_INVALID_API: getStaticProps
|
||||
,-[input.js:1:1]
|
||||
1 | export function getStaticProps() {}
|
||||
: ^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,106 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_REACT_API: useState
|
||||
,-[input.js:1:1]
|
||||
1 | import { useState } from 'react'
|
||||
: ^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: createContext
|
||||
,-[input.js:2:1]
|
||||
2 |
|
||||
3 | import { createContext } from 'react'
|
||||
: ^^^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useEffect
|
||||
,-[input.js:4:1]
|
||||
4 |
|
||||
5 | import { useEffect, useImperativeHandle } from 'react'
|
||||
: ^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useImperativeHandle
|
||||
,-[input.js:4:1]
|
||||
4 |
|
||||
5 | import { useEffect, useImperativeHandle } from 'react'
|
||||
: ^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: Component
|
||||
,-[input.js:7:1]
|
||||
7 | import {
|
||||
8 | Component,
|
||||
: ^^^^^^^^^
|
||||
9 | createFactory,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: createFactory
|
||||
,-[input.js:8:1]
|
||||
8 | Component,
|
||||
9 | createFactory,
|
||||
: ^^^^^^^^^^^^^
|
||||
10 | PureComponent,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: PureComponent
|
||||
,-[input.js:9:1]
|
||||
9 | createFactory,
|
||||
10 | PureComponent,
|
||||
: ^^^^^^^^^^^^^
|
||||
11 | useDeferredValue,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useDeferredValue
|
||||
,-[input.js:10:1]
|
||||
10 | PureComponent,
|
||||
11 | useDeferredValue,
|
||||
: ^^^^^^^^^^^^^^^^
|
||||
12 | useInsertionEffect,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useInsertionEffect
|
||||
,-[input.js:11:1]
|
||||
11 | useDeferredValue,
|
||||
12 | useInsertionEffect,
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
13 | useLayoutEffect,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useLayoutEffect
|
||||
,-[input.js:12:1]
|
||||
12 | useInsertionEffect,
|
||||
13 | useLayoutEffect,
|
||||
: ^^^^^^^^^^^^^^^
|
||||
14 | useReducer,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useReducer
|
||||
,-[input.js:13:1]
|
||||
13 | useLayoutEffect,
|
||||
14 | useReducer,
|
||||
: ^^^^^^^^^^
|
||||
15 | useRef,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useRef
|
||||
,-[input.js:14:1]
|
||||
14 | useReducer,
|
||||
15 | useRef,
|
||||
: ^^^^^^
|
||||
16 | useSyncExternalStore,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useSyncExternalStore
|
||||
,-[input.js:15:1]
|
||||
15 | useRef,
|
||||
16 | useSyncExternalStore,
|
||||
: ^^^^^^^^^^^^^^^^^^^^
|
||||
17 | } from 'react'
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: experimental_useOptimistic
|
||||
,-[input.js:18:1]
|
||||
18 |
|
||||
19 | import { experimental_useOptimistic as useOptimistic } from 'react'
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_REACT_API: findDOMNode
|
||||
,-[input.js:1:1]
|
||||
1 | import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'
|
||||
: ^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: flushSync
|
||||
,-[input.js:1:1]
|
||||
1 | import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'
|
||||
: ^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: unstable_batchedUpdates
|
||||
,-[input.js:1:1]
|
||||
1 | import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useFormStatus
|
||||
,-[input.js:3:1]
|
||||
3 | import {
|
||||
4 | useFormStatus,
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
5 | useFormState,
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_REACT_API: useFormState
|
||||
,-[input.js:4:1]
|
||||
4 | useFormStatus,
|
||||
5 | useFormState,
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
6 | } from 'react-dom'
|
||||
`----
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
x NEXT_RSC_ERR_SERVER_IMPORT: react-dom/server
|
||||
,-[input.js:8:1]
|
||||
8 |
|
||||
9 | import 'react-dom/server'
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x NEXT_RSC_ERR_SERVER_IMPORT: react-dom/client
|
||||
,-[input.js:10:1]
|
||||
10 |
|
||||
11 | import 'react-dom/client'
|
||||
: ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -1,2 +0,0 @@
|
|||
;
|
||||
/*#__PURE__*/ console.log("test!");
|
|
@ -1,13 +0,0 @@
|
|||
// This is a comment.
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* This is a comment.
|
||||
*/
|
||||
|
||||
import 'client-only'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// This is a comment.
|
||||
'use strict';
|
||||
/**
|
||||
* This is a comment.
|
||||
*/ import 'client-only';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export function getServerSideProps() {}
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export function getServerSideProps() {}
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export function getStaticProps() {}
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export function getStaticProps() {}
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// This is a comment.
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* This is a comment.
|
||||
*/
|
||||
|
||||
import 'server-only'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// This is a comment.
|
||||
'use strict';
|
||||
/**
|
||||
* This is a comment.
|
||||
*/ import 'server-only';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import 'react'
|
||||
|
||||
// prettier-ignore
|
||||
'use client'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
import 'react';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// This is a comment.
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* This is a comment.
|
||||
*/
|
||||
|
||||
import 'client-only'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// This is a comment.
|
||||
'use strict';
|
||||
/**
|
||||
* This is a comment.
|
||||
*/ import 'client-only';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
export default function () {
|
||||
return null
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
'use client'
|
|
@ -1,3 +0,0 @@
|
|||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export function getServerSideProps() {}
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export function getServerSideProps() {}
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export function getStaticProps() {}
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export function getStaticProps() {}
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import { useState } from 'react'
|
||||
|
||||
import { createContext } from 'react'
|
||||
|
||||
import { useEffect, useImperativeHandle } from 'react'
|
||||
|
||||
import {
|
||||
Component,
|
||||
createFactory,
|
||||
PureComponent,
|
||||
useDeferredValue,
|
||||
useInsertionEffect,
|
||||
useLayoutEffect,
|
||||
useReducer,
|
||||
useRef,
|
||||
useSyncExternalStore,
|
||||
} from 'react'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { useState } from 'react';
|
||||
import { createContext } from 'react';
|
||||
import { useEffect, useImperativeHandle } from 'react';
|
||||
import { Component, createFactory, PureComponent, useDeferredValue, useInsertionEffect, useLayoutEffect, useReducer, useRef, useSyncExternalStore } from 'react';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'
|
||||
|
||||
import { useFormStatus, useFormState } from 'react-dom'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom';
|
||||
import { useFormStatus, useFormState } from 'react-dom';
|
||||
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// This is a comment.
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* This is a comment.
|
||||
*/
|
||||
|
||||
import 'react-dom/server'
|
||||
|
||||
import 'react-dom/client'
|
||||
|
||||
export default function () {
|
||||
return null
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// This is a comment.
|
||||
'use strict';
|
||||
/**
|
||||
* This is a comment.
|
||||
*/ import 'react-dom/server';
|
||||
import 'react-dom/client';
|
||||
export default function() {
|
||||
return null;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<div>children</div>; '<>hello</>'
|
|
@ -1,24 +0,0 @@
|
|||
function _tagged_template_literal(strings, raw) {
|
||||
if (!raw) {
|
||||
raw = strings.slice(0);
|
||||
}
|
||||
return Object.freeze(Object.defineProperties(strings, {
|
||||
raw: {
|
||||
value: Object.freeze(raw)
|
||||
}
|
||||
}));
|
||||
}
|
||||
function _templateObject() {
|
||||
var data = _tagged_template_literal([
|
||||
"\n color: red;\n"
|
||||
]);
|
||||
_templateObject = function _templateObject() {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
import styled from "styled-components";
|
||||
export var foo = styled.input.withConfig({
|
||||
displayName: "input__foo",
|
||||
componentId: "sc-21a13c03-0"
|
||||
})(_templateObject());
|
|
@ -17,7 +17,7 @@ plugin = [
|
|||
"turbopack-binding/__swc_core_binding_napi_plugin",
|
||||
"turbopack-binding/__swc_core_binding_napi_plugin_filesystem_cache",
|
||||
"turbopack-binding/__swc_core_binding_napi_plugin_shared_runtime",
|
||||
"next-swc/plugin",
|
||||
"next-custom-transforms/plugin",
|
||||
"next-core/plugin",
|
||||
]
|
||||
sentry_native_tls = ["sentry", "sentry/native-tls", "native-tls"]
|
||||
|
@ -54,7 +54,7 @@ napi = { version = "2", default-features = false, features = [
|
|||
"error_anyhow",
|
||||
] }
|
||||
napi-derive = "2"
|
||||
next-swc = { workspace = true }
|
||||
next-custom-transforms = { workspace = true }
|
||||
next-api = { workspace = true }
|
||||
next-build = { workspace = true }
|
||||
next-core = { workspace = true }
|
||||
|
|
|
@ -37,7 +37,7 @@ use std::{
|
|||
use anyhow::{anyhow, bail, Context as _};
|
||||
use fxhash::FxHashSet;
|
||||
use napi::bindgen_prelude::*;
|
||||
use next_swc::{custom_before_pass, TransformOptions};
|
||||
use next_custom_transforms::chain_transforms::{custom_before_pass, TransformOptions};
|
||||
use turbopack_binding::swc::core::{
|
||||
base::{try_with_handler, Compiler, TransformOutput},
|
||||
common::{comments::SingleThreadedComments, errors::ColorConfig, FileName, Mark, GLOBALS},
|
||||
|
|
|
@ -22,7 +22,6 @@ workspace = true
|
|||
[dependencies]
|
||||
anyhow = { workspace = true, features = ["backtrace"] }
|
||||
futures = { workspace = true }
|
||||
next-swc = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
indoc = { workspace = true }
|
||||
next-core = { workspace = true }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{io::Write, iter::once};
|
||||
use std::{collections::BTreeMap, io::Write, iter::once};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use indexmap::{map::Entry, IndexMap};
|
||||
|
@ -6,13 +6,13 @@ use next_core::{
|
|||
next_manifests::{ActionLayer, ActionManifestWorkerEntry, ServerReferenceManifest},
|
||||
util::{get_asset_prefix_from_pathname, NextRuntime},
|
||||
};
|
||||
use next_swc::server_actions::parse_server_actions;
|
||||
use tracing::Instrument;
|
||||
use turbo_tasks::{
|
||||
graph::{GraphTraversal, NonDeterministic},
|
||||
TryFlatJoinIterExt, Value, ValueToString, Vc,
|
||||
};
|
||||
use turbopack_binding::{
|
||||
swc::core::{common::comments::Comments, ecma::ast::Program},
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
|
@ -267,6 +267,30 @@ async fn get_referenced_modules(
|
|||
.map(|modules| modules.clone_value().into_iter().map(move |m| (layer, m)))
|
||||
}
|
||||
|
||||
/// Parses the Server Actions comment for all exported action function names.
|
||||
///
|
||||
/// Action names are stored in a leading BlockComment prefixed by
|
||||
/// `__next_internal_action_entry_do_not_use__`.
|
||||
pub fn parse_server_actions<C: Comments>(
|
||||
program: &Program,
|
||||
comments: C,
|
||||
) -> Option<BTreeMap<String, String>> {
|
||||
let byte_pos = match program {
|
||||
Program::Module(m) => m.span.lo,
|
||||
Program::Script(s) => s.span.lo,
|
||||
};
|
||||
comments.get_leading(byte_pos).and_then(|comments| {
|
||||
comments.iter().find_map(|c| {
|
||||
c.text
|
||||
.split_once("__next_internal_action_entry_do_not_use__")
|
||||
.and_then(|(_, actions)| match serde_json::from_str(actions) {
|
||||
Ok(v) => Some(v),
|
||||
Err(_) => None,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Inspects the comments inside [module] looking for the magic actions comment.
|
||||
/// If found, we return the mapping of every action's hashed id to the name of
|
||||
/// the exported action function. If not, we return a None.
|
||||
|
|
|
@ -18,7 +18,7 @@ async-trait = { workspace = true }
|
|||
base64 = "0.21.0"
|
||||
const_format = "0.2.30"
|
||||
lazy-regex = "3.0.1"
|
||||
next-swc = { workspace = true }
|
||||
next-custom-transforms = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
qstring = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
|
@ -60,10 +60,6 @@ turbopack-binding = { workspace = true, features = [
|
|||
] }
|
||||
turbo-tasks = { workspace = true }
|
||||
turbo-tasks-fs = { workspace = true }
|
||||
next-transform-strip-page-exports = { workspace = true }
|
||||
next-transform-font = { workspace = true }
|
||||
next-transform-dynamic = { workspace = true }
|
||||
next-transform-react-server-components = { workspace = true }
|
||||
|
||||
swc_core = { workspace = true, features = [
|
||||
"ecma_ast",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use next_custom_transforms::transforms::strip_page_exports::ExportFilter;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use next_custom_transforms::transforms::strip_page_exports::ExportFilter;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
|||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use next_transform_dynamic::{next_dynamic, NextDynamicMode};
|
||||
use next_custom_transforms::transforms::dynamic::{next_dynamic, NextDynamicMode};
|
||||
use swc_core::{
|
||||
common::{util::take::Take, FileName},
|
||||
ecma::{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use next_custom_transforms::transforms::fonts::*;
|
||||
use swc_core::ecma::{ast::Program, atoms::JsWord, visit::VisitMutWith};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
|
@ -37,7 +38,7 @@ struct NextJsFont {
|
|||
#[async_trait]
|
||||
impl CustomTransformer for NextJsFont {
|
||||
async fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Result<()> {
|
||||
let mut next_font = next_transform_font::next_font_loaders(next_transform_font::Config {
|
||||
let mut next_font = next_font_loaders(Config {
|
||||
font_loaders: self.font_loaders.clone(),
|
||||
relative_file_path_from_root: ctx.file_name_str.into(),
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
|||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use next_transform_react_server_components::{server_components, Config, Options};
|
||||
use next_custom_transforms::transforms::react_server_components::*;
|
||||
use swc_core::{
|
||||
common::{util::take::Take, FileName},
|
||||
ecma::{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use next_transform_strip_page_exports::{next_transform_strip_page_exports, ExportFilter};
|
||||
use next_custom_transforms::transforms::strip_page_exports::{
|
||||
next_transform_strip_page_exports, ExportFilter,
|
||||
};
|
||||
use swc_core::{
|
||||
common::util::take::Take,
|
||||
ecma::{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use next_swc::server_actions::{server_actions, Config};
|
||||
use next_custom_transforms::transforms::server_actions::{server_actions, Config};
|
||||
use swc_core::{
|
||||
common::FileName,
|
||||
ecma::{ast::Program, visit::VisitMutWith},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "next-swc"
|
||||
name = "next-custom-transforms"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
|
||||
|
@ -18,18 +18,14 @@ either = "1"
|
|||
fxhash = "0.2.1"
|
||||
hex = "0.4.3"
|
||||
once_cell = { workspace = true }
|
||||
pathdiff = "0.2.0"
|
||||
pathdiff = { workspace = true }
|
||||
regex = "1.5"
|
||||
rustc-hash = "1"
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
rustc-hash = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||
sha1 = "0.10.1"
|
||||
tracing = { version = "0.1.37" }
|
||||
|
||||
next-visitor-cjs-finder = { workspace = true }
|
||||
next-transform-dynamic = { workspace = true }
|
||||
next-transform-font = { workspace = true }
|
||||
next-transform-react-server-components = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
||||
turbopack-binding = { workspace = true, features = [
|
||||
"__swc_core",
|
||||
|
@ -40,6 +36,8 @@ turbopack-binding = { workspace = true, features = [
|
|||
"__swc_transform_modularize_imports",
|
||||
"__swc_transform_relay",
|
||||
] }
|
||||
# To allow quote! macro works
|
||||
swc_core = { workspace = true, features = ["ecma_quote"]}
|
||||
react_remove_properties = "0.19.0"
|
||||
remove_console = "0.20.0"
|
||||
|
|
@ -1,44 +1,7 @@
|
|||
/*
|
||||
Copyright (c) 2017 The swc Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// TODO(alexkirsz) Remove once the diagnostic is fixed.
|
||||
#![allow(rustc::untranslatable_diagnostic_trivial)]
|
||||
#![recursion_limit = "2048"]
|
||||
#![deny(clippy::all)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
|
||||
|
||||
use either::Either;
|
||||
use fxhash::FxHashSet;
|
||||
use next_transform_dynamic::{next_dynamic, NextDynamicMode};
|
||||
use next_transform_font::next_font_loaders;
|
||||
use next_visitor_cjs_finder::contains_cjs;
|
||||
use serde::Deserialize;
|
||||
use turbopack_binding::swc::{
|
||||
core::{
|
||||
|
@ -55,18 +18,12 @@ use turbopack_binding::swc::{
|
|||
custom_transform::modularize_imports,
|
||||
};
|
||||
|
||||
pub mod amp_attributes;
|
||||
pub mod cjs_optimizer;
|
||||
pub mod disallow_re_export_all_in_page;
|
||||
mod import_analyzer;
|
||||
pub mod named_import_transform;
|
||||
pub mod next_ssg;
|
||||
pub mod optimize_barrel;
|
||||
pub mod optimize_server_react;
|
||||
pub mod page_config;
|
||||
pub mod pure;
|
||||
pub mod server_actions;
|
||||
pub mod shake_exports;
|
||||
use crate::transforms::{
|
||||
cjs_finder::contains_cjs,
|
||||
dynamic::{next_dynamic, NextDynamicMode},
|
||||
fonts::next_font_loaders,
|
||||
react_server_components,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -99,7 +56,7 @@ pub struct TransformOptions {
|
|||
pub prefer_esm: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub server_components: Option<next_transform_react_server_components::Config>,
|
||||
pub server_components: Option<react_server_components::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub styled_jsx: Option<turbopack_binding::swc::custom_transform::styled_jsx::visitor::Config>,
|
||||
|
@ -125,7 +82,7 @@ pub struct TransformOptions {
|
|||
pub relay: Option<serde_json::Value>,
|
||||
|
||||
#[serde(default)]
|
||||
pub shake_exports: Option<shake_exports::Config>,
|
||||
pub shake_exports: Option<crate::transforms::shake_exports::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub emotion: Option<turbopack_binding::swc::custom_transform::emotion::EmotionOptions>,
|
||||
|
@ -134,22 +91,22 @@ pub struct TransformOptions {
|
|||
pub modularize_imports: Option<modularize_imports::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub auto_modularize_imports: Option<named_import_transform::Config>,
|
||||
pub auto_modularize_imports: Option<crate::transforms::named_import_transform::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub optimize_barrel_exports: Option<optimize_barrel::Config>,
|
||||
pub optimize_barrel_exports: Option<crate::transforms::optimize_barrel::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub font_loaders: Option<next_transform_font::Config>,
|
||||
pub font_loaders: Option<crate::transforms::fonts::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub server_actions: Option<server_actions::Config>,
|
||||
pub server_actions: Option<crate::transforms::server_actions::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub cjs_require_optimizer: Option<cjs_optimizer::Config>,
|
||||
pub cjs_require_optimizer: Option<crate::transforms::cjs_optimizer::Config>,
|
||||
|
||||
#[serde(default)]
|
||||
pub optimize_server_react: Option<optimize_server_react::Config>,
|
||||
pub optimize_server_react: Option<crate::transforms::optimize_server_react::Config>,
|
||||
}
|
||||
|
||||
pub fn custom_before_pass<'a, C: Comments + 'a>(
|
||||
|
@ -189,10 +146,10 @@ where
|
|||
};
|
||||
|
||||
chain!(
|
||||
disallow_re_export_all_in_page::disallow_re_export_all_in_page(opts.is_page_file),
|
||||
crate::transforms::disallow_re_export_all_in_page::disallow_re_export_all_in_page(opts.is_page_file),
|
||||
match &opts.server_components {
|
||||
Some(config) if config.truthy() =>
|
||||
Either::Left(next_transform_react_server_components::server_components(
|
||||
Either::Left(react_server_components::server_components(
|
||||
file.name.clone(),
|
||||
config.clone(),
|
||||
comments.clone(),
|
||||
|
@ -223,10 +180,10 @@ where
|
|||
None => Either::Right(noop()),
|
||||
},
|
||||
Optional::new(
|
||||
next_ssg::next_ssg(eliminated_packages),
|
||||
crate::transforms::next_ssg::next_ssg(eliminated_packages),
|
||||
!opts.disable_next_ssg
|
||||
),
|
||||
amp_attributes::amp_attributes(),
|
||||
crate::transforms::amp_attributes::amp_attributes(),
|
||||
next_dynamic(
|
||||
opts.is_development,
|
||||
opts.is_server_compiler,
|
||||
|
@ -234,7 +191,7 @@ where
|
|||
Some(config) if config.truthy() => match config {
|
||||
// Always enable the Server Components mode for both
|
||||
// server and client layers.
|
||||
next_transform_react_server_components::Config::WithOptions(config) => config.is_react_server_layer,
|
||||
react_server_components::Config::WithOptions(config) => config.is_react_server_layer,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
|
@ -245,7 +202,7 @@ where
|
|||
opts.pages_dir.clone()
|
||||
),
|
||||
Optional::new(
|
||||
page_config::page_config(opts.is_development, opts.is_page_file),
|
||||
crate::transforms::page_config::page_config(opts.is_development, opts.is_page_file),
|
||||
!opts.disable_page_config
|
||||
),
|
||||
relay_plugin,
|
||||
|
@ -263,19 +220,19 @@ where
|
|||
_ => Either::Right(noop()),
|
||||
},
|
||||
match &opts.shake_exports {
|
||||
Some(config) => Either::Left(shake_exports::shake_exports(config.clone())),
|
||||
Some(config) => Either::Left(crate::transforms::shake_exports::shake_exports(config.clone())),
|
||||
None => Either::Right(noop()),
|
||||
},
|
||||
match &opts.auto_modularize_imports {
|
||||
Some(config) => Either::Left(named_import_transform::named_import_transform(config.clone())),
|
||||
Some(config) => Either::Left(crate::transforms::named_import_transform::named_import_transform(config.clone())),
|
||||
None => Either::Right(noop()),
|
||||
},
|
||||
match &opts.optimize_barrel_exports {
|
||||
Some(config) => Either::Left(optimize_barrel::optimize_barrel(config.clone())),
|
||||
Some(config) => Either::Left(crate::transforms::optimize_barrel::optimize_barrel(config.clone())),
|
||||
_ => Either::Right(noop()),
|
||||
},
|
||||
match &opts.optimize_server_react {
|
||||
Some(config) => Either::Left(optimize_server_react::optimize_server_react(config.clone())),
|
||||
Some(config) => Either::Left(crate::transforms::optimize_server_react::optimize_server_react(config.clone())),
|
||||
_ => Either::Right(noop()),
|
||||
},
|
||||
opts.emotion
|
||||
|
@ -309,7 +266,7 @@ where
|
|||
None => Either::Right(noop()),
|
||||
},
|
||||
match &opts.server_actions {
|
||||
Some(config) => Either::Left(server_actions::server_actions(
|
||||
Some(config) => Either::Left(crate::transforms::server_actions::server_actions(
|
||||
&file.name,
|
||||
config.clone(),
|
||||
comments.clone(),
|
||||
|
@ -318,11 +275,11 @@ where
|
|||
},
|
||||
match &opts.cjs_require_optimizer {
|
||||
Some(config) => {
|
||||
Either::Left(cjs_optimizer::cjs_optimizer(config.clone(), SyntaxContext::empty().apply_mark(unresolved_mark)))
|
||||
Either::Left(crate::transforms::cjs_optimizer::cjs_optimizer(config.clone(), SyntaxContext::empty().apply_mark(unresolved_mark)))
|
||||
},
|
||||
None => Either::Right(noop()),
|
||||
},
|
||||
pure::pure_magic(comments),
|
||||
crate::transforms::pure::pure_magic(comments),
|
||||
)
|
||||
}
|
||||
|
37
packages/next-swc/crates/next-custom-transforms/src/lib.rs
Normal file
37
packages/next-swc/crates/next-custom-transforms/src/lib.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright (c) 2017 The swc Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// TODO(alexkirsz) Remove once the diagnostic is fixed.
|
||||
#![allow(rustc::untranslatable_diagnostic_trivial)]
|
||||
#![recursion_limit = "2048"]
|
||||
#![deny(clippy::all)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
pub mod chain_transforms;
|
||||
pub mod transforms;
|
|
@ -1,4 +1,4 @@
|
|||
use swc_core::ecma::{
|
||||
use turbopack_binding::swc::core::ecma::{
|
||||
ast::*,
|
||||
visit::{Visit, VisitWith},
|
||||
};
|
|
@ -1,10 +1,8 @@
|
|||
// TODO(alexkirsz) Remove once the diagnostic is fixed.
|
||||
#![allow(rustc::untranslatable_diagnostic_trivial)]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use pathdiff::diff_paths;
|
||||
use swc_core::{
|
||||
use swc_core::quote;
|
||||
use turbopack_binding::swc::core::{
|
||||
common::{errors::HANDLER, FileName, Span, DUMMY_SP},
|
||||
ecma::{
|
||||
ast::{
|
||||
|
@ -16,7 +14,6 @@ use swc_core::{
|
|||
utils::{private_ident, quote_ident, ExprFactory},
|
||||
visit::{Fold, FoldWith},
|
||||
},
|
||||
quote,
|
||||
};
|
||||
|
||||
/// Creates a SWC visitor to transform `next/dynamic` calls to have the
|
|
@ -1,4 +1,4 @@
|
|||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::errors::HANDLER,
|
||||
ecma::{
|
||||
ast::*,
|
|
@ -1,4 +1,4 @@
|
|||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::errors::HANDLER,
|
||||
ecma::{
|
||||
ast::*,
|
|
@ -1,5 +1,5 @@
|
|||
use serde_json::Value;
|
||||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::{errors::HANDLER, Spanned, DUMMY_SP},
|
||||
ecma::{
|
||||
ast::*,
|
|
@ -1,9 +1,6 @@
|
|||
// TODO(alexkirsz) Remove once the diagnostic is fixed.
|
||||
#![allow(rustc::untranslatable_diagnostic_trivial)]
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
use serde::Deserialize;
|
||||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::{collections::AHashMap, BytePos, Spanned},
|
||||
ecma::{
|
||||
ast::{Id, ModuleItem},
|
|
@ -0,0 +1,17 @@
|
|||
pub mod amp_attributes;
|
||||
pub mod cjs_finder;
|
||||
pub mod cjs_optimizer;
|
||||
pub mod disallow_re_export_all_in_page;
|
||||
pub mod dynamic;
|
||||
pub mod fonts;
|
||||
pub mod import_analyzer;
|
||||
pub mod named_import_transform;
|
||||
pub mod next_ssg;
|
||||
pub mod optimize_barrel;
|
||||
pub mod optimize_server_react;
|
||||
pub mod page_config;
|
||||
pub mod pure;
|
||||
pub mod react_server_components;
|
||||
pub mod server_actions;
|
||||
pub mod shake_exports;
|
||||
pub mod strip_page_exports;
|
|
@ -6,7 +6,7 @@ use turbopack_binding::swc::core::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::import_analyzer::ImportMap;
|
||||
use crate::transforms::import_analyzer::ImportMap;
|
||||
|
||||
pub fn pure_magic<C>(comments: C) -> impl Fold
|
||||
where
|
|
@ -1,11 +1,8 @@
|
|||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use next_visitor_cjs_finder::contains_cjs;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::{
|
||||
comments::{Comment, CommentKind, Comments},
|
||||
errors::HANDLER,
|
||||
|
@ -19,6 +16,8 @@ use swc_core::{
|
|||
},
|
||||
};
|
||||
|
||||
use super::cjs_finder::contains_cjs;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Config {
|
|
@ -63,27 +63,6 @@ pub fn server_actions<C: Comments>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Parses the Server Actions comment for all exported action function names.
|
||||
///
|
||||
/// Action names are stored in a leading BlockComment prefixed by
|
||||
/// `__next_internal_action_entry_do_not_use__`.
|
||||
pub fn parse_server_actions<C: Comments>(program: &Program, comments: C) -> Option<ActionsMap> {
|
||||
let byte_pos = match program {
|
||||
Program::Module(m) => m.span.lo,
|
||||
Program::Script(s) => s.span.lo,
|
||||
};
|
||||
comments.get_leading(byte_pos).and_then(|comments| {
|
||||
comments.iter().find_map(|c| {
|
||||
c.text
|
||||
.split_once("__next_internal_action_entry_do_not_use__")
|
||||
.and_then(|(_, actions)| match serde_json::from_str(actions) {
|
||||
Ok(v) => Some(v),
|
||||
Err(_) => None,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Serializes the Server Actions into a magic comment prefixed by
|
||||
/// `__next_internal_action_entry_do_not_use__`.
|
||||
fn generate_server_actions_comment(actions: ActionsMap) -> String {
|
|
@ -2,11 +2,12 @@
|
|||
//! https://github.com/vercel/next.js/blob/f7fecf00cb40c2f784387ff8ccc5e213b8bdd9ca/packages/next-swc/crates/core/src/next_ssg.rs
|
||||
//!
|
||||
//! This version adds support for eliminating client-side exports only.
|
||||
//! [TODO] may consolidate into next_ssg
|
||||
|
||||
use std::{cell::RefCell, mem::take, rc::Rc};
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use swc_core::{
|
||||
use turbopack_binding::swc::core::{
|
||||
common::{
|
||||
errors::HANDLER,
|
||||
pass::{Repeat, Repeated},
|
||||
|
@ -949,7 +950,8 @@ impl Fold for NextSsg {
|
|||
match e {
|
||||
Expr::Assign(assign_expr) => {
|
||||
let mut retain = true;
|
||||
let left = self.within_lhs_of_var(true, |this| assign_expr.left.fold_with(this));
|
||||
let left =
|
||||
self.within_lhs_of_var(true, |this| assign_expr.left.clone().fold_with(this));
|
||||
|
||||
let right = self.within_lhs_of_var(false, |this| {
|
||||
if let PatOrExpr::Pat(pat) = &left {
|
||||
|
@ -958,7 +960,7 @@ impl Fold for NextSsg {
|
|||
this.mark_as_candidate(&assign_expr.right);
|
||||
}
|
||||
}
|
||||
assign_expr.right.fold_with(this)
|
||||
assign_expr.right.clone().fold_with(this)
|
||||
});
|
||||
|
||||
if retain {
|
||||
|
@ -983,13 +985,13 @@ impl Fold for NextSsg {
|
|||
/// This method make `name` of [VarDeclarator] to [Pat::Invalid] if it
|
||||
/// should be removed.
|
||||
fn fold_var_declarator(&mut self, d: VarDeclarator) -> VarDeclarator {
|
||||
let name = self.within_lhs_of_var(true, |this| d.name.fold_with(this));
|
||||
let name = self.within_lhs_of_var(true, |this| d.name.clone().fold_with(this));
|
||||
|
||||
let init = self.within_lhs_of_var(false, |this| {
|
||||
if name.is_invalid() {
|
||||
this.mark_as_candidate(&d.init);
|
||||
}
|
||||
d.init.fold_with(this)
|
||||
d.init.clone().fold_with(this)
|
||||
});
|
||||
|
||||
VarDeclarator { name, init, ..d }
|
|
@ -1,15 +1,16 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use next_swc::{
|
||||
use next_custom_transforms::transforms::{
|
||||
disallow_re_export_all_in_page::disallow_re_export_all_in_page,
|
||||
dynamic::{next_dynamic, NextDynamicMode},
|
||||
fonts::{next_font_loaders, Config as FontLoaderConfig},
|
||||
next_ssg::next_ssg,
|
||||
react_server_components::server_components,
|
||||
server_actions::{
|
||||
server_actions, {self},
|
||||
},
|
||||
strip_page_exports::{next_transform_strip_page_exports, ExportFilter},
|
||||
};
|
||||
use next_transform_dynamic::{next_dynamic, NextDynamicMode};
|
||||
use next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
||||
use turbopack_binding::swc::{
|
||||
core::{
|
||||
common::{chain, FileName, Mark},
|
||||
|
@ -88,17 +89,16 @@ fn next_ssg_errors(input: PathBuf) {
|
|||
|
||||
#[fixture("tests/errors/react-server-components/server-graph/**/input.js")]
|
||||
fn react_server_components_server_graph_errors(input: PathBuf) {
|
||||
use next_custom_transforms::transforms::react_server_components::{Config, Options};
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|tr| {
|
||||
server_components(
|
||||
FileName::Real(PathBuf::from("/some-project/src/layout.js")),
|
||||
next_swc::react_server_components::Config::WithOptions(
|
||||
next_swc::react_server_components::Options {
|
||||
is_react_server_layer: true,
|
||||
},
|
||||
),
|
||||
Config::WithOptions(Options {
|
||||
is_react_server_layer: true,
|
||||
}),
|
||||
tr.comments.as_ref().clone(),
|
||||
None,
|
||||
)
|
||||
|
@ -114,17 +114,16 @@ fn react_server_components_server_graph_errors(input: PathBuf) {
|
|||
|
||||
#[fixture("tests/errors/react-server-components/client-graph/**/input.js")]
|
||||
fn react_server_components_client_graph_errors(input: PathBuf) {
|
||||
use next_custom_transforms::transforms::react_server_components::{Config, Options};
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|tr| {
|
||||
server_components(
|
||||
FileName::Real(PathBuf::from("/some-project/src/page.js")),
|
||||
next_swc::react_server_components::Config::WithOptions(
|
||||
next_swc::react_server_components::Options {
|
||||
is_react_server_layer: false,
|
||||
},
|
||||
),
|
||||
Config::WithOptions(Options {
|
||||
is_react_server_layer: false,
|
||||
}),
|
||||
tr.comments.as_ref().clone(),
|
||||
None,
|
||||
)
|
||||
|
@ -160,6 +159,7 @@ fn next_font_loaders_errors(input: PathBuf) {
|
|||
|
||||
#[fixture("tests/errors/server-actions/server-graph/**/input.js")]
|
||||
fn react_server_actions_server_errors(input: PathBuf) {
|
||||
use next_custom_transforms::transforms::react_server_components::{Config, Options};
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
|
@ -168,11 +168,9 @@ fn react_server_actions_server_errors(input: PathBuf) {
|
|||
resolver(Mark::new(), Mark::new(), false),
|
||||
server_components(
|
||||
FileName::Real(PathBuf::from("/app/item.js")),
|
||||
next_swc::react_server_components::Config::WithOptions(
|
||||
next_swc::react_server_components::Options {
|
||||
is_react_server_layer: true
|
||||
},
|
||||
),
|
||||
Config::WithOptions(Options {
|
||||
is_react_server_layer: true
|
||||
},),
|
||||
tr.comments.as_ref().clone(),
|
||||
None,
|
||||
),
|
||||
|
@ -197,6 +195,7 @@ fn react_server_actions_server_errors(input: PathBuf) {
|
|||
|
||||
#[fixture("tests/errors/server-actions/client-graph/**/input.js")]
|
||||
fn react_server_actions_client_errors(input: PathBuf) {
|
||||
use next_custom_transforms::transforms::react_server_components::{Config, Options};
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
|
@ -205,11 +204,9 @@ fn react_server_actions_client_errors(input: PathBuf) {
|
|||
resolver(Mark::new(), Mark::new(), false),
|
||||
server_components(
|
||||
FileName::Real(PathBuf::from("/app/item.js")),
|
||||
next_swc::react_server_components::Config::WithOptions(
|
||||
next_swc::react_server_components::Options {
|
||||
is_react_server_layer: false
|
||||
},
|
||||
),
|
||||
Config::WithOptions(Options {
|
||||
is_react_server_layer: false
|
||||
},),
|
||||
tr.comments.as_ref().clone(),
|
||||
None,
|
||||
),
|
||||
|
@ -231,3 +228,20 @@ fn react_server_actions_client_errors(input: PathBuf) {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/errors/strip-page-exports/**/input.js")]
|
||||
fn next_transform_strip_page_exports_errors(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| {
|
||||
next_transform_strip_page_exports(ExportFilter::StripDataExports, Default::default())
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
FixtureTestConfig {
|
||||
allow_error: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue