Skip to content

Commit

Permalink
Misc. changes to support App Router build (vercel/turborepo#5448)
Browse files Browse the repository at this point in the history
### Description

<!--
  ✍️ Write a short summary of your work.
  If necessary, include relevant screenshots.
-->

### Testing Instructions

<!--
  Give a quick description of steps to test your changes.
-->
  • Loading branch information
alexkirsz committed Jul 12, 2023
1 parent 587b26f commit df1e6c7
Show file tree
Hide file tree
Showing 23 changed files with 177 additions and 53 deletions.
14 changes: 14 additions & 0 deletions crates/turbo-tasks/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ impl ValueToString for U64 {
#[turbo_tasks::value(transparent)]
pub struct OptionString(Option<std::string::String>);

#[turbo_tasks::value_impl]
impl OptionStringVc {
#[turbo_tasks::function]
pub fn none() -> Self {
Self::cell(None)
}
}

impl Default for OptionStringVc {
fn default() -> Self {
Self::none()
}
}

#[turbo_tasks::value(transparent)]
pub struct Strings(Vec<std::string::String>);

Expand Down
3 changes: 1 addition & 2 deletions crates/turbopack-build/src/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl BuildChunkingContextVc {
/// * exports the result of evaluating the given module as a CommonJS
/// default export.
#[turbo_tasks::function]
pub async fn generate_entry_chunk(
pub async fn entry_chunk(
self_vc: BuildChunkingContextVc,
path: FileSystemPathVc,
module: EcmascriptChunkPlaceableVc,
Expand All @@ -129,7 +129,6 @@ impl BuildChunkingContextVc {
let asset = EcmascriptBuildNodeEntryChunkVc::new(
path,
self_vc,
entry_chunk,
AssetsVc::cell(other_chunks),
evaluatable_assets,
module,
Expand Down
5 changes: 1 addition & 4 deletions crates/turbopack-build/src/ecmascript/node/entry/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc};
use turbo_tasks_fs::{File, FileSystemPathVc};
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc, AssetsVc},
chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc},
chunk::{ChunkingContext, EvaluatableAssetsVc},
code_builder::{CodeBuilder, CodeVc},
ident::AssetIdentVc,
reference::{AssetReferencesVc, SingleAssetReferenceVc},
Expand All @@ -28,7 +28,6 @@ use crate::BuildChunkingContextVc;
pub(crate) struct EcmascriptBuildNodeEntryChunk {
path: FileSystemPathVc,
chunking_context: BuildChunkingContextVc,
entry_chunk: ChunkVc,
other_chunks: AssetsVc,
evaluatable_assets: EvaluatableAssetsVc,
exported_module: EcmascriptChunkPlaceableVc,
Expand All @@ -41,15 +40,13 @@ impl EcmascriptBuildNodeEntryChunkVc {
pub fn new(
path: FileSystemPathVc,
chunking_context: BuildChunkingContextVc,
entry_chunk: ChunkVc,
other_chunks: AssetsVc,
evaluatable_assets: EvaluatableAssetsVc,
exported_module: EcmascriptChunkPlaceableVc,
) -> Self {
EcmascriptBuildNodeEntryChunk {
path,
chunking_context,
entry_chunk,
other_chunks,
evaluatable_assets,
exported_module,
Expand Down
3 changes: 2 additions & 1 deletion crates/turbopack-cli/src/dev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ async fn source(
)
.build();

let execution_context = ExecutionContextVc::new(project_path, build_chunking_context, env);
let execution_context =
ExecutionContextVc::new(project_path, build_chunking_context.into(), env);

let server_fs = ServerFileSystemVc::new().as_file_system();
let server_root = server_fs.root();
Expand Down
1 change: 1 addition & 0 deletions crates/turbopack-cli/src/dev/web_entry_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ pub fn get_client_chunking_context(
)
.hot_module_replacement()
.build()
.into()
}

#[turbo_tasks::function]
Expand Down
9 changes: 5 additions & 4 deletions crates/turbopack-css/src/chunk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc, AssetsVc},
chunk::{
availability_info::AvailabilityInfo, chunk_content, chunk_content_split, Chunk,
ChunkContentResult, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModuleVc, ChunkingContext,
ChunkingContextVc, ChunksVc, FromChunkableModule, ModuleId, ModuleIdVc, ModuleIdsVc,
OutputChunk, OutputChunkRuntimeInfo, OutputChunkRuntimeInfoVc, OutputChunkVc,
ChunkContentResult, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModule, ChunkableModuleVc,
ChunkingContext, ChunkingContextVc, ChunksVc, FromChunkableModule, ModuleId, ModuleIdVc,
ModuleIdsVc, OutputChunk, OutputChunkRuntimeInfo, OutputChunkRuntimeInfoVc, OutputChunkVc,
},
code_builder::{CodeBuilder, CodeVc},
ident::{AssetIdent, AssetIdentVc},
introspect::{
asset::{children_from_asset_references, content_to_details, IntrospectableAssetVc},
Introspectable, IntrospectableChildrenVc, IntrospectableVc,
},
module::{Module, ModuleVc},
reference::{AssetReference, AssetReferenceVc, AssetReferencesVc},
resolve::PrimaryResolveResult,
source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc},
Expand Down Expand Up @@ -457,7 +458,7 @@ impl CssChunkContextVc {
}

#[turbo_tasks::value_trait]
pub trait CssChunkPlaceable: Asset {
pub trait CssChunkPlaceable: ChunkableModule + Module + Asset {
fn as_chunk_item(&self, context: ChunkingContextVc) -> CssChunkItemVc;
}

Expand Down
3 changes: 1 addition & 2 deletions crates/turbopack-dev-server/src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ impl DevHtmlAssetVc {
async fn html_content(self) -> Result<DevHtmlAssetContentVc> {
let this = self.await?;
let context_path = this.path.parent().await?;

let mut chunk_paths = vec![];
for chunk in &*self.chunks().await? {
let chunk_path = &*chunk.ident().path().await?;
Expand Down Expand Up @@ -173,7 +172,7 @@ struct DevHtmlAssetContent {
}

impl DevHtmlAssetContentVc {
pub fn new(chunk_paths: Vec<String>, body: Option<String>) -> Self {
fn new(chunk_paths: Vec<String>, body: Option<String>) -> Self {
DevHtmlAssetContent { chunk_paths, body }.cell()
}
}
Expand Down
20 changes: 17 additions & 3 deletions crates/turbopack-dev/src/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::Result;
use indexmap::IndexSet;
use turbo_tasks::{
graph::{AdjacencyMap, GraphTraversal},
primitives::{BoolVc, StringVc},
primitives::{BoolVc, OptionStringVc, StringVc},
TryJoinIterExt, Value,
};
use turbo_tasks_fs::FileSystemPathVc;
Expand Down Expand Up @@ -41,6 +41,11 @@ impl DevChunkingContextBuilder {
self
}

pub fn chunk_base_path(mut self, chunk_base_path: OptionStringVc) -> Self {
self.context.chunk_base_path = chunk_base_path;
self
}

pub fn layer(mut self, layer: &str) -> Self {
self.context.layer = (!layer.is_empty()).then(|| layer.to_string());
self
Expand All @@ -61,8 +66,8 @@ impl DevChunkingContextBuilder {
self
}

pub fn build(self) -> ChunkingContextVc {
DevChunkingContextVc::new(Value::new(self.context)).into()
pub fn build(self) -> DevChunkingContextVc {
DevChunkingContextVc::new(Value::new(self.context))
}
}

Expand All @@ -87,6 +92,9 @@ pub struct DevChunkingContext {
reference_css_chunk_source_maps: bool,
/// Static assets are placed at this path
asset_root_path: FileSystemPathVc,
/// Base path that will be prepended to all chunk URLs when loading them.
/// This path will not appear in chunk paths or chunk data.
chunk_base_path: OptionStringVc,
/// Layer name within this context
layer: Option<String>,
/// Enable HMR for this chunking
Expand All @@ -113,6 +121,7 @@ impl DevChunkingContextVc {
reference_chunk_source_maps: true,
reference_css_chunk_source_maps: true,
asset_root_path,
chunk_base_path: Default::default(),
layer: None,
enable_hot_module_replacement: false,
environment,
Expand All @@ -130,6 +139,11 @@ impl DevChunkingContext {
pub fn runtime_type(&self) -> RuntimeType {
self.runtime_type
}

/// Returns the asset base path.
pub fn chunk_base_path(&self) -> OptionStringVc {
self.chunk_base_path
}
}

#[turbo_tasks::value_impl]
Expand Down
8 changes: 6 additions & 2 deletions crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl EcmascriptDevEvaluateChunkVc {
#[turbo_tasks::function]
async fn code(self) -> Result<CodeVc> {
let this = self.await?;
let chunking_context = this.chunking_context.await?;
let environment = this.chunking_context.environment();

let output_root = this.chunking_context.output_root().await?;
Expand Down Expand Up @@ -137,9 +138,12 @@ impl EcmascriptDevEvaluateChunkVc {
StringifyJs(&params),
)?;

match this.chunking_context.await?.runtime_type() {
match chunking_context.runtime_type() {
RuntimeType::Default => {
let runtime_code = turbopack_ecmascript_runtime::get_dev_runtime_code(environment);
let runtime_code = turbopack_ecmascript_runtime::get_dev_runtime_code(
environment,
chunking_context.chunk_base_path(),
);
code.push_code(&*runtime_code.await?);
}
#[cfg(feature = "test")]
Expand Down
2 changes: 1 addition & 1 deletion crates/turbopack-dev/src/ecmascript/merged/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl EcmascriptModuleEntry {
EcmascriptModuleEntry {
// Cloning a rope is cheap.
code: code.source_code().clone(),
url: format!("/{}?{}", chunk_path, &id),
url: format!("{}?{}", chunk_path, &id),
map: code
.has_source_map()
.then(|| format!("/__turbopack_sourcemap__/{}.map?{}", chunk_path, &id)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ pub struct ClientDirectiveTransformer {
}

impl ClientDirectiveTransformer {
pub fn new(transition_name: &StringVc) -> Self {
Self {
transition_name: *transition_name,
}
pub fn new(transition_name: StringVc) -> Self {
Self { transition_name }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
type RefreshRuntimeGlobals =
import("@next/react-refresh-utils/dist/runtime").RefreshRuntimeGlobals;

declare var CHUNK_BASE_PATH: string;
declare var $RefreshHelpers$: RefreshRuntimeGlobals["$RefreshHelpers$"];
declare var $RefreshReg$: RefreshRuntimeGlobals["$RefreshReg$"];
declare var $RefreshSig$: RefreshRuntimeGlobals["$RefreshSig$"];
Expand Down Expand Up @@ -1287,6 +1288,13 @@ function getOrInstantiateRuntimeModule(
return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });
}

/**
* Returns the URL relative to the origin where a chunk can be fetched from.
*/
function getChunkRelativeUrl(chunkPath: ChunkPath): string {
return `${CHUNK_BASE_PATH}${chunkPath}`;
}

/**
* Subscribes to chunk list updates from the update server and applies them.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ function commonJsRequireContext(
unloadChunk(chunkPath) {
deleteResolver(chunkPath);

const chunkUrl = getChunkRelativeUrl(chunkPath);

if (chunkPath.endsWith(".css")) {
const links = document.querySelectorAll(`link[href="/${chunkPath}"]`);
const links = document.querySelectorAll(`link[href="${chunkUrl}"]`);
for (const link of Array.from(links)) {
link.remove();
}
Expand All @@ -74,9 +76,7 @@ function commonJsRequireContext(
// runtime once evaluated.
// However, we still want to remove the script tag from the DOM to keep
// the HTML somewhat consistent from the user's perspective.
const scripts = document.querySelectorAll(
`script[src="/${chunkPath}"]`
);
const scripts = document.querySelectorAll(`script[src="${chunkUrl}"]`);
for (const script of Array.from(scripts)) {
script.remove();
}
Expand All @@ -97,8 +97,10 @@ function commonJsRequireContext(
.map((p) => encodeURIComponent(p))
.join("/");

const chunkUrl = `/${getChunkRelativeUrl(encodedChunkPath)}`;

const previousLink = document.querySelector(
`link[rel=stylesheet][href^="/${encodedChunkPath}"]`
`link[rel=stylesheet][href^="${chunkUrl}"]`
);

if (previousLink == null) {
Expand All @@ -108,7 +110,7 @@ function commonJsRequireContext(

const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `/${encodedChunkPath}`;
link.href = chunkUrl;
link.onerror = () => {
reject();
};
Expand Down Expand Up @@ -194,10 +196,12 @@ function commonJsRequireContext(
return resolver.promise;
}

const chunkUrl = `/${getChunkRelativeUrl(chunkPath)}`;

if (chunkPath.endsWith(".css")) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `/${chunkPath}`;
link.href = chunkUrl;
link.onerror = () => {
resolver.reject();
};
Expand All @@ -209,7 +213,7 @@ function commonJsRequireContext(
document.body.appendChild(link);
} else if (chunkPath.endsWith(".js")) {
const script = document.createElement("script");
script.src = `/${chunkPath}`;
script.src = chunkUrl;
// We'll only mark the chunk as loaded once the script has been executed,
// which happens in `registerChunk`. Hence the absence of `resolve()` in
// this branch.
Expand All @@ -226,7 +230,7 @@ function commonJsRequireContext(
})();

function _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory {
code += `\n\n//# sourceURL=${location.origin}${url}`;
code += `\n\n//# sourceURL=${location.origin}/${url}`;
if (map) code += `\n//# sourceMappingURL=${map}`;
return eval(code);
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function dynamicExport(module: Module, object: Record<string, any>) {
let reexportedObjects = module[REEXPORTED_OBJECTS];
if (!reexportedObjects) {
reexportedObjects = module[REEXPORTED_OBJECTS] = [];
module.namespaceObject = new Proxy(module.exports, {
module.exports = module.namespaceObject = new Proxy(module.exports, {
get(target, prop) {
if (
hasOwnProperty.call(target, prop) ||
Expand Down
17 changes: 14 additions & 3 deletions crates/turbopack-ecmascript-runtime/src/dev_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ use std::io::Write;

use anyhow::Result;
use indoc::writedoc;
use turbo_tasks::primitives::OptionStringVc;
use turbopack_core::{
code_builder::{CodeBuilder, CodeVc},
context::AssetContext,
environment::{ChunkLoading, EnvironmentVc},
};
use turbopack_ecmascript::StaticEcmascriptCodeVc;
use turbopack_ecmascript::{utils::StringifyJs, StaticEcmascriptCodeVc};

use crate::{asset_context::get_runtime_asset_context, embed_file_path};

/// Returns the code for the development ECMAScript runtime.
#[turbo_tasks::function]
pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result<CodeVc> {
pub async fn get_dev_runtime_code(
environment: EnvironmentVc,
chunk_base_path: OptionStringVc,
) -> Result<CodeVc> {
let asset_context = get_runtime_asset_context(environment);

let shared_runtime_utils_code =
Expand Down Expand Up @@ -50,7 +54,14 @@ pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result<CodeVc>
if (!Array.isArray(globalThis.TURBOPACK)) {{
return;
}}
"#
const CHUNK_BASE_PATH = {};
"#,
StringifyJs(if let Some(chunk_base_path) = &*chunk_base_path.await? {
chunk_base_path.as_str()
} else {
""
})
)?;

code.push_code(&*shared_runtime_utils_code.await?);
Expand Down
2 changes: 1 addition & 1 deletion crates/turbopack-tests/tests/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ async fn run_test(resource: &str) -> Result<RunTestResultVc> {
CommandLineProcessEnvVc::new().into(),
test_asset.ident(),
context,
chunking_context,
chunking_context.into(),
Some(EvaluatableAssetsVc::many(vec![
EvaluatableAssetVc::from_source(jest_runtime_asset.into(), context),
EvaluatableAssetVc::from_source(test_asset.into(), context),
Expand Down
Loading

0 comments on commit df1e6c7

Please sign in to comment.