-
Notifications
You must be signed in to change notification settings - Fork 71
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
Cache is not cleared when transformer
changes
#228
Comments
This is a bug, the cache is supposed to catch rollup config changes -- the whole rollup config object is hashed and used as a part of cache key. Could you post your rollup config and what kind of change did you make? (or better yet, make a small repo with reproduction). Thanks. |
Re warning about cache use, which output message made you realize cache might be involved? Maybe I need to print it on other verbosity levels... |
Sorry for the delay in the response. Here is a simplification of the problem: import { rollup } from 'rollup';
import typescript from 'rollup-plugin-typescript2';
import ts from 'typescript';
const nodeRemover = context => {
return sourceFile => {
const visitor = (node) => {
if (ts.isImportDeclaration(node)) {
return undefined;
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(sourceFile, visitor);
};
};
const transformer = () => ({
before: [nodeRemover],
after: []
});
rollup({
input: './index.ts',
plugins: [
typescript({
transformers: [transformer]
})
]
}).then(bundle => {
bundle.write({
file: 'bundle.js'
})
})
// @ts-ignore
import { a } from './src/a';
const b = 'b';
console.log(a);
console.log(b); When modifying the transformer for this: ...
if (ts.isImportDeclaration(node) || ts.isVariableStatement(node)) {
... even the original When adding |
Same issue. I'm using Thanks to @dominguezcelada . |
Hi @ezolenko I'm interested in following up this issue as a chance to get involved in the project if possible. What do you think could be the approach to be followed here? Once agreed on that I would like to draft a PR for it :) |
Sorry for the delay, if you want to look into it, check if rollup config changes are reflected in rollup-plugin-typescript2/src/tscache.ts Lines 119 to 129 in 8ec49c7
And if they are, if they change output of
The fix might be in |
When printing the output of {
name: 'rpt2',
options: [Function: options],
watchChange: [Function: watchChange],
resolveId: [Function: resolveId],
load: [Function: load],
transform: [Function: transform],
generateBundle: [Function: generateBundle],
_ongenerate: [Function: _ongenerate],
_onwrite: [Function: _onwrite]
} Printing Details transform(code, id) {
generateRound = 0; // in watch mode transform call resets generate count (used to avoid printing too many copies of the same error messages)
if (!filter(id))
return undefined;
allImportedFiles.add(normalize(id));
const contextWrapper = new RollupContext(pluginOptions.verbosity, pluginOptions.abortOnError, this, "rpt2: ");
const snapshot = servicesHost.setSnapshot(id, code);
// getting compiled file from cache or from ts
const result = cache().getCompiled(id, snapshot, () => {
const output = service.getEmitOutput(id);
if (output.emitSkipped) {
noErrors = false;
// always checking on fatal errors, even if options.check is set to false
const diagnostics = lodash.concat(cache().getSyntacticDiagnostics(id, snapshot, () => {
return service.getSyntacticDiagnostics(id);
}), cache().getSemanticDiagnostics(id, snapshot, () => {
return service.getSemanticDiagnostics(id);
}));
printDiagnostics(contextWrapper, diagnostics, parsedConfig.options.pretty === true);
// since no output was generated, aborting compilation
cache().done();
if (lodash.isFunction(this.error))
this.error(safe.red(`failed to transpile '${id}'`));
}
const references = getAllReferences(id, servicesHost.getScriptSnapshot(id), parsedConfig.options);
return convertEmitOutput(output, references);
});
if (pluginOptions.check) {
const diagnostics = lodash.concat(cache().getSyntacticDiagnostics(id, snapshot, () => {
return service.getSyntacticDiagnostics(id);
}), cache().getSemanticDiagnostics(id, snapshot, () => {
return service.getSemanticDiagnostics(id);
}));
if (diagnostics.length > 0)
noErrors = false;
printDiagnostics(contextWrapper, diagnostics, parsedConfig.options.pretty === true);
}
if (result) {
if (result.references)
result.references.map(normalize).map(allImportedFiles.add, allImportedFiles);
if (watchMode && this.addWatchFile && result.references) {
if (tsConfigPath)
this.addWatchFile(tsConfigPath);
result.references.map(this.addWatchFile, this);
context.debug(() => `${safe.green(" watching")}: ${result.references.join("\nrpt2: ")}`);
}
if (result.dts) {
const key = normalize(id);
declarations[key] = { type: result.dts, map: result.dtsmap };
context.debug(() => `${safe.blue("generated declarations")} for '${key}'`);
}
const transformResult = { code: result.code, map: { mappings: "" } };
if (result.map) {
if (pluginOptions.sourceMapCallback)
pluginOptions.sourceMapCallback(id, result.map);
transformResult.map = JSON.parse(result.map);
}
return transformResult;
}
return undefined;
} Comparing hashes, it's always the same one so that's why udates are not getting refreshed in cache.
Printing the properties of I did a quick test hashing only
Not sure how this Before getting deeper I would like some guidance from your part if possible @ezolenko 💡 created a repo example I'm playing with just case you want to use it to do some checks: https://github.com/oscard0m/rollup-plugin-typescript2-example |
Here is a playground with |
EDIT: Hi @ezolenko, I tried to find you in social networks but I did not. I would like to get as contributor of this project so we can move this forward and even participate in other issues or plans for this plugin. Would you be open for that option? Thanks |
Hi @oscard0m , sorry that no one's responded to you for over a year 😕 😞 I also created the detailed contributing docs and one of my first major contributions was related to
This seems to 404 now 😕 . Can use the reproduction environment to make a quick repro accessible in the browser
Yeppp, reading your comments I suspected this was the problem as I had seen this behavior before when I was working on it. For instance, in that CodeSandbox, if you in-line the functions directly into So I think a bug/feature is needed in |
Ugh, yeah, github sends too many emails and notifications, pings are easily getting lost there... |
Yes! Better late than never! Thanks for going through all the existing issues @agilgur5 ❤️
I'm sorry. I did a clean-up of my personal repositories and apparently deleted this example. I have it in my local machine so here's the reproduction in stackblitz: https://stackblitz.com/edit/rpt2-repro-g7bbsj?file=README.md
Yep, the workaround is what I ended up doing but the idea would be to centralize the function and import it as many times as we want so a fix in
No problem. I can imagine how busy you are and how many notifications you can receive a day. |
Appreciate the quick response after such a long lull @oscard0m ! And your patience and politeness/respect -- it really makes a difference to maintainers who often have to deal with lots of rudeness/passive-aggressiveness/toxicity in general while volunteering their time -- like I can't overstate enough how long a way that effort goes for maintainers' wellbeing ❤️
No worries, totally understandable for links to not work after a year 😅
I investigated a decent amount and wrote about my findings there. As such, per my comment there, I think we may have a hit a "dead-end" in terms of what we might be able to expect from So I think the workaround I proposed there might be the best possible solution to move forward with: rpt2 can implement a new option, As an example, could just add What do you think @oscard0m @ezolenko ? |
@ezolenko, for reference, do you have a preferred method of contacting you? Can shoot me an email if you'd rather not disclose contact methods in the comments |
Thanks once again for the time, the energy, and for a so detailed answer here @agilgur5
Definitely, anything I can do to collaborate I will do it. I think being thankful for this project, your time, and your effort is the minimum we can do as users.
This issue popped up to me in the previous company I was working for. They had a very
As I mentioned, this issue popped up in my previous company (in May 2020). The issue was that the project was not being rebuilt when some changes were applied (all this My desire was to arrive at a solution transparent to the Your proposal implies being "conscious" of which parts can be hashed incorrectly. This can be unintuitive for users not aware of all this conversation and the implementation details of this plugin. Considering this is the most feasible solution, as you pointed, I think it makes sense to draft a PR with your proposal. My interest in contributing is not as strong as before. I'm not in the company I hit this bug with, so I'm not actively working with Would you like me to draft something and keep discussing there? |
💯 💯 💯 ❤️
I wanna say that transparent design limitations
Absolutely agreed. I think we'd all definitely prefer that. Unfortunately, I don't think we have much of any options, so I thought rather than just declaring this as blocked and unfixable, we could implement some workaround for it. Also, as that'll be an option listed in the docs, it can also act as a more of a hint to the user that the cache is not infallible (which the Related: I left another comment just now in the linked warnings
Getting back to the very opening of this issue, given our current knowledge and those comments, it might also be a good idea to output a warning when a "dynamic" option that can't be wholly cached is used, such as We could add an
Otherwise, anything else can be considered a cache invalidation bug, which, well, is known as one of the two hardest problems in Computer Science for a reason 😅 Caches are pretty ubiquitous in computing, e.g. DNS, CDNs, write buffers, L1/L2/L3 caches etc etc etc etc, and they default to "on" pretty often (and other libraries in the JS/TS ecosystem do as well), so I'm not sure this behavior is a departure from the norm in that sense, but I didn't implement the defaults to know the original rationale. It would be a de-opt for larger projects by default too, as mentioned above. The docs, contributing docs, issues, etc, do mention the cache, debug verbosity, etc, so I don't think it should be altogether that surprising to users either. There aren't altogether that many cache issues either, and I think in nearly all situations, users are aware they can use But, of course, as with most things in software engineering, there's trade-offs in either direction and I could honestly defend either as a default. contributing
Yup, totally expected that given the big gap of time, so no offense taken there.
That sounds like a plan to me! Though @ezolenko has final say, so don't want to overstep there, but I imagine this feature would be welcomed. Separately, I'm also open to a PR (or PRs) with regard to additional warnings as well. |
Cool! Let's wait for @ezolenko and I will draft-pr something then :)
Do you want me to create a new issue for this (and draft a PR for it)? @agilgur5 |
I don't think a new issue is necessary (since this issue details the rationale for more warnings). PR welcome 👍 |
I did think of a better name for this, or, at least, a shorter name: "cache key" is already mentioned in the docs for still open to better names though 😅 also cc @ezolenko still waiting on a 👍 / 👎 here on the proposal! this is the issue I was trying to bring your attention to |
@agilgur5 yeah, github is sending too many emails all of the same kind (especially lately :D), so I often miss pings here. I'll play around with notification settings to limit those to PRs and direct pings, but you can also send direct email to zolenkoe at gmail.
I think warning is not strong enough -- maybe we should disable cache completely in those cases and output a warning about that (unless user provided |
Mm that's a good point and would definitely help users avoid this kind of issue or be more aware of it since they have to opt-in if using a "dynamic" option (I believe the only two are @oscard0m think you're clear to work on this! 🙂 |
@oscard0m just wanted to check in and see if you were still working on a PR for this issue? |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as resolved.
This comment was marked as resolved.
transformer
changes
What happens and why it is wrong
Without
clean: true
option, the plugin is catching the configuration even if changes at rollup config level are done (changing the implementation of a transformer implementation for instance)Until verbosity: 3 was not set, it was not discovered cache could be an issue
Questions
clean: false
as default? It sounds like the default configuration should be without """magic""" on top right?Environment
macOS catalina v10.15.4
node 14.2.0
Versions
rollup.config.js
Not relevant
tsconfig.json
Not relevant
package.json
Not relevant
plugin output with verbosity 3
Not relevant
The text was updated successfully, but these errors were encountered: