add the ability to rewrite modules in-place#1922
Conversation
|
Turns out the the folders are not preserved: "app/index.js" => "index.js". I will work on that next. |
58a6c3b to
601f886
Compare
|
Added another option to enable original directory structure. |
08ed72d to
c66aef5
Compare
guybedford
left a comment
There was a problem hiding this comment.
I've included some feedback here, let me know your thoughts.
| curEntry.isEntryPoint = true; | ||
| curEntryHash = randomUint8Array(10); | ||
| visit(curEntry); | ||
| } |
There was a problem hiding this comment.
It seems like this is done to ensure that no chunking happens right?
I think it can be done more easily by altering the visit function itself to do something like:
if (!preserveModules)
Uint8ArrayXor(module.entryPointsHash, curEntryHash);
else if (isZero(module.entryPointsHash))
module.entryPointsHash = randomUint8Array(10);then I think that would be all there is too it without any extra loops or need to track modules.
There was a problem hiding this comment.
Perfect! It got a lot simpler with this change.
| preservedModules.forEach(module => { | ||
| if (entryModules.indexOf(module) === -1) | ||
| entryModules.push(module); | ||
| }); |
There was a problem hiding this comment.
This is just "all modules" right? If so it should be possible to generate from Object.values(this.graph) + this.externals?
There was a problem hiding this comment.
removed with your other suggested change.
| // generate the imports and exports for the output chunk file | ||
| if (chunk.entryModule) { | ||
| const entryName = generateChunkName(chunk.entryModule.id, chunkNames, true); | ||
| const entryName = generateChunkName(chunk.entryModule.id, chunkNames, true, inputRelativeDir); |
There was a problem hiding this comment.
Is this a mandatory option then? Is there not a way to deduce the lowest base by default if this is not provided?
There was a problem hiding this comment.
Since commondir is not widely maintained and a small piece of code, do you think we could just inline the implementation?
There was a problem hiding this comment.
I could do that. Are you sure I should just copy paste? I would argue that we depend on it until we need to fix something, then copy. @lukastaegert care to tie-break?
There was a problem hiding this comment.
I must admit I did not read everything here. Looking at commondir, it relies on nodes path.resolve which we do not have available in a browser build—even though we have our own polyfill for that (damn, we REALLY need a test for this. You should see a warning about "path" being external when building rollup with this setup—this is always BAD). Thus I fear this needs to go into our own code base somehow.
However I am happy for every bit of functionality we can extract from Graphs.ts and put into other files and for me, this is a clear candidate for the "utils" folder.
There was a problem hiding this comment.
ported into the utils folder.
0a319a1 to
d3006af
Compare
d3006af to
086baab
Compare
|
It's pretty awesome how small this feature has got. And it definitely preserves the original pathnames ok with directory creation etc? |
|
From my testing, yes. It does get weird if your entry file imports from '../../../../../x', then your output dir will look pretty strange, but it should still work and be "correct". |
c9647d3 to
803d043
Compare
guybedford
left a comment
There was a problem hiding this comment.
Looking good.
@lukastaegert would be interested to hear your thoughts here as well.
| @@ -0,0 +1,21 @@ | |||
| // ported from https://github.com/substack/node-commondir | |||
| export default function commondir (relfiles: string[]) { | |||
| var files = relfiles; | |||
There was a problem hiding this comment.
Perhaps just name the argument files/
| export default function commondir (relfiles: string[]) { | ||
| var files = relfiles; | ||
|
|
||
| var res = files.slice(1).reduce(function (ps, file) { |
There was a problem hiding this comment.
const and arrow function can be used.
| var res = files.slice(1).reduce(function (ps, file) { | ||
| if (!file.match(/^([A-Za-z]:)?\/|\\/)) { | ||
| throw new Error('relative path without a basedir'); | ||
| } |
There was a problem hiding this comment.
If we know that our inputs will pass this, it may be possible to remove this check.
| throw new Error('relative path without a basedir'); | ||
| } | ||
|
|
||
| var xs = file.split(/\/+|\\+/); |
| for ( | ||
| var i = 0; | ||
| ps[i] === xs[i] && i < Math.min(ps.length, xs.length); | ||
| i++ |
There was a problem hiding this comment.
compiler didn't like that
| name = path.relative(inputRelativeDir, id).replace(/\\/g, '/'); | ||
| } else { | ||
| name = path.basename(id); | ||
| } |
There was a problem hiding this comment.
Check indentation here.
There was a problem hiding this comment.
One thing I observed that I think we should definitely improve is the fact that if a module imports something from outside the common directory of the entry points (i.e. if the entry point imports something that starts with ../), new files and folders are created outside the intended target directory. This can definitely leave a mess on an unsuspecting user's system. In my opinion there are two possible solutions
- throw an error if something like this would happen (probably not ideal), or
- find the common root directory not among the entry points but among the generated chunk file names.
To achieve the latter, we could do the following:
- use
generateChunkNameonly for the non-path-preserving case (and remove the last argument) - if we preserve paths/modules, we use the completed
chunksobject to build a new object with correct paths (possibly extract a helper method here)
This is just a rough idea, some fine-tuning may be necessary.
|
Sure thing. Was a little busy the last days to get my own PR in order. Will probably take a look at this evening or tomorrow. I think this could become on of the core features of 0.57.0! |
|
BTW some of the chunking form tests seem to be broken. And this should probably be rebased against the current master soon. |
|
@lukastaegert I discovered a bug, so I added more test cases. I'm trying to diagnose it now. |
e061cc2 to
3849e93
Compare
|
@lukastaegert @guybedford Turns out it might not be a bug, but an understanding issue. It has to do with what's going on in \test\chunking-form\samples\chunking-reexport. The way it's collapsing reexports there is unexpected to me, and probably not desirable for this new feature. I would love some pointers. |
|
@kellyselden can you link me to the test case that is failing? I just re-ran the CI here and it seems nothing is breaking specifically. If I can follow the exact simplified scenario I may be able to suggest further. |
|
@guybedford https://github.com/rollup/rollup/pull/1922/files#diff-c7e8e1a25cc0ed7f80f7f0df33f956c7R7 |
7481a1e to
5ede078
Compare
|
@guybedford I added the test for export aliases. Since there are still two commits, I added the test to the first one, and export aliases worked as expected. Then I had to modify the test to remove the aliases once your commit was added on top. You probably already knew this, I just wanted to point it out in case you didn't. |
5ede078 to
f837ca7
Compare
|
This option is still not documented on the site? It seems that i just should try it ;/ |
|
I think we should document this now actually. A documentation PR is more than welcome! |
Closes #1878.
This turned out to be remarkably simpler once @guybedford laid the foundational work with dynamic imports and chunking. I essentially tapped into the dynamic imports system and made every import behave like a dynamic import.
To try this out, all you have to do is add the
experimentalPreserveModulesto your existingexperimentalCodeSplittingsetup. Then, the directory tree should be preserved in your output dir.