Skip to content

Commit

Permalink
fix(misc): don't clear node_modules require cache (#22907)
Browse files Browse the repository at this point in the history
(cherry picked from commit 80b5514)
  • Loading branch information
AgentEnder authored and FrozenPandaz committed Apr 20, 2024
1 parent 39f8713 commit f4ea297
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 101 deletions.
19 changes: 15 additions & 4 deletions packages/devkit/src/utils/config-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dirname, extname, join } from 'path';
import { dirname, extname, join, sep } from 'path';
import { existsSync, readdirSync } from 'fs';
import { requireNx } from '../../nx';
import { pathToFileURL } from 'node:url';
Expand Down Expand Up @@ -54,15 +54,26 @@ export function getRootTsConfigFileName(): string | null {
return null;
}

const packageInstallationDirectories = [
`${sep}node_modules${sep}`,
`${sep}.yarn${sep}`,
];

export function clearRequireCache(): void {
for (const k of Object.keys(require.cache)) {
if (!packageInstallationDirectories.some((dir) => k.includes(dir))) {
delete require.cache[k];
}
}
}

/**
* Load the module after ensuring that the require cache is cleared.
*/
async function load(path: string): Promise<any> {
// Clear cache if the path is in the cache
if (require.cache[path]) {
for (const k of Object.keys(require.cache)) {
delete require.cache[k];
}
clearRequireCache();
}

try {
Expand Down
25 changes: 5 additions & 20 deletions packages/expo/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
import { existsSync, readdirSync } from 'fs';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';

export interface ExpoPluginOptions {
startTargetName?: string;
Expand Down Expand Up @@ -59,7 +60,7 @@ export const createDependencies: CreateDependencies = () => {

export const createNodes: CreateNodes<ExpoPluginOptions> = [
'**/app.{json,config.js}',
(configFilePath, options, context) => {
async (configFilePath, options, context) => {
options = normalizeOptions(options);
const projectRoot = dirname(configFilePath);

Expand All @@ -71,7 +72,7 @@ export const createNodes: CreateNodes<ExpoPluginOptions> = [
) {
return {};
}
const appConfig = getAppConfig(configFilePath, context);
const appConfig = await getAppConfig(configFilePath, context);
// if appConfig.expo is not defined
if (!appConfig.expo) {
return {};
Expand Down Expand Up @@ -152,11 +153,10 @@ function buildExpoTargets(
function getAppConfig(
configFilePath: string,
context: CreateNodesContext
): any {
): Promise<any> {
const resolvedPath = join(context.workspaceRoot, configFilePath);

let module = load(resolvedPath);
return module.default ?? module;
return loadConfigFile(resolvedPath);
}

function getInputs(
Expand All @@ -180,21 +180,6 @@ function getOutputs(projectRoot: string, dir: string) {
}
}

/**
* Load the module after ensuring that the require cache is cleared.
*/
function load(path: string): any {
// Clear cache if the path is in the cache
if (require.cache[path]) {
for (const k of Object.keys(require.cache)) {
delete require.cache[k];
}
}

// Then require
return require(path);
}

function normalizeOptions(options: ExpoPluginOptions): ExpoPluginOptions {
options ??= {};
options.startTargetName ??= 'start';
Expand Down
15 changes: 2 additions & 13 deletions packages/jest/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { existsSync, readdirSync, readFileSync } from 'fs';
import { readConfig } from 'jest-config';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { clearRequireCache } from '@nx/devkit/src/utils/config-utils';
import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json-workspaces';
import { combineGlobPatterns } from 'nx/src/utils/globs';
import { minimatch } from 'minimatch';
Expand Down Expand Up @@ -109,12 +110,6 @@ export const createNodes: CreateNodes<JestPluginOptions> = [
},
];

const jestValidatePath = dirname(
require.resolve('jest-validate/package.json', {
paths: [dirname(require.resolve('jest-config'))],
})
);

async function buildJestTargets(
configFilePath: string,
projectRoot: string,
Expand All @@ -124,13 +119,7 @@ async function buildJestTargets(
const absConfigFilePath = resolve(context.workspaceRoot, configFilePath);

if (require.cache[absConfigFilePath]) {
for (const k of Object.keys(require.cache)) {
// Only delete the cache outside of jest-validate
// jest-validate has a Symbol which is important for jest config validation which breaks if the require cache is broken
if (relative(jestValidatePath, k).startsWith('../')) {
delete require.cache[k];
}
}
clearRequireCache();
}

const config = await readConfig(
Expand Down
44 changes: 3 additions & 41 deletions packages/next/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { existsSync, readdirSync } from 'fs';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { getLockFileName } from '@nx/js';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';

export interface NextPluginOptions {
buildTargetName?: string;
Expand Down Expand Up @@ -194,19 +195,13 @@ async function getOutputs(projectRoot, nextConfig) {
}
}

async function getNextConfig(
function getNextConfig(
configFilePath: string,
context: CreateNodesContext
): Promise<any> {
const resolvedPath = join(context.workspaceRoot, configFilePath);

let module;
if (extname(configFilePath) === '.mjs') {
module = await loadEsmModule(resolvedPath);
} else {
module = load(resolvedPath);
}
return module.default ?? module;
return loadConfigFile(resolvedPath);
}

function normalizeOptions(options: NextPluginOptions): NextPluginOptions {
Expand All @@ -230,36 +225,3 @@ function getInputs(
},
];
}

const packageInstallationDirectories = ['node_modules', '.yarn'];
/**
* Load the module after ensuring that the require cache is cleared.
*/
function load(path: string): any {
// Clear cache if the path is in the cache
if (require.cache[path]) {
for (const key of Object.keys(require.cache)) {
if (!packageInstallationDirectories.some((dir) => key.includes(dir))) {
delete require.cache[key];
}
}
}

// Then require
return require(path);
}

/**
* Lazily compiled dynamic import loader function.
*/
let dynamicLoad: (<T>(modulePath: string | URL) => Promise<T>) | undefined;

export function loadEsmModule<T>(modulePath: string | URL): Promise<T> {
const modulePathWithCacheBust = `${modulePath}?version=${Date.now()}`;
dynamicLoad ??= new Function(
'modulePath',
`return import(modulePath);`
) as Exclude<typeof dynamicLoad, undefined>;

return dynamicLoad(modulePathWithCacheBust);
}
25 changes: 5 additions & 20 deletions packages/react-native/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
import { existsSync, readdirSync } from 'fs';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';

export interface ReactNativePluginOptions {
startTargetName?: string;
Expand Down Expand Up @@ -59,7 +60,7 @@ export const createDependencies: CreateDependencies = () => {

export const createNodes: CreateNodes<ReactNativePluginOptions> = [
'**/app.{json,config.js}',
(configFilePath, options, context) => {
async (configFilePath, options, context) => {
options = normalizeOptions(options);
const projectRoot = dirname(configFilePath);

Expand All @@ -71,7 +72,7 @@ export const createNodes: CreateNodes<ReactNativePluginOptions> = [
) {
return {};
}
const appConfig = getAppConfig(configFilePath, context);
const appConfig = await getAppConfig(configFilePath, context);
if (appConfig.expo) {
return {};
}
Expand Down Expand Up @@ -164,11 +165,10 @@ function buildReactNativeTargets(
function getAppConfig(
configFilePath: string,
context: CreateNodesContext
): any {
): Promise<any> {
const resolvedPath = join(context.workspaceRoot, configFilePath);

let module = load(resolvedPath);
return module.default ?? module;
return loadConfigFile(resolvedPath);
}

function getInputs(
Expand All @@ -192,21 +192,6 @@ function getOutputs(projectRoot: string, dir: string) {
}
}

/**
* Load the module after ensuring that the require cache is cleared.
*/
function load(path: string): any {
// Clear cache if the path is in the cache
if (require.cache[path]) {
for (const k of Object.keys(require.cache)) {
delete require.cache[k];
}
}

// Then require
return require(path);
}

function normalizeOptions(
options: ReactNativePluginOptions
): ReactNativePluginOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { registerTsProject } from '@nx/js/src/internal';
import { clearRequireCache } from '@nx/devkit/src/utils/config-utils';

export function resolveUserDefinedWebpackConfig(
path: string,
Expand All @@ -10,9 +11,7 @@ export function resolveUserDefinedWebpackConfig(
// Clear cache if the path is in the cache
if (require.cache[path]) {
// Clear all entries because config may import other modules
for (const k of Object.keys(require.cache)) {
delete require.cache[k];
}
clearRequireCache();
}
}

Expand Down

0 comments on commit f4ea297

Please sign in to comment.