unjs / unbuild

📦 A unified JavaScript build system
MIT License
2.36k stars 90 forks source link

`__dirname` + relative path (`../`) returns unexpected path after build #354

Closed phanect closed 10 months ago

phanect commented 10 months ago

Environment

Environment of repro (Stackblitz)

~/projects/stackblitz-starters-hebbrj 4s
❯ node --version
v18.18.0

~/projects/stackblitz-starters-hebbrj
❯ npx unbuild --version
2.0.0        

Environment of my local PC

$ node --version
v20.10.0
$ npx unbuild --version
2.0.0
$ lsb_release -a
No LSB modules are available.
Distributor ID: Neon
Description:    KDE neon 5.27
Release:        22.04
Codename:       jammy

# KDE neon is a Linux distro and currently based on Ubuntu 22.04

Reproduction

https://stackblitz.com/edit/stackblitz-starters-hebbrj

Run npm start to build and run the compiled mjs.

Describe the bug

When you build a path with Node.js's path.join() in a different deepness from the build path (e.g. the generated file is $PROJECT_ROOT/build/main.mjs and the source file is in $PROJECT_ROOT/foo/bar/library.ts), path.join() returns unexpected path when you join __dirname and relative path like path.join(__dirname, '../../../..').

In the repro, I created a TS file path/to/deep/folder/lib.ts and declare a variable projectRoot as follows: const projectRoot = join(__dirname, '../../../..'); The project root is /home/projects/stackblitz-starters-hebbrj, so projectRoot should be "/home/projects/stackblitz-starters-hebbrj".

I call this projectRoot variable from main.ts in the project root and build it with unbuild. However, when I build it and run the generated mjs, projectRoot points "/".

This happened because all the source files are compiled to dist/main.mjs and join(__dirname, '../../../..') runs on it. In the built mjs, __dirname is /home/projects/stackblitz-starters-hebbrj/dist while I expected __dirname is /home/projects/stackblitz-starters-hebbrj/path/to/deep/folder.

I understand it is hard to handle this issue (and I'm not sure if it should be considered as a bug), but I believe it should make a better developer experience if this issue is resolved. Sorry if this is not an issue caused by unbuild but by the bundlers (esbuild or mkdist?).

Additional context

No response

Logs

Log of `npm start`:

~/projects/stackblitz-starters-hebbrj 5s
❯ npm start

> unbuild-issue-relative-path@1.0.0 start
> npm run build && node ./dist/main.mjs

> unbuild-issue-relative-path@1.0.0 build
> unbuild

# ...Build logs...

----------

Project root given by path/to/deep/folder/lib.js (wrong): /
Project root given by process.cwd() (correct): /home/projects/stackblitz-starters-hebbrj
peterroe commented 10 months ago

Hi, @phanect, I also meet the same problem. I think this is expected behavior. As you said. It's hard to handle this problem by bundlers

This is my two methods to get expected path:

  1. Use mkdist: keep original file structure
  2. Set project root path as global variable
    
    // src/main.ts
    import { finup } from 'find-up'
    process.env.ROOT_PATH = findUpSync('package.json')

// src/template/build.ejs // Some Content

// src/other/file/foo.ts const path = resolve(process.env.ROOT_PATH, 'template/build.ejs')

phanect commented 10 months ago

Hi @peterroe, thanks for your reply :)

I understand it is hard to handle this by unbuild (and maybe esbuild). I will try mkdist. Thanks for the workaround.

I'm closing this Issue.