Skip to content

Commit

Permalink
Rerun macros babel plugins if dependencies change
Browse files Browse the repository at this point in the history
dependencySatisfies can become invalid if babel caches the macros
plugin + the dependency that is being checked for changes its package
version. This adds a cache busting plugin that tracks a hash of the
contents of the apps lock file so any changes to dependencies will
bust the cache.

Fixes: #906
  • Loading branch information
thoov committed Jul 29, 2021
1 parent 95fab94 commit 0b0d836
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/macros/src/babel-plugin-cache-busting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function makePlugin(): any {
return {};
}
26 changes: 26 additions & 0 deletions packages/macros/src/ember-addon-main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fs from 'fs';
import { join } from 'path';
import crypto from 'crypto';
import { MacrosConfig, isEmbroiderMacrosPlugin } from './node';

export = {
Expand Down Expand Up @@ -70,6 +72,30 @@ export = {
let appInstance = this._findHost();
let source = appOrAddonInstance.root || appOrAddonInstance.project.root;
babelPlugins.unshift(MacrosConfig.for(appInstance).babelPluginConfig(source));

let yarnLockPath = join(appInstance.project.root, 'yarn.lock');
let npmLockPath = join(appInstance.project.root, 'package-lock.json');
let packagePath = join(appInstance.project.root, 'package.json');
let lockFileBuffer;

if (fs.existsSync(yarnLockPath)) {
lockFileBuffer = fs.readFileSync(yarnLockPath);
} else if (fs.existsSync(npmLockPath)) {
lockFileBuffer = fs.readFileSync(npmLockPath);
} else {
// no lock file found, using package.json as a fall back
lockFileBuffer = fs.readFileSync(packagePath);
}

// @embroider/macros provides a macro called dependencySatisfies which checks if a given
// package name satisfies a given semver version range. Due to the way babel caches this can
// cause a problem where the macro plugin does not run (because it has been cached) but the version
// of the dependency being checked for changes (due to installing a different version). This will lead to
// the old evaluated state being used which might be invalid. This cache busting plugin keeps track of a
// hash representing the lock file of the app and if it ever changes forces babel to rerun its plugins.
// more information in issue #906
let cacheKey = crypto.createHash('sha256').update(lockFileBuffer).digest('hex');
babelPlugins.push([require.resolve('./babel-plugin-cache-busting'), { version: cacheKey }]);
}
},

Expand Down

0 comments on commit 0b0d836

Please sign in to comment.