From 7c413483db5ded8d9552891a58dd4a7d6a6430cb Mon Sep 17 00:00:00 2001 From: xusd320 Date: Thu, 12 Feb 2026 17:54:08 +0800 Subject: [PATCH] feat(pack): support write to dir out of dist --- crates/pack-api/src/app.rs | 15 ++--- crates/pack-api/src/library.rs | 6 +- crates/pack-core/src/emit.rs | 10 ++-- crates/pack-napi/src/pack_api/project.rs | 16 ++++-- package-lock.json | 72 ++++++++++++------------ packages/pack-shared/src/config.ts | 3 + packages/pack/package.json | 3 +- packages/pack/src/commands/build.ts | 2 +- packages/pack/src/core/hmr.ts | 2 +- packages/pack/src/plugins/HtmlPlugin.ts | 5 +- packages/pack/src/utils/htmlEntry.ts | 2 + 11 files changed, 74 insertions(+), 62 deletions(-) diff --git a/crates/pack-api/src/app.rs b/crates/pack-api/src/app.rs index 08ff0736a8..a583efb788 100644 --- a/crates/pack-api/src/app.rs +++ b/crates/pack-api/src/app.rs @@ -366,15 +366,18 @@ impl Endpoint for AppEndpoint { let dist_root = this.project.dist_root().await?; - let (server_paths, client_paths) = (vec![], vec![]); - let written_endpoint = EndpointOutputPaths::NodeJs { server_entry_path: dist_root.path.to_string(), - server_paths, - client_paths, + // FIXME: No server path when bundling library + server_paths: vec![], + client_paths: vec![], }; - let output_assets = if *this.project.should_create_webpack_stats().await? { + let should_create_webpack_stats = *this.project.should_create_webpack_stats().await?; + + let output_assets = if !should_create_webpack_stats { + output_assets + } else { let webpack_stats = generate_webpack_stats(output_assets, this.project.dist_root()); let webpack_stats_read = webpack_stats.await?; let dist_root_owned = this.project.dist_root().owned().await?; @@ -386,8 +389,6 @@ impl Endpoint for AppEndpoint { .to_resolved() .await?; output_assets.concatenate(*ResolvedVc::cell(vec![ResolvedVc::upcast(stats_output)])) - } else { - output_assets }; Ok(EndpointOutput { diff --git a/crates/pack-api/src/library.rs b/crates/pack-api/src/library.rs index 3fe652782d..54dc28153f 100644 --- a/crates/pack-api/src/library.rs +++ b/crates/pack-api/src/library.rs @@ -326,13 +326,11 @@ impl Endpoint for LibraryEndpoint { let dist_root = self.project().dist_root().await?; - let (server_paths, client_paths) = (vec![], vec![]); - let written_endpoint = EndpointOutputPaths::NodeJs { // FIXME: No server path when bundling library server_entry_path: dist_root.to_string(), - server_paths, - client_paths, + server_paths: vec![], + client_paths: vec![], }; Ok(EndpointOutput { diff --git a/crates/pack-core/src/emit.rs b/crates/pack-core/src/emit.rs index a2cf2b2d7a..b55177bed3 100644 --- a/crates/pack-core/src/emit.rs +++ b/crates/pack-core/src/emit.rs @@ -15,7 +15,7 @@ use turbopack_core::{ #[turbo_tasks::function] pub async fn emit_assets( assets: Vc, - node_root: FileSystemPath, + _node_root: FileSystemPath, client_relative_path: FileSystemPath, client_output_path: FileSystemPath, ) -> Result<()> { @@ -24,18 +24,16 @@ pub async fn emit_assets( .iter() .copied() .map(|asset| { - let node_root = node_root.clone(); let client_relative_path = client_relative_path.clone(); let client_output_path = client_output_path.clone(); async move { let path = asset.path(); let span = tracing::trace_span!("emit asset", name = %path.to_string().await?); + // We allow to write output out of dist path, this is different with next.js async move { let path = path.await?; - Ok(if path.is_inside_ref(&node_root) { - Some(emit(*asset)) - } else if path.is_inside_ref(&client_relative_path) { + Ok(if path.is_inside_ref(&client_relative_path) { // Client assets are emitted to the client output path, which is prefixed // with _next. We need to rebase them to remove that // prefix. @@ -45,7 +43,7 @@ pub async fn emit_assets( client_output_path, )) } else { - None + Some(emit(*asset)) }) } .instrument(span) diff --git a/crates/pack-napi/src/pack_api/project.rs b/crates/pack-napi/src/pack_api/project.rs index a9be619c27..580f23f9bf 100644 --- a/crates/pack-napi/src/pack_api/project.rs +++ b/crates/pack-napi/src/pack_api/project.rs @@ -33,7 +33,9 @@ use pack_core::tracing_presets::{ TRACING_TURBOPACK_TARGETS, }; use tracing::Instrument; -use tracing_subscriber::{EnvFilter, Registry, layer::SubscriberExt, util::SubscriberInitExt}; +use tracing_subscriber::{ + EnvFilter, Registry, fmt::format::FmtSpan, layer::SubscriberExt, util::SubscriberInitExt, +}; use turbo_rcstr::RcStr; use turbo_tasks::{ NonLocalValue, OperationValue, PrettyPrintError, ReadRef, ResolvedVc, TaskInput, @@ -367,12 +369,18 @@ pub async fn project_new( }); } else { TRACING_INIT.call_once(|| { + let env_filter = EnvFilter::try_from_default_env(); + let env_filter_enabled = env_filter.is_ok(); tracing_subscriber::fmt() - .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| { + .with_env_filter(env_filter.unwrap_or_else(|_| { EnvFilter::new("pack_napi=info,pack_api=info,pack_core=info") })) - .with_target(false) - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::NONE) + .with_target(env_filter_enabled) + .with_span_events(if env_filter_enabled { + FmtSpan::CLOSE + } else { + FmtSpan::NONE + }) .with_timer(tracing_subscriber::fmt::time::ChronoLocal::new( "%Y-%m-%d %H:%M:%S.%3f".to_string(), )) diff --git a/package-lock.json b/package-lock.json index f8f817a32b..01540715d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7600,9 +7600,9 @@ } }, "node_modules/domparser-darwin-arm64": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-darwin-arm64/-/domparser-darwin-arm64-0.0.5.tgz", - "integrity": "sha512-7dNROB7Cv0MJOFkKBKYoO8RhljZmwwwybOUSQGmUoSm0DhFn3ahqPp/W4RNX/4P849EpYdWFxYmRF+s3omeOMA==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-darwin-arm64/-/domparser-darwin-arm64-0.0.7.tgz", + "integrity": "sha512-6lsDppVTrqV9G688q3OWYxghFd3g6gmelA9SR87waAic+eZ+FB7Goco3UxW936lJ0GvSpokiJlqcFX+QnkCfEw==", "cpu": [ "arm64" ], @@ -7616,9 +7616,9 @@ } }, "node_modules/domparser-darwin-x64": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-darwin-x64/-/domparser-darwin-x64-0.0.5.tgz", - "integrity": "sha512-qjzgFLcp6nnYaZq5YHLrlZYnNxU6CdCOQ+vCM0ySK96XB0xlz87VYi347ylyO2boThHlenDVLiDoC6/eq7IvxQ==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-darwin-x64/-/domparser-darwin-x64-0.0.7.tgz", + "integrity": "sha512-BSw91pFsEU56LSRtnqqn2I3pxv+zIh48V2Mp7Ku8q6XbHqUxSWR1POxRjtdjkntmJisTKg2LzezthJODxWMFUA==", "cpu": [ "x64" ], @@ -7632,9 +7632,9 @@ } }, "node_modules/domparser-linux-arm64-gnu": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-linux-arm64-gnu/-/domparser-linux-arm64-gnu-0.0.5.tgz", - "integrity": "sha512-ogEcw0I98MktYhHunyDw+uwsdRxM22HO4RYZPuEDUR6mrw+WFXMdgsl6FqsF4HXxS9d09FITAZvH1B1eRw21pQ==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-linux-arm64-gnu/-/domparser-linux-arm64-gnu-0.0.7.tgz", + "integrity": "sha512-F9Znw5XHqyVS/kMqstedfuy4sgqiLyPZVmG6fpvpNqkMX57pZaSPJlys9/OLwT2Fx+8oB8+8Byb/4E/vnPYqJQ==", "cpu": [ "arm64" ], @@ -7648,9 +7648,9 @@ } }, "node_modules/domparser-linux-arm64-musl": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-linux-arm64-musl/-/domparser-linux-arm64-musl-0.0.5.tgz", - "integrity": "sha512-9LkweiOrR86FLNibNEaX34YTfee7ypweTHCkNfQKOhwGbqHawz9bNtz0bhcj6zW0QQBGXgNJmxabvsLoPCGb6w==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-linux-arm64-musl/-/domparser-linux-arm64-musl-0.0.7.tgz", + "integrity": "sha512-dV14s5WwfotBFGrp5SCGLk0J6LCAj+ZcuuLmpQOsbekPCbiZksk7XOoE2RrZ03ny+/bWN+Sh+jaU9IGiryMVxQ==", "cpu": [ "arm64" ], @@ -7664,9 +7664,9 @@ } }, "node_modules/domparser-linux-x64-gnu": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-linux-x64-gnu/-/domparser-linux-x64-gnu-0.0.5.tgz", - "integrity": "sha512-md2XaziFXXd/1UkmkWWEGQ915UiEoFHAjIS6gLTVkv85UKuH664I8uqJp0cnahhzmOAnZEVy192HuoHyf3KGmw==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-linux-x64-gnu/-/domparser-linux-x64-gnu-0.0.7.tgz", + "integrity": "sha512-Ugu95+nsEyWgEsZ0v6cDp9rUHong0HeWMbjmzjICNIvAdbXfaCjbSk+m10YeOTk2N3O4svLvwfnCLYbRcvUTTg==", "cpu": [ "x64" ], @@ -7680,9 +7680,9 @@ } }, "node_modules/domparser-linux-x64-musl": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-linux-x64-musl/-/domparser-linux-x64-musl-0.0.5.tgz", - "integrity": "sha512-grluiaobq8ERZu6IKEEtSgrwAAH+RcnXPFN0UU2144D2bH4bBI7rJHijDxK+ghnR+kYLecWNesXH8u4PPEjVAg==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-linux-x64-musl/-/domparser-linux-x64-musl-0.0.7.tgz", + "integrity": "sha512-ssuCW0QL1ZB7MjOL0F5o06uy6qreaRsiA8EIGl5rfQstoWrQeKWEtI0yh7dIxvN++Zz0GLFY9IdbSj8GUuY4Kg==", "cpu": [ "x64" ], @@ -7696,9 +7696,9 @@ } }, "node_modules/domparser-rs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-rs/-/domparser-rs-0.0.5.tgz", - "integrity": "sha512-6RNWPBIsu7vcDa4SYs3/SFh9Ha0WuFzAfuZJeIg/alCDCrfSfDduR1CBkgbkD9wwDpowwbVKZS0YHHWqdTOgfg==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-rs/-/domparser-rs-0.0.7.tgz", + "integrity": "sha512-OGXsNHyFLGHGzi/zdPRw+Nv4jQdh7DCgmJAQYHXTIGXX1nW4RFwPyocv+VvemRHqs2QFOH6MDhpkzhiXiI6caA==", "license": "MIT", "workspaces": [ "npm/*" @@ -7707,20 +7707,20 @@ "node": ">= 10" }, "optionalDependencies": { - "domparser-darwin-arm64": "0.0.5", - "domparser-darwin-x64": "0.0.5", - "domparser-linux-arm64-gnu": "0.0.5", - "domparser-linux-arm64-musl": "0.0.5", - "domparser-linux-x64-gnu": "0.0.5", - "domparser-linux-x64-musl": "0.0.5", - "domparser-win32-arm64-msvc": "0.0.5", - "domparser-win32-x64-msvc": "0.0.5" + "domparser-darwin-arm64": "0.0.7", + "domparser-darwin-x64": "0.0.7", + "domparser-linux-arm64-gnu": "0.0.7", + "domparser-linux-arm64-musl": "0.0.7", + "domparser-linux-x64-gnu": "0.0.7", + "domparser-linux-x64-musl": "0.0.7", + "domparser-win32-arm64-msvc": "0.0.7", + "domparser-win32-x64-msvc": "0.0.7" } }, "node_modules/domparser-win32-arm64-msvc": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-win32-arm64-msvc/-/domparser-win32-arm64-msvc-0.0.5.tgz", - "integrity": "sha512-r5PUqGd6txpXMAKzT2UKlk3FXPDPYBAdz0WH//Ci58WAJWP7PQ9Eys5HT5jUZTl30eVjltjRm7JwoEy9112ooA==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-win32-arm64-msvc/-/domparser-win32-arm64-msvc-0.0.7.tgz", + "integrity": "sha512-tqr1ltXk0PG9U3kCFXzF6tEzA0AWVrV4Oa+jbyNb1JeVeuALf6uCQO0XjVdb0nknll5iMjwVXR2y2Mw+CEwTAw==", "cpu": [ "arm64" ], @@ -7734,9 +7734,9 @@ } }, "node_modules/domparser-win32-x64-msvc": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/domparser-win32-x64-msvc/-/domparser-win32-x64-msvc-0.0.5.tgz", - "integrity": "sha512-gMHFDh7D0e86iNErgHW/kO98nlzQS6WAG8SuDb/sGNPULDDaTSXX81MS70B2iUosdgbi90jnRtQJ7sDTz6G08g==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/domparser-win32-x64-msvc/-/domparser-win32-x64-msvc-0.0.7.tgz", + "integrity": "sha512-69XAew+0MublYlx7Mywe/9qkc/lo6L5QYsBBgwHDK96QPy4MFv5U4WgsXWXbKoeKEbBlRMyLA0iohF0qvU+Veg==", "cpu": [ "x64" ], @@ -15466,7 +15466,7 @@ "@swc/helpers": "0.5.15", "@utoo/pack-shared": "*", "@utoo/style-loader": "^1.0.0", - "domparser-rs": "^0.0.5", + "domparser-rs": "^0.0.7", "find-up": "4.1.0", "nanoid": "^3.3.11", "picocolors": "^1.1.1", diff --git a/packages/pack-shared/src/config.ts b/packages/pack-shared/src/config.ts index da27f9bc52..dec3637eca 100644 --- a/packages/pack-shared/src/config.ts +++ b/packages/pack-shared/src/config.ts @@ -213,6 +213,9 @@ export interface HtmlConfig { inject?: boolean | "body" | "head"; scriptLoading?: "blocking" | "defer" | "module"; meta?: Record; + output?: { + path?: string; + }; } export interface StyledComponentsConfig { diff --git a/packages/pack/package.json b/packages/pack/package.json index 336d3453ad..13ac3ebf2f 100644 --- a/packages/pack/package.json +++ b/packages/pack/package.json @@ -41,7 +41,7 @@ "@swc/helpers": "0.5.15", "@utoo/pack-shared": "*", "@utoo/style-loader": "^1.0.0", - "domparser-rs": "^0.0.5", + "domparser-rs": "^0.0.7", "find-up": "4.1.0", "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -67,7 +67,6 @@ "styled-jsx": "^5.1.6", "typescript": "^5.8.3" }, - "engines": { "node": ">= 20" }, diff --git a/packages/pack/src/commands/build.ts b/packages/pack/src/commands/build.ts index c6cfd2e500..3d3251a08f 100644 --- a/packages/pack/src/commands/build.ts +++ b/packages/pack/src/commands/build.ts @@ -69,7 +69,7 @@ async function buildInternal( packPath: getPackPath(), }, { - persistentCaching: false, + persistentCaching: bundleOptions.config.persistentCaching ?? false, }, ); diff --git a/packages/pack/src/core/hmr.ts b/packages/pack/src/core/hmr.ts index 9dc0cb0cb0..d27c784142 100644 --- a/packages/pack/src/core/hmr.ts +++ b/packages/pack/src/core/hmr.ts @@ -135,7 +135,7 @@ export async function createHotReloader( packPath: getPackPath(), }, { - persistentCaching: true, + persistentCaching: bundleOptions.config.persistentCaching ?? false, }, ); diff --git a/packages/pack/src/plugins/HtmlPlugin.ts b/packages/pack/src/plugins/HtmlPlugin.ts index facd036498..83adec61fd 100644 --- a/packages/pack/src/plugins/HtmlPlugin.ts +++ b/packages/pack/src/plugins/HtmlPlugin.ts @@ -117,6 +117,9 @@ export class HtmlPlugin { const finalHtml = doc.outerHTML; const filename = this.config.filename || "index.html"; - fs.writeFileSync(path.join(outputDir, filename), finalHtml); + fs.writeFileSync( + path.join(this.config.output?.path ?? outputDir, filename), + finalHtml, + ); } } diff --git a/packages/pack/src/utils/htmlEntry.ts b/packages/pack/src/utils/htmlEntry.ts index f839ff10c5..ffdd9aa25c 100644 --- a/packages/pack/src/utils/htmlEntry.ts +++ b/packages/pack/src/utils/htmlEntry.ts @@ -34,8 +34,10 @@ export function processHtmlEntry(config: ConfigComplete, projectPath: string) { } newEntries.push({ + ...entry, import: scriptPath, html: { + ...entry.html, template: entry.import, templateContent: doc.outerHTML, filename: path.basename(entry.import),