Skip to content

Commit

Permalink
remove get_by_id (for performance) (#88)
Browse files Browse the repository at this point in the history
I also needed to remove the old html runtime, use new runtime for CSP to
update the CSS HMR code
  • Loading branch information
sokra authored Oct 19, 2022
1 parent 79ac955 commit 3ea2090
Show file tree
Hide file tree
Showing 86 changed files with 850 additions and 1,173 deletions.
5 changes: 5 additions & 0 deletions crates/next-core/js/src/dev/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { initializeHMR } from "./client";

initializeHMR({
assetPrefix: "",
});
45 changes: 25 additions & 20 deletions crates/next-core/js/src/dev/hmr-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type {
ServerMessage,
} from "@vercel/turbopack-runtime/types/protocol";
import type {
ChunkId,
ChunkUpdateCallback,
TurbopackGlobals,
} from "@vercel/turbopack-runtime/types";
Expand All @@ -29,36 +28,36 @@ export function connect() {
throw new Error("A separate HMR handler was already registered");
}
globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = {
push: ([chunkId, callback]: [ChunkId, ChunkUpdateCallback]) => {
onChunkUpdate(chunkId, callback);
push: ([chunkPath, callback]: [string, ChunkUpdateCallback]) => {
onChunkUpdate(chunkPath, callback);
},
};

if (Array.isArray(queued)) {
for (const [chunkId, callback] of queued) {
onChunkUpdate(chunkId, callback);
for (const [chunkPath, callback] of queued) {
onChunkUpdate(chunkPath, callback);
}
}

subscribeToInitialCssChunksUpdates();
}

const chunkUpdateCallbacks: Map<ChunkId, ChunkUpdateCallback[]> = new Map();
const chunkUpdateCallbacks: Map<string, ChunkUpdateCallback[]> = new Map();

function sendJSON(message: ClientMessage) {
sendMessage(JSON.stringify(message));
}

function subscribeToChunkUpdates(chunkId: ChunkId) {
function subscribeToChunkUpdates(chunkPath: string) {
sendJSON({
type: "subscribe",
chunkId,
chunkPath,
});
}

function handleSocketConnected() {
for (const chunkId of chunkUpdateCallbacks.keys()) {
subscribeToChunkUpdates(chunkId);
for (const chunkPath of chunkUpdateCallbacks.keys()) {
subscribeToChunkUpdates(chunkPath);
}
}

Expand All @@ -68,19 +67,22 @@ function handleSocketMessage(event: MessageEvent) {
triggerChunkUpdate(data);
}

export function onChunkUpdate(chunkId: ChunkId, callback: ChunkUpdateCallback) {
const callbacks = chunkUpdateCallbacks.get(chunkId);
export function onChunkUpdate(
chunkPath: string,
callback: ChunkUpdateCallback
) {
const callbacks = chunkUpdateCallbacks.get(chunkPath);
if (!callbacks) {
chunkUpdateCallbacks.set(chunkId, [callback]);
chunkUpdateCallbacks.set(chunkPath, [callback]);
} else {
callbacks.push(callback);
}

subscribeToChunkUpdates(chunkId);
subscribeToChunkUpdates(chunkPath);
}

function triggerChunkUpdate(update: ServerMessage) {
const callbacks = chunkUpdateCallbacks.get(update.chunkId);
const callbacks = chunkUpdateCallbacks.get(update.chunkPath);
if (!callbacks) {
return;
}
Expand All @@ -91,7 +93,7 @@ function triggerChunkUpdate(update: ServerMessage) {
}
} catch (err) {
console.error(
`An error occurred during the update of chunk \`${update.chunkId}\``,
`An error occurred during the update of chunk \`${update.chunkPath}\``,
err
);
location.reload();
Expand All @@ -102,14 +104,17 @@ function triggerChunkUpdate(update: ServerMessage) {
// They must be reloaded here instead.
function subscribeToInitialCssChunksUpdates() {
const initialCssChunkLinks: NodeListOf<HTMLLinkElement> =
document.head.querySelectorAll("link[data-turbopack-chunk-id]");
document.head.querySelectorAll("link");
initialCssChunkLinks.forEach((link) => {
const chunkId = link.dataset.turbopackChunkId!;
if (!link.href) return;
const url = new URL(link.href);
if (url.origin !== location.origin) return;
const chunkPath = url.pathname.slice(1);

onChunkUpdate(chunkId, (update) => {
onChunkUpdate(chunkPath, (update) => {
switch (update.type) {
case "restart": {
console.info(`Reloading CSS chunk \`${chunkId}\``);
console.info(`Reloading CSS chunk \`${chunkPath}\``);
link.replaceWith(link);
break;
}
Expand Down
28 changes: 15 additions & 13 deletions crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ use turbopack_core::{
chunk::{dev::DevChunkingContextVc, ChunkingContextVc},
context::AssetContextVc,
environment::{BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment},
resolve::{parse::RequestVc, pattern::Pattern},
};
use turbopack_ecmascript::chunk::EcmascriptChunkPlaceablesVc;
use turbopack_env::ProcessEnvAssetVc;

use crate::{
embed_js::next_js_fs,
env::filter_for_client,
next_client::runtime_entry::{RuntimeEntriesVc, RuntimeEntry},
react_refresh::assert_can_resolve_react_refresh,
Expand Down Expand Up @@ -106,6 +107,7 @@ pub fn get_client_chunking_context(
) -> ChunkingContextVc {
DevChunkingContextVc::new(
project_root,
server_root,
server_root.join("/_next/static/chunks"),
get_client_assets_path(server_root),
true,
Expand All @@ -122,6 +124,7 @@ pub fn get_client_assets_path(server_root: FileSystemPathVc) -> FileSystemPathVc
pub async fn get_client_runtime_entries(
project_root: FileSystemPathVc,
env: ProcessEnvVc,
bootstrap_dev_client: bool,
) -> Result<RuntimeEntriesVc> {
let resolve_options_context = get_client_resolve_options_context();
let enable_react_refresh =
Expand All @@ -133,21 +136,20 @@ pub async fn get_client_runtime_entries(
ProcessEnvAssetVc::new(project_root, filter_for_client(env)).into(),
)
.cell()];
if bootstrap_dev_client {
runtime_entries.push(
RuntimeEntry::Request(
RequestVc::parse(Value::new(Pattern::Constant(
"./dev/bootstrap.ts".to_string(),
))),
next_js_fs().root(),
)
.cell(),
);
}
if let Some(request) = enable_react_refresh {
runtime_entries.push(RuntimeEntry::Request(request, project_root.join("_")).cell())
};

Ok(RuntimeEntriesVc::cell(runtime_entries))
}

#[turbo_tasks::function]
pub fn get_resolved_client_runtime_entries(
project_root: FileSystemPathVc,
env: ProcessEnvVc,
browserslist_query: &str,
) -> EcmascriptChunkPlaceablesVc {
let context = get_client_asset_context(project_root, browserslist_query);
let entries = get_client_runtime_entries(project_root, env);

entries.resolve_entries(context)
}
6 changes: 0 additions & 6 deletions crates/next-core/src/nodejs/node_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,6 @@ impl ContentSource for NodeRenderContentSource {
}
Ok(ContentSourceResult::NotFound.cell())
}

#[turbo_tasks::function]
fn get_by_id(&self, _id: &str) -> ContentSourceResultVc {
// TODO allow to subscribe to the content
ContentSourceResult::NotFound.cell()
}
}

#[turbo_tasks::function]
Expand Down
3 changes: 2 additions & 1 deletion crates/next-core/src/server_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub async fn create_server_rendered_source(
.with_extended_import_map(next_client_import_map)
.with_extended_fallback_import_map(next_client_fallback_import_map);

let client_runtime_entries = get_client_runtime_entries(project_path, env);
let client_runtime_entries = get_client_runtime_entries(project_path, env, false);

let next_client_transition = NextClientTransition {
client_chunking_context,
Expand Down Expand Up @@ -222,6 +222,7 @@ fn create_server_rendered_source_for_file(

let chunking_context = DevChunkingContextVc::new(
context_path,
intermediate_output_path,
intermediate_output_path.join("chunks"),
get_client_assets_path(server_root),
false,
Expand Down
39 changes: 23 additions & 16 deletions crates/next-core/src/web_entry_source.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::future::IntoFuture;

use anyhow::{anyhow, Result};
use futures::{prelude::*, stream};
use turbo_tasks::TryJoinIterExt;
use turbo_tasks_env::ProcessEnvVc;
use turbo_tasks_fs::FileSystemPathVc;
use turbopack::ecmascript::EcmascriptModuleAssetVc;
Expand All @@ -15,7 +13,7 @@ use turbopack_dev_server::{
};

use crate::next_client::context::{
get_client_asset_context, get_client_chunking_context, get_resolved_client_runtime_entries,
get_client_asset_context, get_client_chunking_context, get_client_runtime_entries,
};

#[turbo_tasks::function]
Expand All @@ -29,22 +27,31 @@ pub async fn create_web_entry_source(
) -> Result<ContentSourceVc> {
let context = get_client_asset_context(project_root, browserslist_query);
let chunking_context = get_client_chunking_context(project_root, server_root);
let runtime_entries =
get_resolved_client_runtime_entries(project_root, env, browserslist_query);
let entries = get_client_runtime_entries(project_root, env, true);

let runtime_entries = entries.resolve_entries(context);

let origin = PlainResolveOriginVc::new(context, project_root.join("_")).as_resolve_origin();
let chunks: Vec<_> = stream::iter(entry_requests)
.then(|r| {
origin
.resolve_asset(r, origin.resolve_options())
let entries = entry_requests
.into_iter()
.map(|request| async move {
Ok(origin
.resolve_asset(request, origin.resolve_options())
.primary_assets()
.into_future()
.await?
.first()
.copied())
})
.map_ok(|assets| stream::iter(assets.clone()).map(Ok))
.try_flatten()
.and_then(|module| async move {
.try_join()
.await?;
let chunks: Vec<_> = entries
.into_iter()
.flatten()
.enumerate()
.map(|(i, module)| async move {
if let Some(ecmascript) = EcmascriptModuleAssetVc::resolve_from(module).await? {
Ok(ecmascript.as_evaluated_chunk(chunking_context, Some(runtime_entries)))
Ok(ecmascript
.as_evaluated_chunk(chunking_context, (i == 0).then_some(runtime_entries)))
} else if let Some(chunkable) = ChunkableAssetVc::resolve_from(module).await? {
// TODO this is missing runtime code, so it's probably broken and we should also
// add an ecmascript chunk with the runtime code
Expand All @@ -57,7 +64,7 @@ pub async fn create_web_entry_source(
))
}
})
.try_collect()
.try_join()
.await?;

let entry_asset = DevHtmlAsset::new(
Expand Down
5 changes: 0 additions & 5 deletions crates/next-dev/src/turbo_tasks_viz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,4 @@ impl ContentSource for TurboTasksSource {
)
.cell())
}

#[turbo_tasks::function]
fn get_by_id(&self, _id: &str) -> ContentSourceResultVc {
ContentSourceResult::NotFound.cell()
}
}
17 changes: 15 additions & 2 deletions crates/turbopack-core/src/chunk/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use crate::asset::AssetVc;
pub struct DevChunkingContext {
/// This path get striped off of path before creating a name out of it
context_path: FileSystemPathVc,
/// This path is used to compute the url to request chunks or assets from
output_root_path: FileSystemPathVc,
/// Chunks are placed at this path
chunk_root_path: FileSystemPathVc,
/// Static assets are placed at this path
Expand All @@ -36,12 +38,14 @@ pub struct DevChunkingContext {
impl DevChunkingContextVc {
pub fn new(
context_path: FileSystemPathVc,
output_root_path: FileSystemPathVc,
chunk_root_path: FileSystemPathVc,
asset_root_path: FileSystemPathVc,
enable_hot_module_replacement: bool,
) -> Self {
DevChunkingContext {
context_path,
output_root_path,
chunk_root_path,
asset_root_path,
layer: StringVc::empty(),
Expand All @@ -52,13 +56,15 @@ impl DevChunkingContextVc {

pub fn new_with_layer(
context_path: FileSystemPathVc,
output_root_path: FileSystemPathVc,
chunk_root_path: FileSystemPathVc,
asset_root_path: FileSystemPathVc,
enable_hot_module_replacement: bool,
layer: &str,
) -> Self {
DevChunkingContext {
context_path,
output_root_path,
chunk_root_path,
asset_root_path,
layer: StringVc::cell(layer.to_string()),
Expand All @@ -70,6 +76,11 @@ impl DevChunkingContextVc {

#[turbo_tasks::value_impl]
impl ChunkingContext for DevChunkingContext {
#[turbo_tasks::function]
fn output_root(&self) -> FileSystemPathVc {
self.output_root_path
}

#[turbo_tasks::function]
async fn chunk_path(
&self,
Expand Down Expand Up @@ -159,16 +170,18 @@ impl ChunkingContext for DevChunkingContext {
#[turbo_tasks::function]
async fn with_layer(self_vc: DevChunkingContextVc, layer: &str) -> Result<ChunkingContextVc> {
let DevChunkingContext {
output_root_path,
asset_root_path,
chunk_root_path,
context_path,
enable_hot_module_replacement,
layer: _,
} = *self_vc.await?;
Ok(DevChunkingContextVc::new_with_layer(
asset_root_path,
chunk_root_path,
context_path,
output_root_path,
chunk_root_path,
asset_root_path,
enable_hot_module_replacement,
layer,
)
Expand Down
10 changes: 2 additions & 8 deletions crates/turbopack-core/src/chunk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,11 @@ pub enum ModuleId {
#[turbo_tasks::value(transparent, shared)]
pub struct ModuleIds(Vec<ModuleIdVc>);

/// A chunk id, which can be a number or string
#[turbo_tasks::value(shared)]
#[derive(Debug, Clone, Hash)]
pub enum ChunkId {
Number(u32),
String(String),
}

/// A context for the chunking that influences the way chunks are created
#[turbo_tasks::value_trait]
pub trait ChunkingContext {
fn output_root(&self) -> FileSystemPathVc;

fn chunk_path(&self, path: FileSystemPathVc, extension: &str) -> FileSystemPathVc;

fn can_be_in_same_chunk(&self, asset_a: AssetVc, asset_b: AssetVc) -> BoolVc;
Expand Down
Loading

0 comments on commit 3ea2090

Please # to comment.