Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Jun 6, 2023
1 parent 6318d50 commit 533db1e
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/next-swc/crates/napi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ default = ["rustls-tls"]
# 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 = ["turbopack-binding/__swc_core_binding_napi_plugin", "next-swc/plugin"]
plugin = ["turbopack-binding/__swc_core_binding_napi_plugin", "next-swc/plugin", "next-core/plugin"]
sentry_native_tls = ["sentry", "sentry/native-tls", "native-tls"]
sentry_rustls = ["sentry", "sentry/rustls", "rustls-tls"]

Expand Down
1 change: 1 addition & 0 deletions packages/next-swc/crates/next-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ turbopack-binding = { workspace = true, features = ["__turbo_tasks_build"] }
next-font-local = []
native-tls = ["turbopack-binding/__turbo_tasks_fetch_native-tls"]
rustls-tls = ["turbopack-binding/__turbo_tasks_fetch_rustls-tls"]
plugin = ["turbopack-binding/__swc_core_binding_napi_plugin"]
# Internal only. Enabled when building for the Next.js integration test suite.
__internal_nextjs_integration_test = []
# enable "HMR" for embedded assets
Expand Down
2 changes: 1 addition & 1 deletion packages/next-swc/crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ pub struct ExperimentalConfig {
pub server_components_external_packages: Option<Vec<String>>,
pub turbo: Option<ExperimentalTurboConfig>,
mdx_rs: Option<bool>,
pub swc_plugins: Option<Vec<(String, serde_json::Value)>>,

// unsupported
adjust_font_fallbacks: Option<bool>,
Expand Down Expand Up @@ -427,7 +428,6 @@ pub struct ExperimentalConfig {
swc_file_reading: Option<bool>,
swc_minify: Option<bool>,
swc_minify_debug_options: Option<serde_json::Value>,
swc_plugins: Option<serde_json::Value>,
swc_trace_profiling: Option<bool>,
transpile_packages: Option<Vec<String>>,
turbotrace: Option<serde_json::Value>,
Expand Down
2 changes: 2 additions & 0 deletions packages/next-swc/crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use crate::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
styled_jsx::get_styled_jsx_transform_plugin,
swc_ecma_transform_plugins::get_swc_ecma_transform_plugin,
},
},
sass::maybe_add_sass_loader,
Expand Down Expand Up @@ -330,6 +331,7 @@ pub async fn get_server_module_options_context(
let source_transforms: Vec<TransformPluginVc> = vec![
*get_relay_transform_plugin(next_config).await?,
*get_emotion_transform_plugin(next_config).await?,
*get_swc_ecma_transform_plugin(project_path, next_config).await?,
]
.into_iter()
.flatten()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub(crate) mod next_strip_page_exports;
pub(crate) mod relay;
pub(crate) mod styled_components;
pub(crate) mod styled_jsx;
pub(crate) mod swc_ecma_transform_plugins;

pub use modularize_imports::{get_next_modularize_imports_rule, ModularizeImportPackageConfig};
pub use next_dynamic::get_next_dynamic_transform_rule;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use anyhow::Result;
use turbo_tasks_fs::FileSystemPathVc;
use turbopack_binding::turbopack::ecmascript::OptionTransformPluginVc;

use crate::next_config::NextConfigVc;

#[turbo_tasks::function]
pub async fn get_swc_ecma_transform_plugin(
#[cfg_attr(not(feature = "plugin"), allow(unused))] project_path: FileSystemPathVc,
next_config: NextConfigVc,
) -> Result<OptionTransformPluginVc> {
let config = next_config.await?;
match config.experimental.swc_plugins.as_ref() {
Some(plugin_configs) if !plugin_configs.is_empty() => {
#[cfg(feature = "plugin")]
{
use anyhow::{bail, Context};
use turbo_tasks::Value;
use turbo_tasks_fs::FileContent;
use turbopack_binding::turbopack::{
core::{
asset::Asset,
issue::{IssueSeverity, OptionIssueSourceVc},
reference_type::ReferenceType,
resolve::{
handle_resolve_error, parse::RequestVc, pattern::Pattern, resolve,
PrimaryResolveResult,
},
},
ecmascript::{OptionTransformPluginVc, TransformPluginVc},
ecmascript_plugin::transform::swc_ecma_transform_plugins::{
SwcEcmaTransformPluginsTransformer, SwcPluginModule, SwcPluginModuleVc,
},
turbopack::{resolve_options, resolve_options_context::ResolveOptionsContext},
};

let mut plugins = vec![];
for (name, config) in plugin_configs.iter() {
// [TODO]: SWC's current experimental config supports
// two forms of plugin path,
// one for implicit package name resolves to node_modules,
// and one for explicit path to a .wasm binary.
// Current resolve will fail with latter.
let request = RequestVc::parse(Value::new(Pattern::Constant(name.to_string())));
let resolve_options = resolve_options(
project_path,
ResolveOptionsContext {
enable_node_modules: Some(project_path.root().resolve().await?),
enable_node_native_modules: true,
..Default::default()
}
.cell(),
);

let plugin_wasm_module_resolve_result = handle_resolve_error(
resolve(project_path, request, resolve_options),
Value::new(ReferenceType::Undefined),
project_path,
request,
resolve_options,
OptionIssueSourceVc::none(),
IssueSeverity::Error.cell(),
)
.await?;
let plugin_wasm_module_resolve_result =
&*plugin_wasm_module_resolve_result.await?;

let primary = plugin_wasm_module_resolve_result
.primary
.first()
.context("Unable to resolve primary context")?;

let PrimaryResolveResult::Asset(plugin_module_asset) = primary else {
bail!("Expected to find asset");
};

let content = &*plugin_module_asset.content().file_content().await?;

let FileContent::Content(file) = content else {
bail!("Expected file content for plugin module");
};

plugins.push((
SwcPluginModuleVc::cell(SwcPluginModule::new(
name,
file.content().to_bytes()?.to_vec(),
)),
config.clone(),
));
}

return Ok(OptionTransformPluginVc::cell(Some(
TransformPluginVc::cell(Box::new(SwcEcmaTransformPluginsTransformer::new(
plugins,
))),
)));
}

#[cfg(not(feature = "plugin"))]
Ok(OptionTransformPluginVc::cell(None))
}
_ => Ok(OptionTransformPluginVc::cell(None)),
}
}

0 comments on commit 533db1e

Please sign in to comment.