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

feat(@parcel/transformer-js): Rewrite __dirname/__filename to be relative to asset.filePath #7727

Merged
merged 50 commits into from Apr 11, 2022
Merged

feat(@parcel/transformer-js): Rewrite __dirname/__filename to be relative to asset.filePath #7727

merged 50 commits into from Apr 11, 2022

Conversation

LekoArts
Copy link
Contributor

@LekoArts LekoArts commented Feb 17, 2022

↪️ Pull Request

This adds a way of accomplishing #7611 - this functionality will be enabled by default in node environment.

Fixes #7611

💻 Examples

See linked issue, but TL;DR is:

Some code in e.g. <root>/index.ts has a ${__dirname}/data string in it.
When it'll be compiled to e.g. <root>/dist the path should be changed to:

const path = require("path")
const dirname = path.resolve(__dirname, "..")
return `${dirname}/data`

🚨 Test instructions

I've added a test to the integration tests, it has to have the node env (so e.g. engines: node key).

✔️ PR Todo

  • Added/updated unit tests for this change
  • Filled out test instructions (In case there aren't any unit tests)
  • Included links to related issues/PRs

@height
Copy link

height bot commented Feb 17, 2022

Link Height tasks by mentioning a task ID in the pull request title or commit messages, or description and comments with the keyword link (e.g. "Link T-123").

💡Tip: You can also use "Close T-X" to automatically close a task when the pull request is merged.

@LekoArts LekoArts changed the title feat(@parcel/transformer-js): Rewrite __dirname to be relative to projectRoot feat(@parcel/transformer-js): Rewrite __dirname/__filename to be relative to projectRoot Feb 17, 2022
Copy link
Member

@mischnic mischnic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall!

IMO relativeContext doesn't really convey that this is about __dirname and __filename 🤷‍♂️


There's a similar existing test here:

it('should insert global variables when needed', async function () {

So duplicate that and add a package.json with that new config option, then you can delete the example you've committed.


Regarding the path import: this is similar to how an import for buffer is added for the Buffer global, that is done here:

@LekoArts
Copy link
Contributor Author

Ok, so I pushed some more changes to the Rust code and I have two problems now:

  1. Actually the generated relative path is incorrect
  2. I'm not seeing my changes in the tests

Let me explain.


When we have a source file at <root>/index.ts and we compile to <root>/dist/index.js we would expect that the relative path to the projectRoot is "..".
But it isn't.

Here is the relevant line: https://github.com/LekoArts/parcel/blob/eca555e83e8ba3ac7ad0eded8dd9c0723a21713e/packages/transformers/js/core/src/global_replacer.rs#L144

dirname here is the path of the <root>/index.ts file, which is identical with projectRoot. So the relative path created will be "" and not "..".

How can I get the distDir here to construct a correct relative path?


I'm not seeing my Rust code changes in the tests. I think I've added the test and the new option correctly, but when I print out the js (currently commented out) I'm not seeing the changes I did when I still had the example project in packages/examples.

@LekoArts
Copy link
Contributor Author

Let me know @mischnic if my above questions/comments make sense and you can help me? Appreciate it a lot! Thanks

@mischnic
Copy link
Member

How can I get the distDir here to construct a correct relative path?

The transformer doesn't know the final path of the bundle that the asset will be put into. This is only known after bundling/packaging (https://parceljs.org/plugin-system/overview/), so you have to do the path.relative(root, bundle.filePath) computation and insertion in a packager (so @parcel/packager-js).


I don't know why the changes wouldn't show up in the tests (apart from forgetting to recompile the Rust code), so I guess it has to be that your change doesn't modify the behaviour somehow.

@LekoArts
Copy link
Contributor Author

Ok, thanks for that information. I'll look into the tests, I probably made an error somewhere.

I'm trying to wrap my head around how to go about this then. Do I need to keep the changes I made to the transformer so far and add some "identifier" so that later the packager can modify/replace things, or do I completely remove the Rust logic and make all my changes in the packager? From my understand I'd need both, so that in the transformer I actually replace the call and then the packager can change the import path?

@mischnic
Copy link
Member

Exactly. The logic to determine whether __dirname wasn't declared as a local variable definitely needs to happen in the transformer.

Then in the packager, one possibility would be replacing that placeholder literally or (though somewhat sketchy) do the same as $parcel$global and just assume that this variable is unused by the user and emit it in the transformer, and then prepend a variable declaration in the packager. Though in this case you probably need one variable per asset

return Ident::new("$parcel$global".into(), node.span);

@LekoArts
Copy link
Contributor Author

Ok, I was sick 🤧 for a bit, I'll start working on this again now

@LekoArts
Copy link
Contributor Author

Ok, so I got it working in my example (currently still committed in this PR) in how I expect it:

Bildschirmfoto 2022-03-18 um 12 54 01

But I'll remove the example and add tests.

The API and naming etc. is pretty gross and I'm also still using same placeholder everywhere, not per asset.

So it works, but still lot to do.

@mischnic

@LekoArts LekoArts marked this pull request as ready for review March 22, 2022 15:50
@LekoArts
Copy link
Contributor Author

LekoArts commented Apr 7, 2022

Thanks! Will look into it and add a test

@LekoArts
Copy link
Contributor Author

LekoArts commented Apr 7, 2022

Good catch @mischnic 👍

The issue was that I've used pathdiff::diff_paths for __filename where I didn't need to use it. It just worked in the past but it seems with /folder-name/index.js it doesn't give back index.js but /folder-name/index.js.

Copy link
Member

@mischnic mischnic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@LekoArts
Copy link
Contributor Author

LekoArts commented Apr 8, 2022

Awesome 🎉 I'll let you re-run the CI, otherwise with my commit trigger I'd invalidate your review

),
);
wrapped = wrapped.replace('$parcel$dirnameReplace', relPath);
wrapped = wrapped.replace('$parcel$filenameReplace', relPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we have two different variables that get replaced with the same path? Were these meant to be different, or do we only need one of them?


*self.has_node_replacements = true;
}
"__dirname" => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of this could probably be combined with the above but ok for now

Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall! Thanks again!

@LekoArts
Copy link
Contributor Author

LekoArts commented Apr 8, 2022

I will optimize this (i.e. address the two new review comments) in a follow-up PR -- I'd like to get this into a nightly release so that we can try it out at Gatsby :)

@LekoArts
Copy link
Contributor Author

I think you'll need to re-run a bunch of times for the flaky tests 😅

@LekoArts
Copy link
Contributor Author

LekoArts commented Apr 11, 2022

With #7931 merged I guess I need to change some ast::Lit::Str occurrences. I'll do this in a bit

@mischnic
Copy link
Member

Sorry, I forgot that merging it would break this PR 😬

@mischnic
Copy link
Member

mischnic commented Apr 11, 2022

Looks like it compiles, the only breaking change from the swc update was related to :ast:Number. And these changes from ast::Str{} to .into() are just using a shorter syntax and are equivalent. So we can clean that up later.

@mischnic mischnic merged commit be0929a into parcel-bundler:v2 Apr 11, 2022
@LekoArts
Copy link
Contributor Author

Awesome. I'll do that in the follow-up PR. Thanks for merging and help on the PR <3

@LekoArts LekoArts deleted the dirname-relative-path branch April 11, 2022 15:23
@LekoArts
Copy link
Contributor Author

The nightly release that would include this failed here: https://github.com/parcel-bundler/parcel/actions/runs/2151865409

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

Successfully merging this pull request may close these issues.

Rewrite __dirname/__filename to be relative from asset.filePath
3 participants