Skip to content

Commit

Permalink
embedded next.js package (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
ForsakenHarmony authored Oct 17, 2022
1 parent 89d0046 commit e857c37
Show file tree
Hide file tree
Showing 61 changed files with 751 additions and 334 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ insert_final_newline = false

[LICENSE]
insert_final_newline = false

[*.rs]
indent_size = 4
3 changes: 0 additions & 3 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,4 @@ crates/turbopack/tests/snapshot/**/output/
packages/node-module-trace/npm
packages/turbo-tracing-next-plugin/test/with-mongodb-mongoose
docs/public/schema.json
crates/next-core/src/**
crates/next-dev/tests/**
crates/turbopack-dev-server/src/**
crates/turbopack-ecmascript/src/**
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ globalThis.__dirname = "";

// Next uses __webpack_require__ extensively.
globalThis.__webpack_require__ = (name) => {
console.error(`__webpack_require__ is not implemented (when requiring ${name})`);
console.error(
`__webpack_require__ is not implemented (when requiring ${name})`
);
};

// initialize() needs `__webpack_public_path__` to be defined.
Expand Down
File renamed without changes.
File renamed without changes.
11 changes: 11 additions & 0 deletions crates/next-core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@vercel/turbopack-next",
"version": "0.0.0",
"description": "turbopack next runtime",
"license": "UNLICENSED",
"private": true,
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
32 changes: 32 additions & 0 deletions crates/next-core/src/embed_js.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use anyhow::Result;
use turbo_tasks_fs::{
attach::AttachedFileSystemVc, embed_directory, FileContentVc, FileSystemPathVc, FileSystemVc,
};

pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next";

#[turbo_tasks::function]
pub(crate) fn next_js_fs() -> FileSystemVc {
embed_directory!("next", "$CARGO_MANIFEST_DIR/js")
}

#[turbo_tasks::function]
pub(crate) fn next_js_file(path: &str) -> FileContentVc {
next_js_fs().root().join(path).read()
}

#[turbo_tasks::function]
pub(crate) async fn attached_next_js_package_path(
project_path: FileSystemPathVc,
) -> FileSystemPathVc {
project_path.join(&format!("[embedded_modules]/{}", VIRTUAL_PACKAGE_NAME))
}

#[turbo_tasks::function]
pub(crate) async fn wrap_with_next_js_fs(
project_path: FileSystemPathVc,
) -> Result<FileSystemPathVc> {
let attached_path = attached_next_js_package_path(project_path);
let fs = AttachedFileSystemVc::new(attached_path, next_js_fs());
Ok(fs.convert_path(project_path))
}
6 changes: 0 additions & 6 deletions crates/next-core/src/embed_next.rs

This file was deleted.

2 changes: 1 addition & 1 deletion crates/next-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(async_closure)]
#![feature(min_specialization)]

mod embed_next;
mod embed_js;
pub mod env;
pub mod next_client;
mod next_import_map;
Expand Down
10 changes: 6 additions & 4 deletions crates/next-core/src/next_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use turbopack_core::{
};

use self::runtime_entry::RuntimeEntriesVc;
use crate::embed_next_file;
use crate::embed_js::next_js_file;

/// Makes a transition into a next.js client context.
///
Expand All @@ -40,9 +40,11 @@ pub struct NextClientTransition {
impl Transition for NextClientTransition {
#[turbo_tasks::function]
fn process_source(&self, asset: AssetVc) -> AssetVc {
let next_hydrate = embed_next_file!("internal/next-hydrate.js").into();

VirtualAssetVc::new(asset.path().join("next-hydrate.js"), next_hydrate).into()
VirtualAssetVc::new(
asset.path().join("next-hydrate.js"),
next_js_file("entry/next-hydrate.js").into(),
)
.into()
}

#[turbo_tasks::function]
Expand Down
120 changes: 54 additions & 66 deletions crates/next-core/src/next_import_map.rs
Original file line number Diff line number Diff line change
@@ -1,120 +1,108 @@
use turbo_tasks_fs::FileSystemPathVc;
use turbopack_core::{
asset::AssetVc,
resolve::{
options::{ImportMap, ImportMapVc, ImportMapping, ImportMappingVc},
AliasPattern, ResolveResult,
},
virtual_asset::VirtualAssetVc,
};
use turbopack_core::resolve::options::{ImportMap, ImportMapVc, ImportMapping, ImportMappingVc};

use crate::embed_next_file;
use crate::embed_js::{attached_next_js_package_path, VIRTUAL_PACKAGE_NAME};

/// Computes the Next-specific client import map.
#[turbo_tasks::function]
pub fn get_next_client_import_map(pages_dir: FileSystemPathVc) -> ImportMapVc {
pub fn get_next_client_import_map(
project_path: FileSystemPathVc,
pages_dir: FileSystemPathVc,
) -> ImportMapVc {
let mut import_map = ImportMap::empty();
let package_root = attached_next_js_package_path(project_path);

insert_next_shared_aliases(&mut import_map, pages_dir);
insert_next_shared_aliases(&mut import_map, package_root);

insert_alias_to_alternatives(
&mut import_map,
"@vercel/turbopack-next/pages/_app",
request_to_import_mapping(pages_dir, "./_app"),
request_to_import_mapping(pages_dir, "next/app"),
format!("{VIRTUAL_PACKAGE_NAME}/pages/_app"),
vec![
request_to_import_mapping(pages_dir, "./_app"),
request_to_import_mapping(pages_dir, "next/app"),
],
);
insert_alias_to_alternatives(
&mut import_map,
"@vercel/turbopack-next/pages/_document",
request_to_import_mapping(pages_dir, "./_document"),
request_to_import_mapping(pages_dir, "next/document"),
format!("{VIRTUAL_PACKAGE_NAME}/pages/_document"),
vec![
request_to_import_mapping(pages_dir, "./_document"),
request_to_import_mapping(pages_dir, "next/document"),
],
);

import_map.cell()
}

/// Computes the Next-specific server-side import map.
#[turbo_tasks::function]
pub fn get_next_server_import_map(pages_dir: FileSystemPathVc) -> ImportMapVc {
pub fn get_next_server_import_map(
project_path: FileSystemPathVc,
pages_dir: FileSystemPathVc,
) -> ImportMapVc {
let mut import_map = ImportMap::empty();
let package_root = attached_next_js_package_path(project_path);

insert_next_shared_aliases(&mut import_map, pages_dir);
insert_next_shared_aliases(&mut import_map, package_root);

insert_alias_to_alternatives(
&mut import_map,
"@vercel/turbopack-next/pages/_app",
request_to_import_mapping(pages_dir, "./_app"),
external_request_to_import_mapping("next/app"),
format!("{VIRTUAL_PACKAGE_NAME}/pages/_app"),
vec![
request_to_import_mapping(pages_dir, "./_app"),
external_request_to_import_mapping("next/app"),
],
);
insert_alias_to_alternatives(
&mut import_map,
"@vercel/turbopack-next/pages/_document",
request_to_import_mapping(pages_dir, "./_document"),
external_request_to_import_mapping("next/document"),
format!("{VIRTUAL_PACKAGE_NAME}/pages/_document"),
vec![
request_to_import_mapping(pages_dir, "./_document"),
external_request_to_import_mapping("next/document"),
],
);

import_map.insert_alias(
AliasPattern::exact("next"),
ImportMapping::External(None).into(),
);
import_map.insert_alias(
AliasPattern::wildcard("next/", ""),
ImportMapping::External(None).into(),
);
import_map.insert_alias(
AliasPattern::exact("react"),
ImportMapping::External(None).into(),
);
import_map.insert_alias(
AliasPattern::wildcard("react/", ""),
ImportMapping::External(None).into(),
);
import_map.insert_exact_alias("next", ImportMapping::External(None).into());
import_map.insert_wildcard_alias("next/", ImportMapping::External(None).into());
import_map.insert_exact_alias("react", ImportMapping::External(None).into());
import_map.insert_wildcard_alias("react/", ImportMapping::External(None).into());

import_map.cell()
}

fn insert_next_shared_aliases(import_map: &mut ImportMap, pages_dir: FileSystemPathVc) {
import_map.insert_alias(
AliasPattern::exact("@vercel/turbopack-next/internal/shims"),
asset_to_import_mapping(get_internal_shims_asset(pages_dir)),
fn insert_next_shared_aliases(import_map: &mut ImportMap, package_root: FileSystemPathVc) {
insert_package_alias(
import_map,
&format!("{VIRTUAL_PACKAGE_NAME}/"),
package_root,
);
}

#[turbo_tasks::function]
fn get_internal_shims_asset(pages_dir: FileSystemPathVc) -> AssetVc {
VirtualAssetVc::new(
pages_dir.root().join("next_js/internal/shims.js"),
embed_next_file!("internal/shims.js").into(),
)
.into()
}

/// Inserts an alias to an alternative of import mappings into an import map.
fn insert_alias_to_alternatives(
import_map: &mut ImportMap,
alias: &str,
alt1: ImportMappingVc,
alt2: ImportMappingVc,
alias: impl ToString,
alternatives: Vec<ImportMappingVc>,
) {
import_map.insert_alias(
AliasPattern::Exact(alias.to_string()),
ImportMapping::Alternatives(vec![alt1, alt2]).into(),
import_map.insert_exact_alias(alias, ImportMapping::Alternatives(alternatives).into());
}

/// Inserts an alias to an import mapping into an import map.
fn insert_package_alias(import_map: &mut ImportMap, prefix: &str, package_root: FileSystemPathVc) {
import_map.insert_wildcard_alias(
prefix,
ImportMapping::PrimaryAlternative("./*".to_string(), Some(package_root)).cell(),
);
}

/// Creates a direct import mapping to the result of resolving a request
/// in a context.
fn request_to_import_mapping(context_path: FileSystemPathVc, request: &str) -> ImportMappingVc {
ImportMapping::PrimaryAlternative(request.to_string(), Some(context_path)).into()
ImportMapping::PrimaryAlternative(request.to_string(), Some(context_path)).cell()
}

/// Creates a direct import mapping to the result of resolving an external
/// request.
fn external_request_to_import_mapping(request: &str) -> ImportMappingVc {
ImportMapping::External(Some(request.to_string())).into()
}

/// Creates a direct import mapping to a single asset.
fn asset_to_import_mapping(asset: AssetVc) -> ImportMappingVc {
ImportMapping::Direct(ResolveResult::Single(asset, vec![]).into()).into()
}
4 changes: 2 additions & 2 deletions crates/next-core/src/nodejs/node_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl NodeRenderContentSource {
/// Checks if a path matches the regular expression
async fn is_matching_path(&self, path: &str) -> Result<bool> {
// TODO(alexkirsz) This should probably not happen here.
if path.starts_with("_") {
if path.starts_with('_') {
return Ok(false);
}
Ok(self.path_regex.await?.is_match(path))
Expand All @@ -88,7 +88,7 @@ impl NodeRenderContentSource {
/// with the named captures
async fn get_matches(&self, path: &str) -> Result<Option<IndexMap<String, String>>> {
// TODO(alexkirsz) This should probably not happen here.
if path.starts_with("_") {
if path.starts_with('_') {
return Ok(None);
}
Ok(self.path_regex.await?.get_matches(path))
Expand Down
10 changes: 6 additions & 4 deletions crates/next-core/src/server_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use turbopack_ecmascript::{
use turbopack_env::ProcessEnvAssetVc;

use crate::{
embed_next_file,
embed_js::{next_js_file, wrap_with_next_js_fs},
next_client::{
context::{
get_client_assets_path, get_client_chunking_context, get_client_environment,
Expand All @@ -52,6 +52,8 @@ pub async fn create_server_rendered_source(
env: ProcessEnvVc,
browserslist_query: &str,
) -> Result<ContentSourceVc> {
let project_path = wrap_with_next_js_fs(project_path);

let pages = project_path.join("pages");
let src_pages = project_path.join("src/pages");
let pages_dir = if *pages.get_type().await? == FileSystemEntryType::Directory {
Expand All @@ -68,8 +70,8 @@ pub async fn create_server_rendered_source(
get_client_module_options_context(project_path, client_environment);
let client_resolve_options_context = get_client_resolve_options_context();

let next_server_import_map = get_next_server_import_map(pages_dir);
let next_client_import_map = get_next_client_import_map(pages_dir);
let next_server_import_map = get_next_server_import_map(project_path, pages_dir);
let next_client_import_map = get_next_client_import_map(project_path, pages_dir);
let client_resolve_options_context =
client_resolve_options_context.with_extended_import_map(next_client_import_map);

Expand Down Expand Up @@ -342,7 +344,7 @@ impl NodeRenderer for SsrRenderer {
EcmascriptModuleAssetVc::new(
VirtualAssetVc::new(
self.entry_asset.path().join("server-renderer.js"),
embed_next_file!("internal/server-renderer.js").into(),
next_js_file("entry/server-renderer.js").into(),
)
.into(),
self.context,
Expand Down
5 changes: 2 additions & 3 deletions crates/turbo-tasks-fs/src/attach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,9 @@ impl ValueToString for AttachedFileSystem {
#[turbo_tasks::function]
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(format!(
"`{}` attached to `{}` at `{}`",
self.child_fs.to_string().await?,
"{}-with-{}",
self.root_fs.to_string().await?,
self.child_path
self.child_fs.to_string().await?
)))
}
}
4 changes: 2 additions & 2 deletions crates/turbo-tasks-fs/src/embed/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{embed::EmbeddedFileSystemVc, DiskFileSystemVc, FileSystemVc};

#[turbo_tasks::function]
pub async fn directory_from_relative_path(name: &str, path: String) -> Result<FileSystemVc> {
let disk_fs = DiskFileSystemVc::new(format!("embedded {}", name), path);
let disk_fs = DiskFileSystemVc::new(name.to_string(), path);
disk_fs.await?.start_watching()?;

Ok(disk_fs.into())
Expand All @@ -17,7 +17,7 @@ pub async fn directory_from_include_dir(
name: &str,
dir: TransientInstance<&'static include_dir::Dir<'static>>,
) -> Result<FileSystemVc> {
Ok(EmbeddedFileSystemVc::new(format!("embedded {}", name), dir).into())
Ok(EmbeddedFileSystemVc::new(name.to_string(), dir).into())
}

/// Returns an embedded filesystem for the given path.
Expand Down
2 changes: 1 addition & 1 deletion crates/turbopack-core/src/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ async fn resolved(
if let Some(resolved_map) = resolved_map {
let result = resolved_map.lookup(*path).await?;
if !matches!(&*result, ImportMapResult::NoEntry) {
return Ok(resolve_import_map_result(&result, path.parent(), options).await?);
return resolve_import_map_result(&result, path.parent(), options).await;
}
}
Ok(ResolveResult::Single(
Expand Down
Loading

0 comments on commit e857c37

Please sign in to comment.