-
Notifications
You must be signed in to change notification settings - Fork 101
file cache (useful for build system interoperability). #94
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
Conversation
@ohjames Thanks for the suggestion. I too have been contemplating how to better support that scenario. Isn't this change going to make it so that it still tries to read the file from disk though (sorry if I skimmed it too quickly and misread)? I haven't looked into it too much yet, but the approach I was going to explore was documenting the pipeline better and being able to pass in row objects with a |
Nah it'll work check https://github.com/substack/module-deps/blob/master/index.js#L184
This would require modifying the way browserify interacts with module-deps, which I believe would also break watchify/browserify-incremental etc. The caching solution used at the moment is clearly less than ideal but there are many external libraries that depend on it. I'd definitely like to see it fixed in an ideal world though! For now though it would be really lovely if you could accept this change and push out a new release, as some people would really like to be able to use fast incremental browserify rebuilds via the sigh buildsystem and this patch would allow such a plugin to be written. |
To be clear I'd add a cache entry with only the |
You might also consider passing the cache entry to |
Okay I've added the "cache deps update" commit to this PR, I think it would be really neat. Can always be easily removed. |
With this API change you can have this greatness: var browserify = require('browserify');
var b = browserify({ cache: {} });
b.cache['./main.js'] = { source: mainSourceCodeThatDependsOnOtherStuff };
b.cache['./other-stuff.js'] = { source: otherStuffSourceCode };
b.add('./main.js');
b.bundle().pipe(process.stdout);
console.log(b.cache['./main.js'].deps); // will now log "{ './other-stuff.js': ... }"
/// ... time passes ... ///
b.cache['./main.js'] = { source: newMainSourceCode };
b.bundle().pipe(process.stdout); // re-uses cached other-stuff.js Wouldn't that be wonderful for streaming build systems! |
@ohjames Thanks for the additional info. I'll look at this closely when I get the chance (or someone else might beat me to it). |
Really would appreciate for this patch to land. Useful for some work I am planning to do. |
I like this since it's actually a bug fix, given that the code for reading a cached file already exists. But why the change in |
@zertosh The change in Or maybe I misunderstood something, I've been working this stuff out mainly from reading the |
@ohjames Got it. It seemed like that was the point. However, it's important for module-deps not to alter the cache since it treated as an immutable input throughout. If you need to invalidate/change it, then having a separate plugin doing what watchify does is perfectly reasonable. |
Watchify hooks into the cache to update the b.pipeline.get('deps').push(through.obj(function(row, enc, next) {
var file = row.expose ? b._expose[row.id] : row.file;
b.cache[file] = {
source: row.source,
deps: xtend({}, row.deps)
};
this.push(row);
next();
})); Is that the best way of doing it? I feel suspicious of that code. |
@ohjames that's how plugins work. what do you find suspicious? |
The bit: var file = row.expose ? b._expose[row.id] : row.file; Isn't the |
Ah, that line is to deal with exposed modules and the watcher file path. As for the Like I said earlier, your PR seems perfectly reasonable sans the |
Thanks for the info.
Okay I don't understand it but I guess I'll use the same fragment of code to update the cache in |
Okay I removed the cache entry updating. As for the test, it seems all the |
@ohjames Borrow as much as you want from the tests. But it's important that the test for this ensures that the transforms are being applied to the cached source. |
@zertosh Added the test. It's a modification of the I'm guessing that since this code only provides a minor extension to the feature already tested in |
@ohjames The existing cache tests don't worry about transformations because the cache is assumed to be the final output of module-deps. Your change does something completely different. Your change is pulling the source from the cache and running it through the transforms. So, your test should make sure that this true. |
Huh? All my change does is fix a crash that occurs when you have a cache entry with a
If the requirement you've stated for my test is necessary then could you help me understand why it isn't also a requirement of the These are the differences between the two tests:
|
You can verify the cached source code has passed the transform stages by the fact that the dependency is parsed from the cached code, I guess it might not be too hard to show the transform stuff on top but then I feel like maybe the test is testing more than it has to, I dunno it's up to you though. |
Your change, although small, has huge implications wrt transforms. When there is a So, with |
Thanks for taking the time to explain it, I see, that makes it sound like my change makes the single I think a better solution is needed than this then I guess. |
@ohjames I'm cool with a |
@zertosh yeah I reckon that sounds like a better solution, I was just adding an |
Okay cool I've added that. The test confirms that dependencies are parsed from the code in the |
Cool. There's no need to preserve the old behavior in diff --git a/index.js b/index.js
index 53fe143e..24a3e436 100644
--- a/index.js
+++ b/index.js
@@ -27,6 +27,7 @@ function Deps (opts) {
this.basedir = opts.basedir || process.cwd();
this.cache = opts.cache;
+ this.fileCache = opts.fileCache;
this.pkgCache = opts.packageCache || {};
this.pkgFileCache = {};
this.pkgFileCachePending = {};
@@ -181,8 +182,8 @@ Deps.prototype.resolve = function (id, parent, cb) {
Deps.prototype.readFile = function (file, id, pkg) {
var self = this;
var tr = through();
- if (this.cache && this.cache[file]) {
- tr.push(this.cache[file].source);
+ if (this.fileCache && this.fileCache[file]) {
+ tr.push(this.fileCache[file]);
tr.push(null);
return tr;
} As for the test, you can follow what's done in |
You're cool ;) 🐤 Sorry for being so slow and confused, I will blame having the flu. |
@ohjames nah - I appreciate your effort :) |
Okay I've added the transform stuff to the tests, hopefully should be done now! |
Oops left in |
Looks good. Just needs a quick entry in the README. Something like "opts.fileCache - an object mapping filenames to raw source to avoid reading from disk" |
Done! |
Not quite sure when I change the name of the file from
I thought it shouldn't be looking for files in the filesystem due to the |
I'm guessing that you changed Also, I just noticed that the indentation for the return block in the test's |
I changed everything to |
I think maybe line 173 also needs to be changed to use the |
Ah, so when |
I'm getting the error from |
This second commit allows |
It needed one more change and now I can also change |
Nope. That only works for files that are siblings of the requiree. I don't see a way for the resolver to use the paths from |
Ah well, guess browserify is inherently tied to the filesystem for now then. |
@ohjames I liked https://github.com/ohjames/module-deps/commit/c86adc9d16001c7e553308fc27ca2ba8991fb752 – I was already coming up with uses for it. You can pass your own resolve function into browserify/module-deps and do whatever you want in there with |
So I might be able to get a build system to interact with browserify using in-memory files only? I can remove the second commit if you think there's any use for the first one. |
Yeah. You might not even need to implement the resolver, or even wrap it. if (opts.isFile) parent.isFile = opts.isFile;
if (opts.readFile) parent.readFile = opts.readFile;
Yes please 😄 And fix the test indentation :P |
Cool I reset the second commit, I already fixed the test indentation. For some reason github won't let me "Reopen" though. |
weird. I guess just open a new PR and reference this one |
Add fileCache (copy of PR #94).
With this change I can add a cache entry for source file content without being forced to cache the deps.
If my build system already has all of the file data in memory (indeed using a streaming build system the data may not even exist on the filesystem) then it would be nice if module-deps could be told about this data so it doesn't have to read it from the filesystem.
You can do this by adding a
cache
entry, however cache entries must also contain thedeps
, the build system only has the source content not the deps. With this 10 character change the best of both worlds can be had.