Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 3 additions & 2 deletions crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ use crate::{
get_typescript_transform_options,
},
util::{
OptionEnvMap, defines, foreign_code_context_condition, internal_assets_conditions,
OptionEnvMap, defines, foreign_code_context_condition,
free_var_references_with_vercel_system_env_warnings, internal_assets_conditions,
module_styles_rule_condition,
},
};
Expand All @@ -81,7 +82,7 @@ async fn next_client_defines(define_env: Vc<OptionEnvMap>) -> Result<Vc<CompileT
#[turbo_tasks::function]
async fn next_client_free_vars(define_env: Vc<OptionEnvMap>) -> Result<Vc<FreeVarReferences>> {
Ok(free_var_references!(
..defines(&*define_env.await?).into_iter(),
..free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)),
Buffer = FreeVarReference::EcmaScriptModule {
request: rcstr!("node:buffer"),
lookup_path: None,
Expand Down
7 changes: 5 additions & 2 deletions crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use crate::{
ModuleFeatureReportResolvePlugin, NextSharedRuntimeResolvePlugin,
get_invalid_client_only_resolve_plugin, get_invalid_styled_jsx_resolve_plugin,
},
util::{NextRuntime, OptionEnvMap, defines, foreign_code_context_condition},
util::{
NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
free_var_references_with_vercel_system_env_warnings,
},
};

#[turbo_tasks::function]
Expand All @@ -46,7 +49,7 @@ async fn next_edge_free_vars(
define_env: Vc<OptionEnvMap>,
) -> Result<Vc<FreeVarReferences>> {
Ok(free_var_references!(
..defines(&*define_env.await?).into_iter(),
..free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)),
Buffer = FreeVarReference::EcmaScriptModule {
request: rcstr!("buffer"),
lookup_path: Some(project_path),
Expand Down
7 changes: 3 additions & 4 deletions crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use turbopack_core::{
compile_time_defines,
compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences},
environment::{Environment, ExecutionEnvironment, NodeJsEnvironment, NodeJsVersion},
free_var_references,
module_graph::binding_usage_info::OptionBindingUsageInfo,
target::CompileTarget,
};
Expand Down Expand Up @@ -73,8 +72,8 @@ use crate::{
},
util::{
NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
get_transpiled_packages, internal_assets_conditions, load_next_js_jsonc_file,
module_styles_rule_condition,
free_var_references_with_vercel_system_env_warnings, get_transpiled_packages,
internal_assets_conditions, load_next_js_jsonc_file, module_styles_rule_condition,
},
};

Expand Down Expand Up @@ -357,7 +356,7 @@ async fn next_server_defines(define_env: Vc<OptionEnvMap>) -> Result<Vc<CompileT

#[turbo_tasks::function]
async fn next_server_free_vars(define_env: Vc<OptionEnvMap>) -> Result<Vc<FreeVarReferences>> {
Ok(free_var_references!(..defines(&*define_env.await?).into_iter()).cell())
Ok(free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)).cell())
}

#[turbo_tasks::function]
Expand Down
138 changes: 136 additions & 2 deletions crates/next-core/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ use bincode::{Decode, Encode};
use next_taskless::{expand_next_js_template, expand_next_js_template_no_imports};
use serde::{Deserialize, de::DeserializeOwned};
use turbo_rcstr::{RcStr, rcstr};
use turbo_tasks::{FxIndexMap, NonLocalValue, TaskInput, Vc, trace::TraceRawVcs};
use turbo_tasks::{FxIndexMap, NonLocalValue, TaskInput, Vc, fxindexset, trace::TraceRawVcs};
use turbo_tasks_fs::{File, FileContent, FileJsonContent, FileSystem, FileSystemPath, rope::Rope};
use turbopack::module_options::RuleCondition;
use turbopack_core::{
asset::AssetContent,
compile_time_info::{CompileTimeDefineValue, CompileTimeDefines, DefinableNameSegment},
compile_time_info::{
CompileTimeDefineValue, CompileTimeDefines, DefinableNameSegment, FreeVarReference,
FreeVarReferences,
},
condition::ContextCondition,
issue::IssueSeverity,
source::Source,
virtual_source::VirtualSource,
};
Expand Down Expand Up @@ -58,6 +62,136 @@ pub fn defines(define_env: &FxIndexMap<RcStr, Option<RcStr>>) -> CompileTimeDefi
CompileTimeDefines(defines)
}

