Venryx/webpack-runtime-require

What if two modules have the same name?

anton164 opened this issue · 5 comments

From the readme:

// if path was "./Path/To/MyComponent", specify just the file-name
let MyComponent = Require("MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);

I have a pretty large project with > 100 packages, and > 1000 modules so there are definitely going to be conflicts with the above approach.

Is there a technical reason of why this shouldn't be possible?
let MyComponent = Require("Path/To/MyComponent");

At the moment, I think the later module with a given name will just override the earlier module. It's not ideal, but just haven't had the need personally to make it work any differently.

There's no technical reason is has to work this way, as far as I recall; I think I did it that way to make it easier to require modules from the console. (instead of having to remember/type the whole path)

If you want to use the paths instead of just the module name, change the GetModuleNameFromPath function in this file: https://github.com/Venryx/webpack-runtime-require/blob/master/Source/Utils.ts

Remove all the code in that function, and replace it with just the line: return path;

Of course, you'll have to recompile the library then. So, clone the repo, run npm install, make the code change, then run npm run dev. (or press ctrl+shift+b with the project open in vscode)

For ease of use, you can then run npm link in the library folder to place a symbolic-link from your npm global packages folder to your customized version. Then run npm link webpack-runtime-require in any project where you want to use your modified version. Of course, this solution doesn't really work if you have other people working on your project, since your modified version isn't accessible to them. (in the case of a team project, might just want to include the code from the library in some subfolder in your project and make the customization there)

All that said, the library should really:

  1. Have built-in support for path-based requires. (as an option)
  2. If using name-based, at least not have same-name modules overwrite each other.
  3. Beyond that, collect a flat list of exports in another container so you can more efficiently access functions and such from the console.

I already have #3 accomplished actually, however it's not part of this library yet. The set-up function for it is here: https://github.com/Venryx/DebateMap/blob/master/Source/Main_Hot.tsx#L126

Anyway, I'll leave this issue open until I get around to completing the three tasks above.

I just pushed a commit which achieves task 3 of the above. (though haven't published a new npm version yet)

If two modules/files have the same name, the 2nd one will be stored as ${name}_. (and so on, adding an underscore whenever there's a name clash)

It's a stop-gap solution, to at least make the secondary modules/files accessible. Later I'll most likely add more flexibility in the area. (eg. tasks 1 and 3 above)

Awesome, I'll see if I can get around adding path-based requires.

Would love to see the above in a release :)

toddq commented

Not sure what you had in mind for path based requires, but I needed that so I added something here - https://github.com/toddq/webpack-runtime-require/commits/search-paths. I was originally going to just use explicit path matching, but for my specific use case using find/includes made for cleaner client code.

I've cleaned up the code quite a bit, and achieving path-based requires is pretty straightforward in the new version.

Something like the below should work:

function RequireModuleByPartialPath(partialPath) {
    const modulesByPath_entries = Object.entries(wrr.webpackData.moduleCache);
    return modulesByPath_entries.find(a=>a[0].includes(partialPath))[1];
}

Here's a screenshot of the helper function above in use:

(You can also just explore the new wrr.webpackData object manually in dev-tools console.)

Note that the helper function above does require the webpack config to have: config.optimization.moduleIds: "named" (in wp <=4: config.optimization.namedModules: true). (if that's not true for your project, there are ways you can still achieve it; but it takes a bit more work, as then you'll need to use the library's path-comment parsing functions rather than the paths from webpack's standard "named-modules" setting)