deno: Unexpected import.meta.url value when bundling

I’ve noticed that when using paths relative to import.meta.url, the bundle hardcodes the path. Here is an example:

// relative.ts

import * as path from 'https://deno.land/std/path/mod.ts';

const main = async () => {
  const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
  const relativeDataPath = path.join(moduleDir, 'file.ext');
  console.log(relativeDataPath);
};

if (import.meta.main) main();
subdirectory % deno run relative.ts 
/path/to/example/subdirectory/file.ext

# output ok, now bundle...

subdirectory % deno bundle relative.ts relative.bundle.js
Bundling file:///path/to/example/subdirectory/relative.ts
Emitting bundle to "relative.bundle.js"
106.77 KB emitted.

# run bundle...

subdirectory % deno run relative.bundle.js 
/path/to/example/subdirectory/file.ext

# output ok, now move bundle to a different directory...

subdirectory % mv relative.bundle.js ../

# change to that directory...

subdirectory % cd ..

# run bundle again...

example % deno run relative.bundle.js 
/path/to/example/subdirectory/file.ext

# output is wrong!

Is this the expected behavior, or is it a bug? If expected, how do I accommodate for this?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 24 (20 by maintainers)

Commits related to this issue

Most upvoted comments

The output of the unit test here demonstrates it: https://github.com/denoland/deno/blob/master/cli/tests/bundle/fixture06.out. When the module is a root/entry module import.meta.main is preserved, all other modules when they are flattened in the bundle it is replaced with false.

Can you edit the title of this issue be about the import.meta.bundle boolean?

Ok; what title would you like?

I’m wondering if it’s possible to expose the rollup option you mentioned for relative/absolute path references to each bundled module’s import.meta.url when using deno bundle? This was surprising behavior to me, and I don’t think I’ll be the last one.

But as you mention, that becomes a challenge when a local module is outside of the root of the main module. Given your specific use case Deno.mainModule() is a better solution. The only potential improvement is to potentially add a import.meta.bundle so that at runtime code could better determine what sort of environment it was in. Really want to try to avoid “configuration” for deno bundle as much as possible, especially something that impacts the runtime information/behaviour as it becomes a barrier to that being consumed down the road, because the consumer has to “know” how the bundle was configured. Things like import-maps get fully resolved and don’t impact the downstream behaviour of the code.

If we feel that there are no questionable semantics about how Deno.mainModule() works then an issue to stabilise Deno.mainModule() would the logical thing to do. It was post 1.0 functionality, so by default it was placed into unstable, just to make sure that it was behaving correctly. Because it doesn’t break any existing code, there should be no barrier to stabilising it before 2.0.

But it is better to keep the issues opened focused on specifically what needs to be done.

There’s simply a lot of not stable ways to do things, until those APIs are stabilised.

I think that wouldn’t be possible for some cases. Example: ../../../mod1.ts at bundle time and invoked from /dir/bundle.js

Is there something equivalent to entrypoint.meta.url?