Fridious
Fridious•7mo ago

Module loading

Hey, I am just testing the deno_core. I know, that the deno runtime with the command line supports native executing of ts files and also loading of dependencies by an url and also npm depependcies out of the box. As I evaluated it, the deno_core does not support this by default, so how to easily implement executing ts files and loading of depencies by url? I already found, that I can set a custom module_loader and a custom_module_evaluation_cb for the JsRuntime, but I think there is an easier way to do this instead of integrating it by myself. Thanks for you help
2 Replies
Deno AI Helper
Deno AI Helper•7mo ago
Hello! You're correct that deno_core doesn't support TypeScript execution and dependency loading by URL out of the box. It provides a lower-level API that allows you to build these features on top of it. To execute TypeScript files and load dependencies by URL, you would typically need to implement a custom ModuleLoader that can handle these tasks. The documentation provides an example of how to create a custom ModuleLoader that can resolve and load TypeScript modules. Here's a simplified version of the process: 1. Implement the ModuleLoader trait for your custom loader, which includes the resolve and load functions. 2. Use deno_core::resolve_import to resolve module specifiers in the resolve function. 3. In the load function, determine the file's media type and whether it needs transpiling. 4. Read the file into a string and transpile it if necessary using deno_ast. 5. Return the transpiled code as a ModuleSource. Here's a snippet from the documentation that outlines the structure of a custom ModuleLoader:
struct TsModuleLoader;

impl deno_core::ModuleLoader for TsModuleLoader {
fn resolve(
&self,
specifier: &str,
referrer: &str,
_kind: deno_core::ResolutionKind,
) -> Result<deno_core::ModuleSpecifier, deno_core::error::AnyError> {
deno_core::resolve_import(specifier, referrer).map_err(|e| e.into())
}

// ... load function implementation ...
}
struct TsModuleLoader;

impl deno_core::ModuleLoader for TsModuleLoader {
fn resolve(
&self,
specifier: &str,
referrer: &str,
_kind: deno_core::ResolutionKind,
) -> Result<deno_core::ModuleSpecifier, deno_core::error::AnyError> {
deno_core::resolve_import(specifier, referrer).map_err(|e| e.into())
}

// ... load function implementation ...
}
And the load function would look something like this:
fn load(
&self,
module_specifier: &deno_core::ModuleSpecifier,
_maybe_referrer: Option<deno_core::ModuleSpecifier>,
_is_dyn_import: bool,
) -> std::pin::Pin<Box<deno_core::ModuleSourceFuture>> {
// ... implementation details ...
}
fn load(
&self,
module_specifier: &deno_core::ModuleSpecifier,
_maybe_referrer: Option<deno_core::ModuleSpecifier>,
_is_dyn_import: bool,
) -> std::pin::Pin<Box<deno_core::ModuleSourceFuture>> {
// ... implementation details ...
}
In the load function, you would use deno_ast to
Deno AI Helper
Deno AI Helper•7mo ago
parse and transpile TypeScript to JavaScript. The deno_ast crate is part of the Deno ecosystem and can be added to your dependencies to handle the parsing and transpiling of TypeScript. While this does require some manual setup, it allows you to have fine-grained control over how modules are loaded and processed. If you're looking for a more out-of-the-box solution, you might consider using the full Deno runtime for executing TypeScript and managing dependencies, as it already has these capabilities built-in. For more detailed guidance and code examples, you can refer to the Deno blog post titled "Roll your own JavaScript runtime, pt. 2" which is available in the documentation. 🦕