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

Relative imports ignored via “browser” field cause absolute paths in source maps #785

Closed
eelco opened this issue Feb 10, 2021 · 2 comments · Fixed by #787
Closed

Relative imports ignored via “browser” field cause absolute paths in source maps #785

eelco opened this issue Feb 10, 2021 · 2 comments · Fixed by #787

Comments

@eelco
Copy link
Contributor

eelco commented Feb 10, 2021

While looking into why our builds were not perfectly reproducing between different systems, I ended up finding that in some cases, absolute paths end up in the source map file, causing the hash to change.

Example (snippet from .map file):

"empty:/mnt/ramdisk/node_modules/paper/dist/node/self.js", "empty:/mnt/ramdisk/node_modules/paper/dist/node/extend.js", "../../../../node_modules/paper/dist/paper-core.js"

Turns out, this is caused by the browser field in the package.json of dependencies. In this case: https://github.com/paperjs/paper.js/blob/095671073b9cfed2221b48aea54776ca6f2aed70/package.json#L45-L52

  "browser": {
    "canvas": false,
    "jsdom": false,
    "jsdom/lib/jsdom/living/generated/utils": false,
    "source-map-support": false,
    "./dist/node/self.js": false,
    "./dist/node/extend.js": false
  },

I believe this is caused by the resolver, specifically:

return &ResolveResult{PathPair: PathPair{Primary: logger.Path{Text: absPath, Namespace: BrowserFalseNamespace}}}

And

if absolute, ok := r.loadNodeModules(importPath, kind, sourceDirInfo); ok {
absolute.Primary = logger.Path{Text: absolute.Primary.Text, Namespace: BrowserFalseNamespace}
if absolute.HasSecondary() {
absolute.Secondary = logger.Path{Text: absolute.Secondary.Text, Namespace: BrowserFalseNamespace}
}
return &ResolveResult{PathPair: absolute}

I’m not sure why this has to be an absolute path, nor why these should be part of the sourcemap, and as this causes differences between builds on different systems, I’d love to get rid of it.

@evanw
Copy link
Owner

evanw commented Feb 11, 2021

Thanks for the report. I intend to have output files be deterministic across different systems so this is a bug.

This happens because esbuild uses absolute paths internally to represent file identity, esbuild converts absolute file system paths to relative paths for output file determinism, and esbuild only interprets paths in the file namespace as file system paths. Paths in other namespaces could be in an arbitrary format that is up to whichever plugin made them, and esbuild deliberately doesn't change with those paths to avoid messing with the plugin.

The change to preserve non-file paths was made with the introduction of the plugin API. However, that broke this internal code which uses the empty namespace for these files. One way to fix this could be to use some other mechanism instead of the empty namespace to flag empty modules.

@evanw evanw closed this as completed in 419b801 Feb 11, 2021
@eelco
Copy link
Contributor Author

eelco commented Feb 11, 2021

Thank you so much for the fast fix! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants