Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
26 changes: 15 additions & 11 deletions crates/pack-api/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use pack_core::{
get_client_module_options_context, get_client_resolve_options_context,
get_client_runtime_entries,
},
library::contexts::get_library_chunking_context,
library::contexts::{LibraryChunkingContextOptions, get_library_chunking_context},
util::convert_to_project_relative,
};
use qstring::QString;
Expand Down Expand Up @@ -238,17 +238,21 @@ impl LibraryEndpoint {
runtime_export: Vc<Vec<RcStr>>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let project = self.project();

Ok(get_library_chunking_context(
project.project_root().owned().await?,
project.dist_root().owned().await?,
rcstr!("/ROOT"),
project.client_compile_time_info().environment(),
project.mode(),
project.module_ids(),
project.no_mangling(),
runtime_root,
runtime_export,
project.config(),
LibraryChunkingContextOptions {
mode: project.mode(),
root_path: project.project_root().owned().await?,
output_root: project.dist_root().owned().await?,
output_root_to_root_path: rcstr!("/ROOT"),
environment: project.client_compile_time_info().environment(),
module_id_strategy: project.module_ids(),
no_mangling: project.no_mangling(),
runtime_root,
runtime_export,
config: project.config(),
export_usage: project.export_usage(),
},
))
}

Expand Down
43 changes: 31 additions & 12 deletions crates/pack-api/src/project.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use anyhow::{Context, Result, bail};
use pack_core::{
all_assets_from_entries,
client::context::{get_client_chunking_context, get_client_compile_time_info},
client::context::{
ClientChunkingContextOptions, get_client_chunking_context, get_client_compile_time_info,
},
config::{Config, ModuleIds as ModuleIdStrategyConfig},
emit_assets,
mode::Mode,
Expand Down Expand Up @@ -46,6 +48,7 @@ use turbopack_core::{
module_graph::{
GraphEntries, ModuleGraph, SingleModuleGraph, VisitedModules,
chunk_group_info::ChunkGroupEntry,
export_usage::{OptionExportUsageInfo, compute_export_usage_info},
},
output::{OutputAsset, OutputAssets},
raw_output::RawOutput,
Expand Down Expand Up @@ -892,17 +895,18 @@ impl Project {

#[turbo_tasks::function]
pub async fn client_chunking_context(self: Vc<Self>) -> Result<Vc<Box<dyn ChunkingContext>>> {
Ok(get_client_chunking_context(
self.project_root().owned().await?,
self.client_root().owned().await?,
rcstr!("/ROOT"),
Some(self.dist_dir().owned().await?),
self.client_compile_time_info().environment(),
self.mode(),
self.module_ids(),
self.no_mangling(),
self.config(),
))
Ok(get_client_chunking_context(ClientChunkingContextOptions {
mode: self.mode(),
root_path: self.project_root().owned().await?,
output_root: self.client_root().owned().await?,
output_root_to_root_path: rcstr!("/ROOT"),
chunk_base_path: Some(self.dist_dir().owned().await?),
environment: self.client_compile_time_info().environment(),
module_id_strategy: self.module_ids(),
no_mangling: self.no_mangling(),
config: self.config(),
export_usage: self.export_usage(),
}))
}

#[turbo_tasks::function]
Expand Down Expand Up @@ -1161,6 +1165,21 @@ impl Project {
}
}

/// Computed the used exports for each module.
#[turbo_tasks::function]
pub async fn export_usage(self: Vc<Self>) -> Result<Vc<OptionExportUsageInfo>> {
if *self.config().remove_unused_exports(self.mode()).await? {
let module_graphs = self.whole_app_module_graphs().await?;
Ok(Vc::cell(Some(
compute_export_usage_info(module_graphs.full)
.resolve_strongly_consistent()
.await?,
)))
} else {
Ok(Vc::cell(None))
}
}

#[turbo_tasks::function]
pub async fn copy_output_assets(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
let project_path = self.project_path().owned().await?;
Expand Down
50 changes: 38 additions & 12 deletions crates/pack-core/src/client/context.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::{collections::BTreeSet, str::FromStr};

use anyhow::Result;
use serde::{Deserialize, Serialize};
use turbo_rcstr::{RcStr, rcstr};
use turbo_tasks::{FxIndexMap, ResolvedVc, TryJoinIterExt, ValueToString, Vc};
use turbo_tasks::{
FxIndexMap, ResolvedVc, TaskInput, TryJoinIterExt, ValueToString, Vc, trace::TraceRawVcs,
};
use turbo_tasks_env::EnvMap;
use turbo_tasks_fs::FileSystemPath;
use turbopack::{
Expand All @@ -26,6 +29,7 @@ use turbopack_core::{
environment::{BrowserEnvironment, Environment, ExecutionEnvironment},
file_source::FileSource,
free_var_references,
module_graph::export_usage::OptionExportUsageInfo,
};
use turbopack_ecmascript::{TypeofWindow, chunk::EcmascriptChunkType};
use turbopack_node::{
Expand Down Expand Up @@ -470,18 +474,37 @@ pub async fn get_client_resolve_options_context(
.cell())
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Serialize, Deserialize)]
pub struct ClientChunkingContextOptions {
pub mode: Vc<Mode>,
pub root_path: FileSystemPath,
pub output_root: FileSystemPath,
pub output_root_to_root_path: RcStr,
pub chunk_base_path: Option<RcStr>,
pub environment: Vc<Environment>,
pub module_id_strategy: Vc<Box<dyn ModuleIdStrategy>>,
pub no_mangling: Vc<bool>,
pub config: Vc<Config>,
pub export_usage: Vc<OptionExportUsageInfo>,
}

#[turbo_tasks::function]
pub async fn get_client_chunking_context(
root_path: FileSystemPath,
output_root: FileSystemPath,
output_root_to_root_path: RcStr,
chunk_base_path: Option<RcStr>,
environment: ResolvedVc<Environment>,
mode: Vc<Mode>,
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
no_mangling: Vc<bool>,
config: ResolvedVc<Config>,
options: ClientChunkingContextOptions,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let ClientChunkingContextOptions {
mode,
root_path,
output_root,
output_root_to_root_path,
chunk_base_path,
environment,
module_id_strategy,
no_mangling,
config,
export_usage,
} = options;

let minify = config.minify(mode);
let concatenate_modules = config.concatenate_modules(mode);
let mode = mode.await?;
Expand Down Expand Up @@ -509,7 +532,7 @@ pub async fn get_client_chunking_context(
output_root.clone(),
output_root.clone(),
output_root,
environment,
environment.to_resolved().await?,
runtime_type,
)
.minify_type(if mode.is_production() && *minify.await? {
Expand All @@ -526,10 +549,13 @@ pub async fn get_client_chunking_context(
})
.chunk_base_path(chunk_base_path)
.current_chunk_method(CurrentChunkMethod::DocumentCurrentScript)
.module_id_strategy(module_id_strategy);
.export_usage(*export_usage.await?)
.module_id_strategy(module_id_strategy.to_resolved().await?);

let output = config.output().await?;

builder = builder.asset_base_path(output.asset_prefix.clone());

if !mode.is_development() {
if let Some(filename) = &output.filename {
builder = builder.filename(filename.clone());
Expand Down
15 changes: 15 additions & 0 deletions crates/pack-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ pub struct OptimizationConfig {
/// improving caching.
#[serde(default)]
pub concatenate_modules: Option<bool>,
/// Defaults to false in development mode, true in production mode.
pub remove_unused_exports: Option<bool>,
}

#[derive(
Expand All @@ -328,6 +330,8 @@ pub struct OutputConfig {
pub r#type: Option<OutputType>,
pub clean: Option<bool>,
pub copy: Option<Vec<CopyItem>>,
/// URL prefix that will be prepended to all static asset URLs when loading them.
pub asset_prefix: Option<RcStr>,
}

#[derive(
Expand Down Expand Up @@ -1342,6 +1346,17 @@ impl Config {
.cell()
}

#[turbo_tasks::function]
pub async fn remove_unused_exports(&self, mode: Vc<Mode>) -> Result<Vc<bool>> {
let remove_unused_exports = self.optimization.as_ref().map(|op| {
op.remove_unused_exports
.is_none_or(|remove_unused_exports| remove_unused_exports)
});
Ok(Vc::cell(
remove_unused_exports.unwrap_or(matches!(*mode.await?, Mode::Production)),
))
}

#[turbo_tasks::function]
pub fn module_ids(&self) -> Vc<OptionModuleIds> {
let Some(module_ids) = self.optimization.as_ref().and_then(|t| t.module_ids) else {
Expand Down
20 changes: 19 additions & 1 deletion crates/pack-core/src/library/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ impl LibraryChunkingContextBuilder {
self
}

pub fn asset_base_path(mut self, asset_base_path: Option<RcStr>) -> Self {
self.chunking_context.asset_base_path = asset_base_path;
self
}

pub fn build(self) -> Vc<LibraryChunkingContext> {
LibraryChunkingContext::cell(self.chunking_context)
}
Expand Down Expand Up @@ -161,6 +166,8 @@ pub struct LibraryChunkingContext {
output_root: FileSystemPath,
/// The relative path from the output_root to the root_path.
output_root_to_root_path: RcStr,
/// URL prefix that will be prepended to all static asset URLs when loading them.
asset_base_path: Option<RcStr>,
/// The environment chunks will be evaluated in.
environment: ResolvedVc<Environment>,
/// Enable module merging
Expand Down Expand Up @@ -198,6 +205,7 @@ impl LibraryChunkingContext {
output_root,
output_root_to_root_path,
should_use_file_source_map_uris: false,
asset_base_path: None,
environment,
runtime_type,
minify_type: MinifyType::NoMinify,
Expand Down Expand Up @@ -410,7 +418,17 @@ impl ChunkingContext for LibraryChunkingContext {
async fn asset_url(&self, ident: FileSystemPath) -> Result<Vc<RcStr>> {
let asset_path = ident.to_string();

Ok(Vc::cell(asset_path.into()))
Ok(Vc::cell(
format!(
"{}{}",
self.asset_base_path
.as_ref()
.map(|s| s.as_str())
.unwrap_or(""),
asset_path
)
.into(),
))
}

#[turbo_tasks::function]
Expand Down
53 changes: 39 additions & 14 deletions crates/pack-core/src/library/contexts.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
use turbo_rcstr::RcStr;
use turbo_tasks::{ResolvedVc, Vc};
use turbo_tasks::{TaskInput, Vc, trace::TraceRawVcs};
use turbo_tasks_fs::FileSystemPath;
use turbopack_core::{
chunk::{
ChunkingContext, MangleType, MinifyType, SourceMapsType,
module_id_strategies::ModuleIdStrategy,
},
environment::Environment,
module_graph::export_usage::OptionExportUsageInfo,
};

use crate::{config::Config, mode::Mode};

use super::LibraryChunkingContext;

#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Serialize, Deserialize)]
pub struct LibraryChunkingContextOptions {
pub mode: Vc<Mode>,
pub root_path: FileSystemPath,
pub output_root: FileSystemPath,
pub output_root_to_root_path: RcStr,
pub environment: Vc<Environment>,
pub module_id_strategy: Vc<Box<dyn ModuleIdStrategy>>,
pub no_mangling: Vc<bool>,
pub runtime_root: Vc<Option<RcStr>>,
pub runtime_export: Vc<Vec<RcStr>>,
pub config: Vc<Config>,
pub export_usage: Vc<OptionExportUsageInfo>,
}

#[turbo_tasks::function]
pub async fn get_library_chunking_context(
root_path: FileSystemPath,
output_root: FileSystemPath,
output_root_to_root_path: RcStr,
environment: ResolvedVc<Environment>,
mode: Vc<Mode>,
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
no_mangling: Vc<bool>,
runtime_root: Vc<Option<RcStr>>,
runtime_export: Vc<Vec<RcStr>>,
config: ResolvedVc<Config>,
options: LibraryChunkingContextOptions,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let LibraryChunkingContextOptions {
mode,
root_path,
output_root,
output_root_to_root_path,
environment,
module_id_strategy,
no_mangling,
runtime_root,
runtime_export,
config,
export_usage,
} = options;
let minify = config.minify(mode);
let concatenate_modules = config.concatenate_modules(mode);
let mode = mode.await?;
Expand All @@ -47,11 +68,13 @@ pub async fn get_library_chunking_context(
}
};

let output = config.output().await?;

let mut builder = LibraryChunkingContext::builder(
root_path,
output_root,
output_root_to_root_path,
environment,
environment.to_resolved().await?,
runtime_type,
(*runtime_root.await?).clone(),
(*runtime_export.await?).clone(),
Expand All @@ -68,10 +91,12 @@ pub async fn get_library_chunking_context(
} else {
SourceMapsType::None
})
.module_id_strategy(module_id_strategy);
.asset_base_path(output.asset_prefix.clone())
.module_id_strategy(module_id_strategy.to_resolved().await?)
.export_usage(*export_usage.await?);

if !mode.is_development()
&& let Some(filename) = &config.output().await?.filename
&& let Some(filename) = &output.filename
{
builder = builder.filename(filename.clone());
}
Expand Down
Loading
Loading