feat(next/swc): support experimental swc plugins (#36790)

* build(cargo): build swc with plugin support

* feat(next): expose experimental swcplugins config

* docs(compiler): add description

* build(cargo): resolve feature conflicts

* build(cargo): resolve build conflict

* Update docs/advanced-features/compiler.md

Co-authored-by: Maia Teegarden <dev@padmaia.rocks>

Co-authored-by: Maia Teegarden <dev@padmaia.rocks>
This commit is contained in:
OJ Kwon 2022-05-26 15:16:26 -07:00 committed by GitHub
parent e4a9f09d45
commit fc61428db1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 986 additions and 28 deletions

1
.gitignore vendored
View file

@ -44,3 +44,4 @@ test-timings.json
# Cache
*.tsbuildinfo
.swc/

View file

@ -316,6 +316,42 @@ This transform uses [handlebars](https://docs.rs/handlebars) to template the rep
2. `member`: Has type `string`. The name of the member import.
3. `lowerCase`, `upperCase`, `camelCase`: Helper functions to convert a string to lower, upper or camel cases.
### SWC Trace profiling
You can generate SWC's internal transform traces as chromium's [trace event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview?mode=html#%21=).
```js
// next.config.js
module.exports = {
experimental: {
swcTraceProfiling: true,
},
}
```
Once enabled, swc will generate trace named as `swc-trace-profile-${timestamp}.json` under `.next/`. Chromium's trace viewer (chrome://tracing/, https://ui.perfetto.dev/), or compatible flamegraph viewer (https://www.speedscope.app/) can load & visualize generated traces.
### Experimental SWC plugin support
You can configure swc's transform to use SWC's experimental plugin support written in wasm to customize transformation behavior.
```js
// next.config.js
module.exports = {
experimental: {
swcPlugins: [
['plugin', {
..pluginOptions
}]
]
}
}
```
`swcPlugins` accepts an array of tuples for configuring plugins. A tuple for the plugin contains the path to the plugin and an object for plugin configuration. The path to the plugin can be an npm module package name or an absolute path to the `.wasm` binary itself.
## Unsupported Features
When your application has a `.babelrc` file, Next.js will automatically fall back to using Babel for transforming individual files. This ensures backwards compatibility with existing applications that leverage custom Babel plugins.

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,11 @@ publish = false
[lib]
crate-type = ["cdylib", "rlib"]
[features]
plugin = [
"swc/plugin"
]
[dependencies]
chrono = "0.4"
easy-error = "1.0.0"
@ -21,13 +26,16 @@ swc_emotion = {path="../emotion"}
styled_components = {path="../styled_components"}
styled_jsx = {path="../styled_jsx"}
modularize_imports = {path="../modularize_imports"}
swc = "0.181.2"
swc = { version = "0.181.2" }
swc_atoms = "0.2.11"
swc_common = { version = "0.18.7", features = ["concurrent", "sourcemap"] }
swc_ecma_loader = { version = "0.30.2", features = ["node", "lru"] }
swc_ecmascript = { version = "0.157.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.55.0", optional = true, default-features = false }
swc_cached = "0.1.1"
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
wasmer = {version = "2.2.1", optional = true, default-features = false}
wasmer-wasi = {version = "2.2.1", optional = true, default-features = false}
[dev-dependencies]
swc_ecma_transforms_testing = "0.87.0"

View file

@ -7,6 +7,19 @@ publish = false
[lib]
crate-type = ["cdylib", "rlib"]
[features]
# Instead of enabling all the plugin-related features by default, make it explicitly specified
# when build (i.e napi --build --features plugin), same for the wasm as well.
# this is due to some of transitive dependencies have features cannot be enabled at the same time
# (i.e wasmer/default vs wasmer/js-default) while cargo merges all the features at once.
plugin = [
"swc/plugin",
"swc_plugin_runner/default",
"wasmer/default",
"wasmer-wasi/default",
"next-swc/plugin"
]
[dependencies]
anyhow = "1.0"
backtrace = "0.3"
@ -17,18 +30,20 @@ next-swc = {version = "0.0.0", path = "../core"}
once_cell = "1.8.0"
serde = "1"
serde_json = "1"
swc = "0.181.2"
swc = { version = "0.181.2" }
swc_atoms = "0.2.11"
swc_bundler = { version = "0.147.0", features = ["concurrent"] }
swc_common = { version = "0.18.7", features = ["concurrent", "sourcemap"] }
swc_ecma_loader = { version = "0.30.2", features = ["node", "lru"] }
swc_ecmascript = { version = "0.157.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.55.0", optional = true, default-features = false }
swc_node_base = "0.5.3"
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
tracing-futures = "0.2.5"
tracing-subscriber = "0.3.9"
tracing-chrome = "0.5.0"
wasmer = {version = "2.2.1", optional = true, default-features = false}
wasmer-wasi = {version = "2.2.1", optional = true, default-features = false}
[build-dependencies]
napi-build = "1"

View file

@ -7,6 +7,15 @@ version = "0.0.0"
[lib]
crate-type = ["cdylib"]
[features]
plugin = [
"swc/plugin",
"swc_plugin_runner/memory_cache",
"wasmer/js-default",
"wasmer-wasi/js-default",
"getrandom/js"
]
[dependencies]
anyhow = "1.0.42"
console_error_panic_hook = "0.1.6"
@ -19,6 +28,10 @@ serde_json = "1"
swc = "0.181.2"
swc_common = { version = "0.18.7", features = ["concurrent", "sourcemap"] }
swc_ecmascript = { version = "0.157.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.55.0", default-features = false, optional = true }
tracing = { version = "0.1.32", features = ["release_max_level_off"] }
wasm-bindgen = {version = "0.2", features = ["serde-serialize"]}
wasm-bindgen-futures = "0.4.8"
wasmer = {version = "2.2.1", optional = true, default-features = false}
wasmer-wasi = {version = "2.2.1", optional = true, default-features = false}
getrandom = { version = "0.2.5", optional = true, default-features = false }

View file

@ -3,7 +3,7 @@
"version": "12.1.7-canary.16",
"private": true,
"scripts": {
"build-native": "napi build --platform --cargo-name next_swc_napi native",
"build-native": "napi build --platform -p next-swc-napi --cargo-name next_swc_napi native --features plugin",
"build-wasm": "wasm-pack build crates/wasm --scope=next"
},
"napi": {

View file

@ -54,6 +54,7 @@ function getBaseSWCOptions({
parser: parserConfig,
experimental: {
keepImportAssertions: true,
plugins: nextConfig?.experimental?.swcPlugins ?? undefined,
},
transform: {
// Enables https://github.com/swc-project/swc/blob/0359deb4841be743d73db4536d4a22ac797d7f65/crates/swc_ecma_ext_transforms/src/jest.rs

View file

@ -132,6 +132,7 @@ export interface ExperimentalConfig {
>
swcTraceProfiling?: boolean
forceSwcTransforms?: boolean
swcPlugins?: Array<[string, Record<string, unknown>]>
}
/**