Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update hmr-poc #3

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
929dfc1
feat: add hmr_rebuild api (#2137)
underfin Sep 3, 2024
e4ef98f
feat: store pervious build module info and using it at next hmr modul…
underfin Sep 4, 2024
dd0ff89
chore: add react hmr example (#2147)
underfin Sep 4, 2024
88d239a
feat: enable app format at js side (#2148)
underfin Sep 4, 2024
21e2270
chore: disable IsolatingModuleFinalizer (#2149)
underfin Sep 4, 2024
20fd0ae
feat: add react-refresh and make transform to commonjs work (#2150)
underfin Sep 5, 2024
9ae4e02
feat: render app chunk and replace require module id to stable id (#2…
underfin Sep 5, 2024
6332c0e
fix: avoid wrapper runtime module at app format (#2157)
underfin Sep 5, 2024
0b129c9
fix: using simple react refresh and make serve work (#2158)
underfin Sep 5, 2024
4c8bc78
feat: implement rolldown_runtime and fix react-refresh make react-exa…
underfin Sep 6, 2024
b283d5c
feat: implement hmr runtime (#2172)
underfin Sep 6, 2024
8b407cf
feat: generate hmr chunk (#2173)
underfin Sep 6, 2024
6fada77
fix: diff modules ast should be mutate by IsolatingModuleFinalizer (#…
underfin Sep 9, 2024
681a710
feat: add watcher (#2185)
underfin Sep 9, 2024
b62ae08
feat: add server and ws (#2186)
underfin Sep 9, 2024
44aca17
chore(hmr): rebase main branch
underfin Sep 13, 2024
3b3eb46
fix(hmr): reuse symbols info for hmr (#2231)
underfin Sep 15, 2024
99333f3
feat(hmr): remove babel @babel/plugin-transform-modules-commonjs (#2232)
underfin Sep 15, 2024
135b5dc
chore(hmr): add rebase missing changes (#2233)
underfin Sep 15, 2024
37f0b0f
fix(hmr): should replace module ast correctly at hmr (#2234)
underfin Sep 15, 2024
06c747c
feat: using oxc react refresh (#2235)
underfin Sep 20, 2024
52212e4
feat(hmr): inject react refresh entry at builtin react plugin (#2259)
underfin Sep 20, 2024
6a28aff
chore: using plugin emit html (#2260)
underfin Sep 20, 2024
52cc3a1
feat(app): transform export named declaration (#2264)
underfin Sep 23, 2024
26ad849
fix(hmr): fix some issue for benchmark (#2265)
underfin Sep 23, 2024
47e71e6
feat(hmr): using virtual file to avoid write file (#2266)
underfin Sep 23, 2024
14dbed0
feat(hmr): using watchpack (#2267)
underfin Sep 23, 2024
6d2b895
feat: add vue hmr example (#2291)
underfin Sep 25, 2024
ec614eb
fix: make sure rolldown inject runtime at vue (#2292)
underfin Sep 25, 2024
c17260b
fix: escape module id at define to same as oxc codegen (#2293)
underfin Sep 25, 2024
e22e079
feat: support hot accept callback (#2294)
underfin Sep 27, 2024
a292401
chore: rebase main branch
underfin Nov 5, 2024
d0e22cd
Merge branch 'main' into hmr-poc-merge
hi-ogawa Nov 28, 2024
04c7c6f
fix: update
hi-ogawa Nov 28, 2024
2916221
fix: update js
hi-ogawa Nov 28, 2024
7919f5f
chore: lint
hi-ogawa Nov 28, 2024
3f1ff73
fix: fix js
hi-ogawa Nov 28, 2024
b1b4f5b
refactor: move runtime-app.js
hi-ogawa Nov 28, 2024
1d8ed9e
test: run test-node
hi-ogawa Nov 28, 2024
d188fd1
chore: sort package.json
hi-ogawa Nov 28, 2024
d89a0eb
chore: cleanup
hi-ogawa Nov 28, 2024
5f230d1
chore: cleanup
hi-ogawa Nov 28, 2024
fe30379
test: cleanup
hi-ogawa Nov 28, 2024
8a6deff
chore: cleanup
hi-ogawa Nov 28, 2024
27d203a
fix: fix patch export var
hi-ogawa Nov 28, 2024
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
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ rolldown_plugin_json = { version = "0.1.0", path = "./crates/
rolldown_plugin_load_fallback = { version = "0.1.0", path = "./crates/rolldown_plugin_load_fallback" }
rolldown_plugin_manifest = { version = "0.1.0", path = "./crates/rolldown_plugin_manifest" }
rolldown_plugin_module_preload_polyfill = { version = "0.1.0", path = "./crates/rolldown_plugin_module_preload_polyfill" }
rolldown_plugin_react = { version = "0.1.0", path = "./crates/rolldown_plugin_react" }
rolldown_plugin_replace = { version = "0.1.0", path = "./crates/rolldown_plugin_replace" }
rolldown_plugin_transform = { version = "0.1.0", path = "./crates/rolldown_plugin_transform" }
rolldown_plugin_vite_resolve = { version = "0.1.0", path = "./crates/rolldown_plugin_vite_resolve" }
Expand Down
94 changes: 74 additions & 20 deletions crates/rolldown/src/bundler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,30 @@ use super::stages::{
};
use crate::{
bundler_builder::BundlerBuilder,
stages::{generate_stage::GenerateStage, scan_stage::ScanStage},
module_loader::hmr_module_loader::HmrModuleLoader,
stages::{
generate_stage::{render_hmr_chunk::render_hmr_chunk, GenerateStage},
scan_stage::ScanStage,
},
type_alias::IndexEcmaAst,
types::bundle_output::BundleOutput,
watcher::watcher::{wait_for_change, Watcher},
BundlerOptions, SharedOptions, SharedResolver,
};
use anyhow::Result;
use arcstr::ArcStr;

use rolldown_common::{
ModuleIdx, ModuleTable, NormalizedBundlerOptions, SharedFileEmitter, SymbolRefDb,
};

use rolldown_common::{NormalizedBundlerOptions, SharedFileEmitter};
use rolldown_error::{BuildDiagnostic, BuildResult};
use rolldown_fs::{FileSystem, OsFileSystem};
use rolldown_plugin::{
HookBuildEndArgs, HookRenderErrorArgs, SharedPluginDriver, __inner::SharedPluginable,
};
use rolldown_std_utils::OptionExt;
use rustc_hash::FxHashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing_chrome::FlushGuard;
Expand All @@ -31,6 +41,10 @@ pub struct Bundler {
pub(crate) plugin_driver: SharedPluginDriver,
pub(crate) warnings: Vec<BuildDiagnostic>,
pub(crate) _log_guard: Option<FlushGuard>,
pub(crate) previous_module_table: ModuleTable,
pub(crate) previous_module_id_to_modules: FxHashMap<ArcStr, ModuleIdx>,
pub(crate) pervious_index_ecma_ast: IndexEcmaAst,
pub(crate) pervious_symbols: SymbolRefDb,
}

impl Bundler {
Expand All @@ -46,26 +60,9 @@ impl Bundler {
impl Bundler {
#[tracing::instrument(level = "debug", skip_all)]
pub async fn write(&mut self) -> BuildResult<BundleOutput> {
let dir = self.options.cwd.join(&self.options.dir);

let mut output = self.bundle_up(/* is_write */ true).await?;

self.fs.create_dir_all(&dir).map_err(|err| {
anyhow::anyhow!("Could not create directory for output chunks: {:?}", dir).context(err)
})?;

for chunk in &output.assets {
let dest = dir.join(chunk.filename());
if let Some(p) = dest.parent() {
if !self.fs.exists(p) {
self.fs.create_dir_all(p).unwrap();
}
};
self
.fs
.write(&dest, chunk.content_as_bytes())
.map_err(|err| anyhow::anyhow!("Failed to write file in {:?}", dest).context(err))?;
}
self.write_file_to_disk(&output)?;

self.plugin_driver.write_bundle(&mut output.assets, &self.options).await?;

Expand Down Expand Up @@ -129,6 +126,57 @@ impl Bundler {
Ok(scan_stage_output)
}

#[allow(clippy::unused_async)]
pub async fn hmr_rebuild(&mut self, changed_files: Vec<String>) -> BuildResult<BundleOutput> {
let hmr_module_loader = HmrModuleLoader::new(
Arc::clone(&self.options),
Arc::clone(&self.plugin_driver),
self.fs,
Arc::clone(&self.resolver),
std::mem::take(&mut self.previous_module_id_to_modules),
std::mem::take(&mut self.previous_module_table),
std::mem::take(&mut self.pervious_index_ecma_ast),
std::mem::take(&mut self.pervious_symbols),
)?;

let mut hmr_module_loader_output = hmr_module_loader.fetch_changed_files(changed_files).await?;

let output = render_hmr_chunk(&self.options, &mut hmr_module_loader_output);

self.write_file_to_disk(&output)?;

// store last build modules info
self.previous_module_table = hmr_module_loader_output.module_table;
self.previous_module_id_to_modules = hmr_module_loader_output.module_id_to_modules;
self.pervious_index_ecma_ast = hmr_module_loader_output.index_ecma_ast;
self.pervious_symbols = hmr_module_loader_output.symbol_ref_db;

Ok(output)
}

fn write_file_to_disk(&self, output: &BundleOutput) -> Result<()> {
let dir = self.options.cwd.join(&self.options.dir);

self.fs.create_dir_all(&dir).map_err(|err| {
anyhow::anyhow!("Could not create directory for output chunks: {:?}", dir).context(err)
})?;

for chunk in &output.assets {
let dest = dir.join(chunk.filename());
if let Some(p) = dest.parent() {
if !self.fs.exists(p) {
self.fs.create_dir_all(p).unwrap();
}
};
self
.fs
.write(&dest, chunk.content_as_bytes())
.map_err(|err| anyhow::anyhow!("Failed to write file in {:?}", dest).context(err))?;
}

Ok(())
}

async fn try_build(&mut self) -> BuildResult<LinkStageOutput> {
let build_info = self.scan().await?;
Ok(LinkStage::new(build_info, &self.options).link())
Expand Down Expand Up @@ -170,6 +218,12 @@ impl Bundler {

output.watch_files = self.plugin_driver.watch_files.iter().map(|f| f.clone()).collect();

// store last build modules info
self.previous_module_table = link_stage_output.module_table;
self.previous_module_id_to_modules = link_stage_output.module_id_to_modules;
self.pervious_index_ecma_ast = link_stage_output.ast_table;
self.pervious_symbols = link_stage_output.symbol_db;

Ok(output)
}

Expand Down
8 changes: 7 additions & 1 deletion crates/rolldown/src/bundler_builder.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::sync::Arc;

use rolldown_common::FileEmitter;
use oxc_index::IndexVec;
use rolldown_common::{FileEmitter, ModuleTable, SymbolRefDb};
use rolldown_fs::OsFileSystem;
use rolldown_plugin::{PluginDriver, __inner::SharedPluginable};
use rolldown_resolver::Resolver;
use rustc_hash::FxHashMap;

use crate::{
utils::{
Expand Down Expand Up @@ -44,6 +46,10 @@ impl BundlerBuilder {
fs: OsFileSystem,
warnings,
_log_guard: maybe_guard,
previous_module_table: ModuleTable::default(),
previous_module_id_to_modules: FxHashMap::default(),
pervious_index_ecma_ast: IndexVec::default(),
pervious_symbols: SymbolRefDb::default(),
}
}

Expand Down
27 changes: 24 additions & 3 deletions crates/rolldown/src/ecmascript/format/app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use rolldown_common::{ChunkKind, Module};
use rolldown_sourcemap::SourceJoiner;

use crate::{ecmascript::ecma_generator::RenderedModuleSources, types::generator::GenerateContext};

pub fn render_app<'code>(
_ctx: &GenerateContext<'_>,
ctx: &GenerateContext<'_>,
hashbang: Option<&'code str>,
banner: Option<&'code str>,
intro: Option<&'code str>,
Expand All @@ -25,14 +26,34 @@ pub fn render_app<'code>(
}

// chunk content
module_sources.iter().for_each(|(_, _, module_render_output)| {
module_sources.iter().for_each(|(module_idx, _, module_render_output)| {
if let Some(emitted_sources) = module_render_output {
for source in emitted_sources.as_ref() {
let is_runtime = ctx.link_output.runtime.id() == *module_idx;
if !is_runtime {
source_joiner.append_source(format!(
"rolldown_runtime.define('{}',function(require, module, exports){{\n",
// Here need to care about virtual module `\0`, the oxc codegen will escape it, so here also escape it
ctx.link_output.module_table.modules[*module_idx].stable_id().escape_default()
));
}
for source in emitted_sources.iter() {
source_joiner.append_source(source);
}
if !is_runtime {
source_joiner.append_source("});".to_string());
}
}
});

if let ChunkKind::EntryPoint { module: entry_id, .. } = ctx.chunk.kind {
if let Module::Normal(entry_module) = &ctx.link_output.module_table.modules[entry_id] {
source_joiner.append_source(format!(
"rolldown_runtime.require('{}');",
entry_module.stable_id.escape_default()
));
}
}

if let Some(outro) = outro {
source_joiner.append_source(outro);
}
Expand Down
11 changes: 11 additions & 0 deletions crates/rolldown/src/module_finalizers/isolating/impl_visit_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ impl<'me, 'ast> VisitMut<'ast> for IsolatingModuleFinalizer<'me, 'ast> {

walk_mut::walk_call_expression(self, expr);
}

fn visit_static_member_expression(&mut self, expr: &mut ast::StaticMemberExpression<'ast>) {
// replace `import.meta.hot` -> `module.hot`
if let Expression::MetaProperty(meta) = &expr.object {
if expr.property.name == "hot" && meta.meta.name == "import" && meta.property.name == "meta" {
expr.object = self.snippet.id_ref_expr("module", SPAN);
}
}

walk_mut::walk_static_member_expression(self, expr);
}
}

impl<'me, 'ast> IsolatingModuleFinalizer<'me, 'ast> {
Expand Down
2 changes: 2 additions & 0 deletions crates/rolldown/src/module_finalizers/isolating/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ use rustc_hash::FxHashSet;

mod impl_visit_mut;

#[allow(dead_code)]
pub struct IsolatingModuleFinalizerContext<'me> {
pub module: &'me NormalModule,
pub modules: &'me IndexModules,
pub symbol_db: &'me SymbolRefDb,
}

#[allow(dead_code)]
pub struct IsolatingModuleFinalizer<'me, 'ast> {
pub ctx: &'me IsolatingModuleFinalizerContext<'me>,
pub scope: &'me AstScopes,
Expand Down
Loading
Loading