Closed danielgindi closed 4 years ago
Yay, finally passed all tests!
There's one weird thing with an additional \n
that broke 2 tests, did not figure out why yet.
@danielgindi Any update, when this feature will be released. I badly need this feature.
@ansarizafar It's not up to me...
I'll rebase on master as there are conflicts now
@danielgindi will your implementation support complete dynamic path with require. Wepack does not support full dynamic path. const location = '/project/modules; const file = 'user,js' example require(location + file);
@ansarizafar Yes, but in case of fully dynamic path you'll have to tell the plugin to include those files so it can find it dynamically in runtime. You do that with the dynamicRequires
option like in the example.
You can actually add the git url to the package.json
instead of an npm version and see if it works for you.
In my case path is fully dynamic and only known at runtime. It would be very useful If dynamicRequires option also allow a folder path from where to load files dynamically.
It does.
@guybedford are you going to consider merging this?
I've been working with this successfully for 2 months now with problematic modules like knex
, logform
etc.
I will take look, probably early next week. This looks really promising.
From what I see from a first glance at the code: Maybe you want to split up some of the functions used. I know rollup-plugin-commonjs is some kind of a mess with this regard already so any works towards cleaning this up, at least as far as things are touched by this feature, is highly appreciated!
This will also make the review a little faster :) Anyway, I am currently going over the core plugins to ensure rollup@1.0 compatibility, and having this feature would fit in nicely!
@lukastaegert Yeah I noticed the mess, but didn't want to make too many structural changes as it usually makes PRs harder to review. It's easier to do it separately and then run the tests to see who broke stuff :-)
Hi @danielgindi! I started going through your PR. This looks really impressive!
It will probably take a moment until I am done. I hope you do not mind if I do some minor refactorings on your branch to get a better feeling for what is going on (as I wanted to do this anyway and your PR gives me an excuse 😜)?
Also, it would be good to sync the fork with current master as there have been some smaller changes.
I don’t mind at all :) Ad we have a bunch of holidays here one after the other, I don’t have time to look into your comments and assist on the PR but I will get to it soon!
Wow you've done a lot of work there! I was just getting ready rolling up my sleeves but then I see all of that work. I see that you've done general refactoring to the library, things that I couldn't safely do without deeper knowledge of the library. Amazing!
Thanks for the kind words. I must admit I really wanted this feature to go into the next release but at the moment it looks like there is quite a bit more to do. So my current plan is to extract the refactorings from the PR and but them into a separate PR so that I can focus on making the plugin Rollup@1.0 compatible (which was my original goal). Here is a list of what I did so far and what I believe should be done before this one can get merged:
dynamicRequires
to dynamicRequireTargets
as I found it confusing initially whether it referred to the files being required or the files doing the requiringAdded lots of test for the completely untested basic functionalities:
index.js
/package.json
works if the node-resolve plugin is present and we get the same instances if we require in different waysWith those tests in place, it should be a little easier to refactor code with some confidence. Nevertheless, there are probably quite a few untested things left. My rule of thumb is that removing or fundamentally changing a line of code should result in a red test. This also serves as the documentation and the insurance that refactorings do not break existing functionality. Most of the helper code is tested now but I did not look too deeply into the other code yet. Also, I could not figure out or write a test for the third if-statement case in commonjsRequire
. There should either be a test or it should be refactored so that this case does not exist.
require
statement for the path
module. This had the result that created bundles were basically unusable in browsers or as ES modules. I solved this by adding a simple polyfill for the normalize function.At the moment, the code assumes the first module read is the entry point, reads this module (ignoring other load hooks) and injects the dynamic module list. This is bad for several reasons:
It seems that the injection should probably happen in a transform hook instead and it should happen in all entry points (relying on the fact that rollup will dedupe the helper code).
require
(as they will only work in node anyway). All other paths could then be resolved relative to a common local directory which could be the common ancestor of all dynamic require targets. node_modules
resolution attempts could also stop at this common ancestor directory.These are the most important points that struck me while working with the code. The main idea is very promising but personally, my target is to get this plugin to be rollup 1.0 compatible which I will focus on first. I will not be working on this PR for some time, if you would improve on some of the points listed above, this would be great!
@lukastaegert As for the third if-case - that is resolved in my latest commits. I did some work on the path-module replicas there, as they had some bugs and broke a module that I'm compiling with this. Added tests for that too.
As for local paths hardcoded into the module - I'm aware of that, and in my own code which calls the rollup I'm replacing it with a root path. It could probably be done automatically, but not 100% as if someone has require
calls to a module in a completely different path tree or a different drive - that would break things.
I'm not sure that we have to handle all complex cases right away with this. As this already covers most situations (that I stumbled upon, at least), and without this you have no other options anyway.
This also does not break compatibility, as it's optional - you specify dynamicRequireTargets
, and without it nothing special is happening from this PR.
Btw there are many cases where dynamic requires are required that will be redundant in the future, as some modules are moving away from circular dependencies and dynamic requires. I posted quite a few issues in popular modules that do that, and most of them fixed it.
However some modules are more complex than others, like knex
, where I fixed the issues with the module's core - but you still have to dynamically require the specific dialect that you are going to use.
Also what do you prefer - rebase on master or merge from master? As there are conflicts now
Merging is ok as we will squash the PR anyway in the end
@lukastaegert I've added a proposal commit for handling the test with dynamic-require-es-entry
, please review it!
It succeeds, but breaks form/unambiguous-with-default-export
, form/unambiguous-with-import
, and form/unambiguous-with-named-export
.
Of course the output could be changed accordingly, but I want to make sure that this is the real expected output.
Also I see that in many tests the output contains imports from "commonjs-proxy:..."
. Is this really what's expected? And why don't those "proxies" pass again through the plugin? I don't see them passing in resolveId/load
@lukastaegert since there were so many conflicts with each merge due to the heavy refactoring - I've rebased this on master, and compared to the merged version to make sure that it's exactly the same. This removed the heavy refactoring commits and let us stay with a steady branch
I need you to look at the tests - I think that the ones that are failing need to adjust their expected outputs. But can't be sure.
Hi @danielgindi, sorry for the wait. The last weeks, I was busy with some important private matters as well as trying to finally get the rollup 1.0 release going, which for me has some priority as I hope you will understand.
It succeeds, but breaks form/unambiguous-with-default-export, form/unambiguous-with-import, and form/unambiguous-with-named-export
These tests make sure that a file that is already ESM (i.e. it contains import or export statements) is allowed to have a function named require
without getting it transpiled. These tests should not be broken!
Also I see that in many tests the output contains imports from "commonjs-proxy:...". Is this really what's expected?
Yes, the form
tests only test the transform function but not the entire process. These proxies are references to virtual modules injected by the plugin via the load
hook. In the end, rollup itself resolves these imports via the virtual modules. The entire process is tested via the function
tests (and the misc
tests but the idea is to replace most of them with function
tests if possible).
I don't see them passing in resolveId/load
But they do, it is the very first lines of resolveId
(const isProxyModule = importee.startsWith(PROXY_PREFIX); if (isProxyModule) {...
) as well as in the middle of the load
function (if (id.startsWith(PROXY_PREFIX)) {...
).
This removed the heavy refactoring commits and let us stay with a steady branch
This was my hope with cherry-picking them to a separate PR.
As for the future of this PR, this is why I am not happy to merge this in its current form:
.
. normalize
function in the helpers to handle ../..
paths correctly. So basically you fixed a bug in the code. Where is the test for that? Untested code cannot be refactored safely, especially not by a person that did not originally write the code (or by the person who wrote the code after a few months). As I said before, more than anything this plugin needs a thorough refactoring cleanup; also, this plugin is one of the most important plugins of the ecosystem. So please understand if I insist on good test coverage, especially for the helper code that is added to bundles.So here is my suggested path forward:
.
(e.g. by leaving the require
untranspiled)Sorry this is quite a long list of things to do. Note that even if we drastically reduce the scope of this PR, it does not mean the things we skip cannot be re-added at some later point. So make sure you keep a copy of the branch in its current state for reference.
Well a few points are already resolved AFAIK.
normalize
function is tested. I've added tests for that, to make sure that we're not missing these edge cases.Overall the PR seems huge, but it's mainly tests...
I understand your priorities and considerations, it's OK if this takes a little bit more time.
@lukastaegert How can we get this moving?
@danielgindi First, apologies that this didn't get the attention it needed. We've got a great team of developers that have joined in on a Plugin Maintainers team and we're migrating all of the rollup plugins to a monorepo at https://github.com/rollup/plugins.
I'd like to invite you to reopen your pull request on that repo once the move there is done. I fully recognize that it's a big ask. The unfortunate fact is that PR is just too large for us to get reviewed properly before we'd like to get the plugin moved. I also don't want to ask you to resolve any conflicts once again without a promise that it'll have eyes on it when it's done. I can tell you that a PR at the new plugins monorepo would have eyes on it.
Does that sound good to you?
@shellscape Yes, I'll try to get some time for it in the following days
Thanks for replying, and no rush. I'll ping you again once we have the plugin moved to rollup/plugins.
We've completed the move to the new repo. Please look for it in https://github.com/rollup/plugins
This can handle cases of dynamic requires (
return require(modules[index])
/require(modulesPath + './test.js')
) and circular dependencies.Closes #131