/// Emits warnings or errors when inlining frequently changing Vercel system env vars
pub fn free_var_references_with_vercel_system_env_warnings(
defines: CompileTimeDefines,
) -> FreeVarReferences {
// List of system env vars:
// not available as NEXT_PUBLIC_* anyway:
// CI
// VERCEL
// VERCEL_SKEW_PROTECTION_ENABLED
// VERCEL_AUTOMATION_BYPASS_SECRET
// VERCEL_GIT_PROVIDER
// VERCEL_GIT_REPO_SLUG
// VERCEL_GIT_REPO_OWNER
// VERCEL_GIT_REPO_ID
// VERCEL_OIDC_TOKEN
//
// constant:
// VERCEL_PROJECT_PRODUCTION_URL
// VERCEL_REGION
// VERCEL_PROJECT_ID
//
// suboptimal (changes production main branch VS preview branches):
// VERCEL_ENV
// VERCEL_TARGET_ENV
//
// bad (changes per branch):
// VERCEL_BRANCH_URL
// VERCEL_GIT_COMMIT_REF
// VERCEL_GIT_PULL_REQUEST_ID
//
// catastrophic (changes per commit):
// NEXT_DEPLOYMENT_ID
// VERCEL_URL
// VERCEL_DEPLOYMENT_ID
// VERCEL_GIT_COMMIT_SHA
// VERCEL_GIT_COMMIT_MESSAGE
// VERCEL_GIT_COMMIT_AUTHOR_LOGIN
// VERCEL_GIT_COMMIT_AUTHOR_NAME
// VERCEL_GIT_PREVIOUS_SHA

let entries = defines
.0
.into_iter()
.map(|(k, value)| (k, FreeVarReference::Value(value)));

let should_error = std::env::var("NEXT_TURBOPACK_SYSTEM_ENV_ERROR")
.ok()
.is_some_and(|v| !v.is_empty());

fn wrap_report_next_public_usage(
public_env_var: &str,
inner: Option<Box<FreeVarReference>>,
should_error: bool,
) -> FreeVarReference {
let message = match public_env_var {
"NEXT_PUBLIC_NEXT_DEPLOYMENT_ID" | "NEXT_PUBLIC_VERCEL_DEPLOYMENT_ID" => {
rcstr!(
"The deployment id is being inlined. Use process.env.NEXT_DEPLOYMENT_ID \
instead to access the same value without inlining, for faster deploy times \
and better browser client-side caching."
)
}
_ => format!(
"A system environment variable is being inlined. This variable changes on every \
deployment, causing slower deploy times and worse browser client-side caching. \
For server-side code, replace with process.env.{} and for browser code, try to \
remove it.",
public_env_var.strip_prefix("NEXT_PUBLIC_").unwrap(),
)
.into(),
};
FreeVarReference::ReportUsage {
message,
severity: if should_error {
IssueSeverity::Error
} else {
IssueSeverity::Warning
},
inner,
}
}

let mut list = fxindexset!(
"NEXT_PUBLIC_NEXT_DEPLOYMENT_ID",
"NEXT_PUBLIC_VERCEL_BRANCH_URL",
"NEXT_PUBLIC_VERCEL_DEPLOYMENT_ID",
"NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN",
"NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME",
"NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE",
"NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF",
"NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA",
"NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA",
"NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID",
"NEXT_PUBLIC_VERCEL_URL",
);

let mut entries: FxIndexMap<_, _> = entries
.map(|(k, value)| {
let value = if let &[
DefinableNameSegment::Name(a),
DefinableNameSegment::Name(b),
DefinableNameSegment::Name(public_env_var),
] = &&*k
&& a == "process"
&& b == "env"
&& list.swap_remove(&**public_env_var)
{
wrap_report_next_public_usage(public_env_var, Some(Box::new(value)), should_error)
} else {
value
};
(k, value)
})
.collect();

// For the remaining ones, still add a warning, but without replacement
for public_env_var in list {
entries.insert(
vec![
rcstr!("process").into(),
rcstr!("env").into(),
DefinableNameSegment::Name(public_env_var.into()),
],
wrap_report_next_public_usage(public_env_var, None, should_error),
);
}

FreeVarReferences(entries)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)]
pub enum PathType {
PagesPage,
Expand Down
9 changes: 9 additions & 0 deletions turbopack/crates/turbopack-core/src/compile_time_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,15 @@ impl FreeVarReferences {
}
}

impl IntoIterator for FreeVarReferences {
type Item = (Vec<DefinableNameSegment>, FreeVarReference);
type IntoIter = indexmap::map::IntoIter<Vec<DefinableNameSegment>, FreeVarReference>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

#[turbo_tasks::value(shared)]
#[derive(Debug, Clone)]
pub struct CompileTimeInfo {
Expand Down
Loading