mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
a6ca4d0d61
This changes npm specifiers to be handled by deno_graph and resolved to an npm package name and version when the specifier is encountered. It also slightly changes how npm specifier resolution occurs—previously it would collect all the npm specifiers and resolve them all at once, but now it resolves them on the fly as they are encountered in the module graph. https://github.com/denoland/deno_graph/pull/232 --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
173 lines
5.1 KiB
Rust
173 lines
5.1 KiB
Rust
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use deno_core::error::AnyError;
|
|
use deno_core::futures::FutureExt;
|
|
use deno_core::resolve_url_or_path;
|
|
use deno_graph::Module;
|
|
use deno_runtime::colors;
|
|
|
|
use crate::args::BundleFlags;
|
|
use crate::args::CliOptions;
|
|
use crate::args::Flags;
|
|
use crate::args::TsConfigType;
|
|
use crate::args::TypeCheckMode;
|
|
use crate::graph_util::create_graph_and_maybe_check;
|
|
use crate::graph_util::error_for_any_npm_specifier;
|
|
use crate::proc_state::ProcState;
|
|
use crate::util;
|
|
use crate::util::display;
|
|
use crate::util::file_watcher::ResolutionResult;
|
|
|
|
pub async fn bundle(
|
|
flags: Flags,
|
|
bundle_flags: BundleFlags,
|
|
) -> Result<(), AnyError> {
|
|
let cli_options = Arc::new(CliOptions::from_flags(flags)?);
|
|
|
|
log::info!(
|
|
"{} \"deno bundle\" is deprecated and will be removed in the future.",
|
|
colors::yellow("Warning"),
|
|
);
|
|
log::info!(
|
|
"Use alternative bundlers like \"deno_emit\", \"esbuild\" or \"rollup\" instead."
|
|
);
|
|
|
|
let resolver = |_| {
|
|
let cli_options = cli_options.clone();
|
|
let source_file1 = &bundle_flags.source_file;
|
|
let source_file2 = &bundle_flags.source_file;
|
|
async move {
|
|
let module_specifier = resolve_url_or_path(source_file1)?;
|
|
|
|
log::debug!(">>>>> bundle START");
|
|
let ps = ProcState::from_options(cli_options).await?;
|
|
let graph = create_graph_and_maybe_check(module_specifier, &ps).await?;
|
|
|
|
let mut paths_to_watch: Vec<PathBuf> = graph
|
|
.specifiers()
|
|
.filter_map(|(_, r)| {
|
|
r.ok().and_then(|module| match module {
|
|
Module::Esm(m) => m.specifier.to_file_path().ok(),
|
|
Module::Json(m) => m.specifier.to_file_path().ok(),
|
|
// nothing to watch
|
|
Module::Node(_) | Module::Npm(_) | Module::External(_) => None,
|
|
})
|
|
})
|
|
.collect();
|
|
|
|
if let Ok(Some(import_map_path)) = ps
|
|
.options
|
|
.resolve_import_map_specifier()
|
|
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
|
{
|
|
paths_to_watch.push(import_map_path);
|
|
}
|
|
|
|
Ok((paths_to_watch, graph, ps))
|
|
}
|
|
.map(move |result| match result {
|
|
Ok((paths_to_watch, graph, ps)) => ResolutionResult::Restart {
|
|
paths_to_watch,
|
|
result: Ok((ps, graph)),
|
|
},
|
|
Err(e) => ResolutionResult::Restart {
|
|
paths_to_watch: vec![PathBuf::from(source_file2)],
|
|
result: Err(e),
|
|
},
|
|
})
|
|
};
|
|
|
|
let operation = |(ps, graph): (ProcState, Arc<deno_graph::ModuleGraph>)| {
|
|
let out_file = &bundle_flags.out_file;
|
|
async move {
|
|
// at the moment, we don't support npm specifiers in deno bundle, so show an error
|
|
error_for_any_npm_specifier(&graph)?;
|
|
|
|
let bundle_output = bundle_module_graph(graph.as_ref(), &ps)?;
|
|
log::debug!(">>>>> bundle END");
|
|
|
|
if let Some(out_file) = out_file {
|
|
let output_bytes = bundle_output.code.as_bytes();
|
|
let output_len = output_bytes.len();
|
|
util::fs::write_file(out_file, output_bytes, 0o644)?;
|
|
log::info!(
|
|
"{} {:?} ({})",
|
|
colors::green("Emit"),
|
|
out_file,
|
|
colors::gray(display::human_size(output_len as f64))
|
|
);
|
|
if let Some(bundle_map) = bundle_output.maybe_map {
|
|
let map_bytes = bundle_map.as_bytes();
|
|
let map_len = map_bytes.len();
|
|
let ext = if let Some(curr_ext) = out_file.extension() {
|
|
format!("{}.map", curr_ext.to_string_lossy())
|
|
} else {
|
|
"map".to_string()
|
|
};
|
|
let map_out_file = out_file.with_extension(ext);
|
|
util::fs::write_file(&map_out_file, map_bytes, 0o644)?;
|
|
log::info!(
|
|
"{} {:?} ({})",
|
|
colors::green("Emit"),
|
|
map_out_file,
|
|
colors::gray(display::human_size(map_len as f64))
|
|
);
|
|
}
|
|
} else {
|
|
println!("{}", bundle_output.code);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
};
|
|
|
|
if cli_options.watch_paths().is_some() {
|
|
util::file_watcher::watch_func(
|
|
resolver,
|
|
operation,
|
|
util::file_watcher::PrintConfig {
|
|
job_name: "Bundle".to_string(),
|
|
clear_screen: !cli_options.no_clear_screen(),
|
|
},
|
|
)
|
|
.await?;
|
|
} else {
|
|
let module_graph =
|
|
if let ResolutionResult::Restart { result, .. } = resolver(None).await {
|
|
result?
|
|
} else {
|
|
unreachable!();
|
|
};
|
|
operation(module_graph).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn bundle_module_graph(
|
|
graph: &deno_graph::ModuleGraph,
|
|
ps: &ProcState,
|
|
) -> Result<deno_emit::BundleEmit, AnyError> {
|
|
log::info!("{} {}", colors::green("Bundle"), graph.roots[0]);
|
|
|
|
let ts_config_result = ps
|
|
.options
|
|
.resolve_ts_config_for_emit(TsConfigType::Bundle)?;
|
|
if ps.options.type_check_mode() == TypeCheckMode::None {
|
|
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
|
log::warn!("{}", ignored_options);
|
|
}
|
|
}
|
|
|
|
deno_emit::bundle_graph(
|
|
graph,
|
|
deno_emit::BundleOptions {
|
|
bundle_type: deno_emit::BundleType::Module,
|
|
emit_options: ts_config_result.ts_config.into(),
|
|
emit_ignore_directives: true,
|
|
},
|
|
)
|
|
}
|