Skip to content

Commit

Permalink
feat(turbopack): add support for polling file watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
ForsakenHarmony committed Sep 6, 2024
1 parent 87f4fc3 commit ea15075
Show file tree
Hide file tree
Showing 22 changed files with 147 additions and 50 deletions.
16 changes: 11 additions & 5 deletions crates/napi/src/app_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{collections::HashMap, path::MAIN_SEPARATOR};

use anyhow::{anyhow, Result};
use indexmap::IndexMap;
use next_api::project::WatchOptions;
use next_core::app_structure::{
find_app_dir, get_entrypoints as get_entrypoints_impl, Components, Entrypoint, Entrypoints,
LoaderTree, MetadataItem, MetadataWithAltItem,
Expand All @@ -14,10 +15,15 @@ use turbo_tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath};
use turbopack_core::PROJECT_FILESYSTEM_NAME;

#[turbo_tasks::function]
async fn project_fs(project_dir: RcStr, watching: bool) -> Result<Vc<Box<dyn FileSystem>>> {
async fn project_fs(
project_dir: RcStr,
watch_options: WatchOptions,
) -> Result<Vc<Box<dyn FileSystem>>> {
let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.into(), project_dir, vec![]);
if watching {
disk_fs.await?.start_watching_with_invalidation_reason()?;
if watch_options.enable {
disk_fs
.await?
.start_watching_with_invalidation_reason(watch_options.poll_interval)?;
}
Ok(Vc::upcast(disk_fs))
}
Expand Down Expand Up @@ -329,10 +335,10 @@ async fn get_value(
root_dir: RcStr,
project_dir: RcStr,
page_extensions: Vec<RcStr>,
watching: bool,
watch_options: WatchOptions,
) -> Result<Vc<OptionEntrypointsForJs>> {
let page_extensions = Vc::cell(page_extensions);
let fs = project_fs(root_dir.clone(), watching);
let fs = project_fs(root_dir.clone(), watch_options);
let project_relative = project_dir.strip_prefix(&*root_dir).unwrap();
let project_relative = project_relative
.strip_prefix(MAIN_SEPARATOR)
Expand Down
35 changes: 28 additions & 7 deletions crates/napi/src/next_api/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use next_api::{
entrypoints::Entrypoints,
project::{
DefineEnv, DraftModeOptions, Instrumentation, Middleware, PartialProjectOptions, Project,
ProjectContainer, ProjectOptions,
ProjectContainer, ProjectOptions, WatchOptions,
},
route::{Endpoint, Route},
};
Expand Down Expand Up @@ -78,6 +78,16 @@ impl From<NapiDraftModeOptions> for DraftModeOptions {
}
}

#[napi(object)]
pub struct NapiWatchOptions {
/// Whether to watch the filesystem for file changes.
pub enable: bool,

/// Enable polling at a certain interval if the native file watching doesn't work (e.g.
/// docker).
pub poll_interval_ms: Option<f64>,
}

#[napi(object)]
pub struct NapiProjectOptions {
/// A root path from which all files must be nested under. Trying to access
Expand All @@ -91,8 +101,8 @@ pub struct NapiProjectOptions {
/// deserializing next.config, so passing it as separate option.
pub dist_dir: Option<String>,

/// Whether to watch he filesystem for file changes.
pub watch: bool,
/// Filesystem watcher options.
pub watch: NapiWatchOptions,

/// The contents of next.config.js, serialized to JSON.
pub next_config: String,
Expand Down Expand Up @@ -134,8 +144,8 @@ pub struct NapiPartialProjectOptions {
/// deserializing next.config, so passing it as separate option.
pub dist_dir: Option<Option<String>>,

/// Whether to watch he filesystem for file changes.
pub watch: Option<bool>,
/// Filesystem watcher options.
pub watch: Option<NapiWatchOptions>,

/// The contents of next.config.js, serialized to JSON.
pub next_config: Option<String>,
Expand Down Expand Up @@ -177,12 +187,23 @@ pub struct NapiTurboEngineOptions {
pub memory_limit: Option<f64>,
}

impl From<NapiWatchOptions> for WatchOptions {
fn from(val: NapiWatchOptions) -> Self {
WatchOptions {
enable: val.enable,
poll_interval: val
.poll_interval_ms
.map(|interval| Duration::from_secs_f64(interval / 1000.0)),
}
}
}

impl From<NapiProjectOptions> for ProjectOptions {
fn from(val: NapiProjectOptions) -> Self {
ProjectOptions {
root_path: val.root_path.into(),
project_path: val.project_path.into(),
watch: val.watch,
watch: val.watch.into(),
next_config: val.next_config.into(),
js_config: val.js_config.into(),
env: val
Expand All @@ -204,7 +225,7 @@ impl From<NapiPartialProjectOptions> for PartialProjectOptions {
PartialProjectOptions {
root_path: val.root_path.map(From::from),
project_path: val.project_path.map(From::from),
watch: val.watch,
watch: val.watch.map(From::from),
next_config: val.next_config.map(From::from),
js_config: val.js_config.map(From::from),
env: val.env.map(|env| {
Expand Down
33 changes: 24 additions & 9 deletions crates/next-api/src/project.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::MAIN_SEPARATOR;
use std::{path::MAIN_SEPARATOR, time::Duration};

use anyhow::{bail, Context, Result};
use indexmap::{indexmap, map::Entry, IndexMap};
Expand Down Expand Up @@ -74,6 +74,19 @@ pub struct DraftModeOptions {
pub preview_mode_signing_key: RcStr,
}

#[derive(
Debug, Default, Serialize, Deserialize, Copy, Clone, TaskInput, PartialEq, Eq, Hash, TraceRawVcs,
)]
#[serde(rename_all = "camelCase")]
pub struct WatchOptions {
/// Whether to watch the filesystem for file changes.
pub enable: bool,

/// Enable polling at a certain interval if the native file watching doesn't work (e.g.
/// docker).
pub poll_interval: Option<Duration>,
}

#[derive(Debug, Serialize, Deserialize, Clone, TaskInput, PartialEq, Eq, Hash, TraceRawVcs)]
#[serde(rename_all = "camelCase")]
pub struct ProjectOptions {
Expand All @@ -97,8 +110,8 @@ pub struct ProjectOptions {
/// time.
pub define_env: DefineEnv,

/// Whether to watch the filesystem for file changes.
pub watch: bool,
/// Filesystem watcher options.
pub watch: WatchOptions,

/// The mode in which Next.js is running.
pub dev: bool,
Expand Down Expand Up @@ -136,8 +149,8 @@ pub struct PartialProjectOptions {
/// time.
pub define_env: Option<DefineEnv>,

/// Whether to watch the filesystem for file changes.
pub watch: Option<bool>,
/// Filesystem watcher options.
pub watch: Option<WatchOptions>,

/// The mode in which Next.js is running.
pub dev: Option<bool>,
Expand Down Expand Up @@ -402,8 +415,8 @@ pub struct Project {
/// A path inside the root_path which contains the app/pages directories.
pub project_path: RcStr,

/// Whether to watch the filesystem for file changes.
watch: bool,
/// Filesystem watcher options.
watch: WatchOptions,

/// Next config.
next_config: Vc<NextConfig>,
Expand Down Expand Up @@ -516,8 +529,10 @@ impl Project {
this.root_path.clone(),
vec![],
);
if this.watch {
disk_fs.await?.start_watching_with_invalidation_reason()?;
if this.watch.enable {
disk_fs
.await?
.start_watching_with_invalidation_reason(this.watch.poll_interval)?;
}
Ok(disk_fs)
}
Expand Down
4 changes: 2 additions & 2 deletions crates/next-build-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ pub async fn main_inner(

if matches!(strat, Strategy::Development { .. }) {
options.dev = true;
options.watch = true;
options.watch.enable = true;
} else {
options.dev = false;
options.watch = false;
options.watch.enable = false;
}

let project = tt
Expand Down
2 changes: 1 addition & 1 deletion crates/next-build-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fn main() {
},
project_path: canonical_path.to_string_lossy().into(),
root_path: "/".into(),
watch: false,
watch: Default::default(),
};

let json = serde_json::to_string_pretty(&options).unwrap();
Expand Down
4 changes: 3 additions & 1 deletion packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,9 @@ export default async function build(
rootPath: config.outputFileTracingRoot || dir,
nextConfig: config,
jsConfig: await getTurbopackJsConfig(dir, config),
watch: false,
watch: {
enable: false,
},
dev,
env: process.env as Record<string, string>,
defineEnv: createDefineEnv({
Expand Down
17 changes: 13 additions & 4 deletions packages/next/src/build/swc/generated-native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ export interface NapiDraftModeOptions {
previewModeEncryptionKey: string
previewModeSigningKey: string
}
export interface NapiWatchOptions {
/** Whether to watch the filesystem for file changes. */
enable: boolean
/**
* Enable polling at a certain interval if the native file watching doesn't work (e.g.
* docker).
*/
pollIntervalMs?: number
}
export interface NapiProjectOptions {
/**
* A root path from which all files must be nested under. Trying to access
Expand All @@ -92,8 +101,8 @@ export interface NapiProjectOptions {
* deserializing next.config, so passing it as separate option.
*/
distDir?: string
/** Whether to watch he filesystem for file changes. */
watch: boolean
/** Filesystem watcher options. */
watch: NapiWatchOptions
/** The contents of next.config.js, serialized to JSON. */
nextConfig: string
/** The contents of ts/config read by load-jsconfig, serialized to JSON. */
Expand Down Expand Up @@ -128,8 +137,8 @@ export interface NapiPartialProjectOptions {
* deserializing next.config, so passing it as separate option.
*/
distDir?: string | undefined | null
/** Whether to watch he filesystem for file changes. */
watch?: boolean
/** Filesystem watcher options. */
watch?: NapiWatchOptions
/** The contents of next.config.js, serialized to JSON. */
nextConfig?: string
/** The contents of ts/config read by load-jsconfig, serialized to JSON. */
Expand Down
5 changes: 4 additions & 1 deletion packages/next/src/build/swc/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,10 @@ export interface ProjectOptions {
/**
* Whether to watch the filesystem for file changes.
*/
watch: boolean
watch: {
enable: boolean
pollIntervalMs?: number
}

/**
* The mode in which Next.js is running.
Expand Down
4 changes: 4 additions & 0 deletions packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,10 @@ export interface NextConfig extends Record<string, any> {
* were not detected on a per-page basis.
*/
outputFileTracingIncludes?: Record<string, string[]>

watchOptions?: {
pollIntervalMs?: number
}
}

export const defaultConfig: NextConfig = {
Expand Down
5 changes: 4 additions & 1 deletion packages/next/src/server/dev/hot-reloader-turbopack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ export async function createHotReloaderTurbopack(
rootPath: opts.nextConfig.outputFileTracingRoot || dir,
nextConfig: opts.nextConfig,
jsConfig: await getTurbopackJsConfig(dir, nextConfig),
watch: true,
watch: {
enable: true,
pollIntervalMs: nextConfig.watchOptions?.pollIntervalMs,
},
dev: true,
env: process.env as Record<string, string>,
defineEnv: createDefineEnv({
Expand Down
4 changes: 3 additions & 1 deletion test/development/basic/next-rs-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ describe('next.rs api', () => {
rootPath: process.env.NEXT_SKIP_ISOLATE
? path.resolve(__dirname, '../../..')
: next.testDir,
watch: true,
watch: {
enable: true,
},
dev: true,
defineEnv: createDefineEnv({
isTurbopack: true,
Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/node-file-trace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl Args {
async fn create_fs(name: &str, root: &str, watch: bool) -> Result<Vc<Box<dyn FileSystem>>> {
let fs = DiskFileSystem::new(name.into(), root.into(), vec![]);
if watch {
fs.await?.start_watching()?;
fs.await?.start_watching(None)?;
} else {
fs.await?.invalidate_with_reason();
}
Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-fs/examples/hash_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async fn main() -> Result<()> {
Box::pin(async {
let root = current_dir().unwrap().to_str().unwrap().into();
let disk_fs = DiskFileSystem::new("project".into(), root, vec![]);
disk_fs.await?.start_watching()?;
disk_fs.await?.start_watching(None)?;

// Smart Pointer cast
let fs: Vc<Box<dyn FileSystem>> = Vc::upcast(disk_fs);
Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-fs/examples/hash_glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async fn main() -> Result<()> {
Box::pin(async {
let root = current_dir().unwrap().to_str().unwrap().into();
let disk_fs = DiskFileSystem::new("project".into(), root, vec![]);
disk_fs.await?.start_watching()?;
disk_fs.await?.start_watching(None)?;

// Smart Pointer cast
let fs: Vc<Box<dyn FileSystem>> = Vc::upcast(disk_fs);
Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-fs/src/embed/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub async fn directory_from_relative_path(
path: RcStr,
) -> Result<Vc<Box<dyn FileSystem>>> {
let disk_fs = DiskFileSystem::new(name, path, vec![]);
disk_fs.await?.start_watching()?;
disk_fs.await?.start_watching(None)?;

Ok(Vc::upcast(disk_fs))
}
Expand Down
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-fs/src/embed/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub async fn content_from_relative_path(
root_path.to_string_lossy().into(),
vec![],
);
disk_fs.await?.start_watching()?;
disk_fs.await?.start_watching(None)?;

let fs_path = disk_fs.root().join(path.into());
Ok(fs_path.read())
Expand Down
Loading

0 comments on commit ea15075

Please sign in to comment.