Skip to content

Caching issues (leading to Webpack crashing or component templates not being picked up) #1619

Description

@chancancode

Setup

  1. ember new --embroider --yarn zomg (yarn optional)
  2. JOBS=0 ember s (JOBS=0 optional, but may get better stack traces/easier to step through the code without the workers)

Scenario 1

  1. touch app/components/foo.hbs
  2. observe it rebuilds successfully
  3. observe that .../rewritten-app/components/foo.hbs exists (as expected)
  4. observe that .../rewritten-app/components/foo.js exists (in addition to foo.hbs)
  5. observe that .../rewritten-app/assets/zomg.js has an entry for components/foo.js
  6. rm app/components/foo.hbs
  7. observe that the build crashes
  8. observe that .../rewritten-app/components/foo.hbs does not exists (as expected)
  9. observe that .../rewritten-app/components/foo.js exists (unexpected)
  10. observe that .../rewritten-app/assets/zomg.js has an entry for components/foo.js (unexpected)

The problem here is that the code the reflects the FS changes (deletion, in this case) into rewritten-app, in response to a sole .hbs file being deleted, should have also deleted the "virtual" js file (which it added in the first place), but did not.

While it is hard to "see" (not sure if there is a way to get the babel output written to disk), but because of the content-based caching (see the scenario below), the babel-transformed output of the leftover foo.js has a reference to foo.hbs, leading to the crash.

Scenario 2

(This scenario is to illustrate an independent issue to the previous one, so make sure you git reset the changes, restart the server, etc, to being from a fresh state)

  1. create app/components/foo.js with the following content:
    import Component from "@ember/component";
    export default Component.extend({ tagName: "span" });
  2. observe it rebuilds successfully
  3. observe that the expected files and entries are present in rewritten-app
  4. observe that if you invoke the component (from application.hbs) it renders an empty span in the browser
  5. create app/components/foo.hbs with any non-empty content (e.g. hello world!)
  6. observe it rebuilds successfully
  7. observe that the expected files and entries are present in rewritten-app
  8. observe that if you invoke the component it renders an empty span without the template's content (unexpected)
  9. edit the component js file to have tagName: "p"
  10. observe it rebuilds successfully
  11. observe that if you invoke the component it does render an p tag with the template's content (as expected)

I believe the issue is the babel transform for the co-located components plug-in only gets re-run solely if (and only if) the content of the .js file changes, which is semantically incorrect. The presence or absence of the adjacent .hbs file should effectively be part of the logical cache key.

Notably, simply touching the mtime of the .js file (either in the actual app, or in the rewritten-app) is not sufficient.

Scenario 3

I added this one later, and I think fundamentally it is just a variant of Scenario 2, but this results in a persistent crash, which shows that the content-based caching behavior survives rebuilds.

  1. before starting the server, create app/components/foo.js and app/components/foo.hbs, the content doesn't matter
  2. start the server
  3. observe that it builds successfully
  4. delete app/components/foo.hbs
  5. observes that the build crashes
  6. exit the server
  7. start the server again
  8. observe that the build is still crashing

You can fix the build by making any content changes to the .js file. However, if you then revert to the previous content at any later time, so long as the underlying cache entry hasn't been evicted yet, it will bring back the crash! So effectively that exact filename-content pair is semi-permanently poisoned to expect a corresponding .hbs file. Fun!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions