mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 00:20:08 +01:00
module: fix directory option in the enableCompileCache() API
The option name should be `directory` to be consistent with the returned result. It should also allow environment variable overrides. This also adds documentation for the new options and improves it. PR-URL: https://github.com/nodejs/node/pull/59931 Reviewed-By: Aditi Singh <aditisingh1400@gmail.com>
This commit is contained in:
parent
f8a43f6f34
commit
db0121bedd
|
|
@ -385,8 +385,8 @@ changes:
|
|||
|
||||
The module compile cache can be enabled either using the [`module.enableCompileCache()`][]
|
||||
method or the [`NODE_COMPILE_CACHE=dir`][] environment variable. After it is enabled,
|
||||
whenever Node.js compiles a CommonJS or a ECMAScript Module, it will use on-disk
|
||||
[V8 code cache][] persisted in the specified directory to speed up the compilation.
|
||||
whenever Node.js compiles a CommonJS, a ECMAScript Module, or a TypeScript module, it will
|
||||
use on-disk [V8 code cache][] persisted in the specified directory to speed up the compilation.
|
||||
This may slow down the first load of a module graph, but subsequent loads of the same module
|
||||
graph may get a significant speedup if the contents of the modules do not change.
|
||||
|
||||
|
|
@ -394,11 +394,24 @@ To clean up the generated compile cache on disk, simply remove the cache directo
|
|||
directory will be recreated the next time the same directory is used for for compile cache
|
||||
storage. To avoid filling up the disk with stale cache, it is recommended to use a directory
|
||||
under the [`os.tmpdir()`][]. If the compile cache is enabled by a call to
|
||||
[`module.enableCompileCache()`][] without specifying the directory, Node.js will use
|
||||
[`module.enableCompileCache()`][] without specifying the `directory`, Node.js will use
|
||||
the [`NODE_COMPILE_CACHE=dir`][] environment variable if it's set, or defaults
|
||||
to `path.join(os.tmpdir(), 'node-compile-cache')` otherwise. To locate the compile cache
|
||||
directory used by a running Node.js instance, use [`module.getCompileCacheDir()`][].
|
||||
|
||||
The enabled module compile cache can be disabled by the [`NODE_DISABLE_COMPILE_CACHE=1`][]
|
||||
environment variable. This can be useful when the compile cache leads to unexpected or
|
||||
undesired behaviors (e.g. less precise test coverage).
|
||||
|
||||
At the moment, when the compile cache is enabled and a module is loaded afresh, the
|
||||
code cache is generated from the compiled code immediately, but will only be written
|
||||
to disk when the Node.js instance is about to exit. This is subject to change. The
|
||||
[`module.flushCompileCache()`][] method can be used to ensure the accumulated code cache
|
||||
is flushed to disk in case the application wants to spawn other Node.js instances
|
||||
and let them share the cache long before the parent exits.
|
||||
|
||||
### Portability of the compile cache
|
||||
|
||||
By default, caches are invalidated when the absolute paths of the modules being
|
||||
cached are changed. To keep the cache working after moving the
|
||||
project directory, enable portable compile cache. This allows previously compiled
|
||||
|
|
@ -409,38 +422,29 @@ will not be cached.
|
|||
|
||||
There are two ways to enable the portable mode:
|
||||
|
||||
1. Using the portable option in module.enableCompileCache():
|
||||
1. Using the portable option in [`module.enableCompileCache()`][]:
|
||||
|
||||
```js
|
||||
// Non-portable cache (default): cache breaks if project is moved
|
||||
module.enableCompileCache({ path: '/path/to/cache/storage/dir' });
|
||||
module.enableCompileCache({ directory: '/path/to/cache/storage/dir' });
|
||||
|
||||
// Portable cache: cache works after the project is moved
|
||||
module.enableCompileCache({ path: '/path/to/cache/storage/dir', portable: true });
|
||||
module.enableCompileCache({ directory: '/path/to/cache/storage/dir', portable: true });
|
||||
```
|
||||
|
||||
2. Setting the environment variable: [`NODE_COMPILE_CACHE_PORTABLE=1`][]
|
||||
|
||||
### Limitations of the compile cache
|
||||
|
||||
Currently when using the compile cache with [V8 JavaScript code coverage][], the
|
||||
coverage being collected by V8 may be less precise in functions that are
|
||||
deserialized from the code cache. It's recommended to turn this off when
|
||||
running tests to generate precise coverage.
|
||||
|
||||
The enabled module compile cache can be disabled by the [`NODE_DISABLE_COMPILE_CACHE=1`][]
|
||||
environment variable. This can be useful when the compile cache leads to unexpected or
|
||||
undesired behaviors (e.g. less precise test coverage).
|
||||
|
||||
Compilation cache generated by one version of Node.js can not be reused by a different
|
||||
version of Node.js. Cache generated by different versions of Node.js will be stored
|
||||
separately if the same base directory is used to persist the cache, so they can co-exist.
|
||||
|
||||
At the moment, when the compile cache is enabled and a module is loaded afresh, the
|
||||
code cache is generated from the compiled code immediately, but will only be written
|
||||
to disk when the Node.js instance is about to exit. This is subject to change. The
|
||||
[`module.flushCompileCache()`][] method can be used to ensure the accumulated code cache
|
||||
is flushed to disk in case the application wants to spawn other Node.js instances
|
||||
and let them share the cache long before the parent exits.
|
||||
|
||||
### `module.constants.compileCacheStatus`
|
||||
|
||||
<!-- YAML
|
||||
|
|
@ -494,16 +498,30 @@ The following constants are returned as the `status` field in the object returne
|
|||
</tr>
|
||||
</table>
|
||||
|
||||
### `module.enableCompileCache([cacheDir])`
|
||||
### `module.enableCompileCache([options])`
|
||||
|
||||
<!-- YAML
|
||||
added: v22.8.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/58797
|
||||
description: Add `portable` option to enable portable compile cache.
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/59931
|
||||
description: Rename the unreleased `path` option to `directory` to maintain consistency.
|
||||
-->
|
||||
|
||||
> Stability: 1.1 - Active Development
|
||||
|
||||
* `cacheDir` {string|undefined} Optional path to specify the directory where the compile cache
|
||||
will be stored/retrieved.
|
||||
* `options` {string|Object} Optional. If a string is passed, it is considered to be `options.directory`.
|
||||
* `directory` {string} Optional. Directory to store the compile cache. If not specified,
|
||||
the directory specified by the [`NODE_COMPILE_CACHE=dir`][] environment variable
|
||||
will be used if it's set, or `path.join(os.tmpdir(), 'node-compile-cache')`
|
||||
otherwise.
|
||||
* `portable` {boolean} Optional. If `true`, enables portable compile cache so that
|
||||
the cache can be reused even if the project directory is moved. This is a best-effort
|
||||
feature. If not specified, it will depend on whether the environment variable
|
||||
[`NODE_COMPILE_CACHE_PORTABLE=1`][] is set.
|
||||
* Returns: {Object}
|
||||
* `status` {integer} One of the [`module.constants.compileCacheStatus`][]
|
||||
* `message` {string|undefined} If Node.js cannot enable the compile cache, this contains
|
||||
|
|
@ -515,20 +533,16 @@ added: v22.8.0
|
|||
|
||||
Enable [module compile cache][] in the current Node.js instance.
|
||||
|
||||
If `cacheDir` is not specified, Node.js will either use the directory specified by the
|
||||
[`NODE_COMPILE_CACHE=dir`][] environment variable if it's set, or use
|
||||
`path.join(os.tmpdir(), 'node-compile-cache')` otherwise. For general use cases, it's
|
||||
recommended to call `module.enableCompileCache()` without specifying the `cacheDir`,
|
||||
so that the directory can be overridden by the `NODE_COMPILE_CACHE` environment
|
||||
variable when necessary.
|
||||
For general use cases, it's recommended to call `module.enableCompileCache()` without
|
||||
specifying the `options.directory`, so that the directory can be overridden by the
|
||||
`NODE_COMPILE_CACHE` environment variable when necessary.
|
||||
|
||||
Since compile cache is supposed to be a quiet optimization that is not required for the
|
||||
application to be functional, this method is designed to not throw any exception when the
|
||||
compile cache cannot be enabled. Instead, it will return an object containing an error
|
||||
message in the `message` field to aid debugging.
|
||||
If compile cache is enabled successfully, the `directory` field in the returned object
|
||||
contains the path to the directory where the compile cache is stored. The `status`
|
||||
field in the returned object would be one of the `module.constants.compileCacheStatus`
|
||||
Since compile cache is supposed to be a optimization that is not mission critical, this
|
||||
method is designed to not throw any exception when the compile cache cannot be enabled.
|
||||
Instead, it will return an object containing an error message in the `message` field to
|
||||
aid debugging. If compile cache is enabled successfully, the `directory` field in the
|
||||
returned object contains the path to the directory where the compile cache is stored. The
|
||||
`status` field in the returned object would be one of the `module.constants.compileCacheStatus`
|
||||
values to indicate the result of the attempt to enable the [module compile cache][].
|
||||
|
||||
This method only affects the current Node.js instance. To enable it in child worker threads,
|
||||
|
|
@ -1817,7 +1831,7 @@ returned object contains the following keys:
|
|||
[`SourceMap`]: #class-modulesourcemap
|
||||
[`initialize`]: #initialize
|
||||
[`module.constants.compileCacheStatus`]: #moduleconstantscompilecachestatus
|
||||
[`module.enableCompileCache()`]: #moduleenablecompilecachecachedir
|
||||
[`module.enableCompileCache()`]: #moduleenablecompilecacheoptions
|
||||
[`module.flushCompileCache()`]: #moduleflushcompilecache
|
||||
[`module.getCompileCacheDir()`]: #modulegetcompilecachedir
|
||||
[`module.setSourceMapsSupport()`]: #modulesetsourcemapssupportenabled-options
|
||||
|
|
|
|||
|
|
@ -405,28 +405,32 @@ function stringify(body) {
|
|||
* Enable on-disk compiled cache for all user modules being compiled in the current Node.js instance
|
||||
* after this method is called.
|
||||
* This method accepts either:
|
||||
* - A string `cacheDir`: the path to the cache directory.
|
||||
* - An options object `{path?: string, portable?: boolean}`:
|
||||
* - `path`: A string path to the cache directory.
|
||||
* - `portable`: If `portable` is true, the cache directory will be considered relative. Defaults to false.
|
||||
* If cache path is undefined, it defaults to the NODE_MODULE_CACHE environment variable.
|
||||
* If `NODE_MODULE_CACHE` isn't set, it defaults to `path.join(os.tmpdir(), 'node-compile-cache')`.
|
||||
* @param {string | { path?: string, portable?: boolean } | undefined} options
|
||||
* - A string: path to the cache directory.
|
||||
* - An options object `{directory?: string, portable?: boolean}`:
|
||||
* - `directory`: A string path to the cache directory.
|
||||
* - `portable`: If `portable` is true, the cache directory will be considered relative.
|
||||
* Defaults to `NODE_COMPILE_CACHE_PORTABLE === '1'`.
|
||||
* If cache directory is undefined, it defaults to the `NODE_COMPILE_CACHE` environment variable.
|
||||
* If `NODE_COMPILE_CACHE` isn't set, it defaults to `path.join(os.tmpdir(), 'node-compile-cache')`.
|
||||
* @param {string | { directory?: string, portable?: boolean } | undefined} options
|
||||
* @returns {{status: number, message?: string, directory?: string}}
|
||||
*/
|
||||
function enableCompileCache(options) {
|
||||
let cacheDir;
|
||||
let portable = false;
|
||||
let portable;
|
||||
let directory;
|
||||
|
||||
if (typeof options === 'object' && options !== null) {
|
||||
({ path: cacheDir, portable = false } = options);
|
||||
({ directory, portable } = options);
|
||||
} else {
|
||||
cacheDir = options;
|
||||
directory = options;
|
||||
}
|
||||
if (cacheDir === undefined) {
|
||||
cacheDir = join(lazyTmpdir(), 'node-compile-cache');
|
||||
if (directory === undefined) {
|
||||
directory = process.env.NODE_COMPILE_CACHE || join(lazyTmpdir(), 'node-compile-cache');
|
||||
}
|
||||
const nativeResult = _enableCompileCache(cacheDir, portable);
|
||||
if (portable === undefined) {
|
||||
portable = process.env.NODE_COMPILE_CACHE_PORTABLE === '1';
|
||||
}
|
||||
const nativeResult = _enableCompileCache(directory, portable);
|
||||
const result = { status: nativeResult[0] };
|
||||
if (nativeResult[1]) {
|
||||
result.message = nativeResult[1];
|
||||
|
|
|
|||
23
test/fixtures/compile-cache-wrapper-options.js
vendored
Normal file
23
test/fixtures/compile-cache-wrapper-options.js
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
const { enableCompileCache, getCompileCacheDir, constants } = require('module');
|
||||
|
||||
console.log('dir before enableCompileCache:', getCompileCacheDir());
|
||||
const options = JSON.parse(process.env.NODE_TEST_COMPILE_CACHE_OPTIONS);
|
||||
console.log('options:', options);
|
||||
const result = enableCompileCache(options);
|
||||
switch (result.status) {
|
||||
case constants.compileCacheStatus.FAILED:
|
||||
console.log('Compile cache failed. ' + result.message);
|
||||
break;
|
||||
case constants.compileCacheStatus.ENABLED:
|
||||
console.log('Compile cache enabled. ' + result.directory);
|
||||
break;
|
||||
case constants.compileCacheStatus.ALREADY_ENABLED:
|
||||
console.log('Compile cache already enabled.');
|
||||
break;
|
||||
case constants.compileCacheStatus.DISABLED:
|
||||
console.log('Compile cache already disabled.');
|
||||
break;
|
||||
}
|
||||
console.log('dir after enableCompileCache:', getCompileCacheDir());
|
||||
89
test/parallel/test-compile-cache-api-options-portable-env.js
Normal file
89
test/parallel/test-compile-cache-api-options-portable-env.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
'use strict';
|
||||
|
||||
// This tests module.enableCompileCache() with an options object still works with environment
|
||||
// variable NODE_COMPILE_CACHE overrides.
|
||||
|
||||
require('../common');
|
||||
const { spawnSyncAndAssert } = require('../common/child_process');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const wrapper = fixtures.path('compile-cache-wrapper-options.js');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Create a build directory and copy the entry point file.
|
||||
const buildDir = tmpdir.resolve('build');
|
||||
fs.mkdirSync(buildDir);
|
||||
const entryPoint = path.join(buildDir, 'empty.js');
|
||||
fs.copyFileSync(fixtures.path('empty.js'), entryPoint);
|
||||
|
||||
// Check that the portable option can be overridden by NODE_COMPILE_CACHE_PORTABLE.
|
||||
// We don't override NODE_COMPILE_CACHE because it will enable the cache before
|
||||
// the wrapper is loaded.
|
||||
spawnSyncAndAssert(
|
||||
process.execPath,
|
||||
['-r', wrapper, entryPoint],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
|
||||
NODE_COMPILE_CACHE_PORTABLE: '1',
|
||||
NODE_TEST_COMPILE_CACHE_OPTIONS: JSON.stringify({ directory: 'build/.compile_cache' }),
|
||||
},
|
||||
cwd: tmpdir.path
|
||||
},
|
||||
{
|
||||
stdout(output) {
|
||||
console.log(output); // Logging for debugging.
|
||||
assert.match(output, /dir before enableCompileCache: undefined/);
|
||||
assert.match(output, /Compile cache enabled/);
|
||||
assert.match(output, /dir after enableCompileCache: .*build[/\\]\.compile_cache/);
|
||||
return true;
|
||||
},
|
||||
stderr(output) {
|
||||
console.log(output); // Logging for debugging.
|
||||
assert.match(output, /reading cache from .*build[/\\]\.compile_cache.* for CommonJS .*empty\.js/);
|
||||
assert.match(output, /empty\.js was not initialized, initializing the in-memory entry/);
|
||||
assert.match(output, /writing cache for .*empty\.js.*success/);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
assert(fs.existsSync(tmpdir.resolve('build/.compile_cache')));
|
||||
|
||||
const movedDir = buildDir + '_moved';
|
||||
fs.renameSync(buildDir, movedDir);
|
||||
const movedEntryPoint = path.join(movedDir, 'empty.js');
|
||||
|
||||
// When portable is undefined, it should use the env var NODE_COMPILE_CACHE_PORTABLE.
|
||||
spawnSyncAndAssert(
|
||||
process.execPath,
|
||||
['-r', wrapper, movedEntryPoint],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
|
||||
NODE_COMPILE_CACHE_PORTABLE: '1',
|
||||
NODE_TEST_COMPILE_CACHE_OPTIONS: JSON.stringify({ directory: 'build_moved/.compile_cache' }),
|
||||
},
|
||||
cwd: tmpdir.path
|
||||
},
|
||||
{
|
||||
stdout(output) {
|
||||
console.log(output); // Logging for debugging.
|
||||
assert.match(output, /dir before enableCompileCache: undefined/);
|
||||
assert.match(output, /Compile cache enabled/);
|
||||
assert.match(output, /dir after enableCompileCache: .*build_moved[/\\]\.compile_cache/);
|
||||
return true;
|
||||
},
|
||||
stderr(output) {
|
||||
console.log(output); // Logging for debugging.
|
||||
assert.match(output, /reading cache from .*build_moved[/\\]\.compile_cache.* for CommonJS .*empty\.js/);
|
||||
assert.match(output, /cache for .*empty\.js was accepted, keeping the in-memory entry/);
|
||||
assert.match(output, /.*skip .*empty\.js because cache was the same/);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
// This tests module.enableCompileCache({ path, portable: true }) works
|
||||
// This tests module.enableCompileCache({ directory, portable: true }) works
|
||||
// and supports portable paths across directory relocations.
|
||||
|
||||
require('../common');
|
||||
|
|
@ -9,26 +9,18 @@ const assert = require('assert');
|
|||
const fs = require('fs');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const path = require('path');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
tmpdir.refresh();
|
||||
const workDir = path.join(tmpdir.path, 'work');
|
||||
const cacheRel = '.compile_cache_dir';
|
||||
fs.mkdirSync(workDir, { recursive: true });
|
||||
|
||||
const wrapper = path.join(workDir, 'wrapper.js');
|
||||
const wrapper = fixtures.path('compile-cache-wrapper-options.js');
|
||||
const target = path.join(workDir, 'target.js');
|
||||
|
||||
fs.writeFileSync(
|
||||
wrapper,
|
||||
`
|
||||
const { enableCompileCache, getCompileCacheDir } = require('module');
|
||||
console.log('dir before enableCompileCache:', getCompileCacheDir());
|
||||
enableCompileCache({ path: '${cacheRel}', portable: true });
|
||||
console.log('dir after enableCompileCache:', getCompileCacheDir());
|
||||
`
|
||||
);
|
||||
|
||||
fs.writeFileSync(target, '');
|
||||
const NODE_TEST_COMPILE_CACHE_OPTIONS = JSON.stringify({ directory: cacheRel, portable: true });
|
||||
|
||||
// First run
|
||||
{
|
||||
|
|
@ -39,6 +31,7 @@ fs.writeFileSync(target, '');
|
|||
env: {
|
||||
...process.env,
|
||||
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
|
||||
NODE_TEST_COMPILE_CACHE_OPTIONS,
|
||||
},
|
||||
cwd: workDir,
|
||||
},
|
||||
|
|
@ -73,13 +66,14 @@ fs.writeFileSync(target, '');
|
|||
process.execPath,
|
||||
[
|
||||
'-r',
|
||||
path.join(movedWorkDir, 'wrapper.js'),
|
||||
wrapper,
|
||||
path.join(movedWorkDir, 'target.js'),
|
||||
],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
|
||||
NODE_TEST_COMPILE_CACHE_OPTIONS,
|
||||
},
|
||||
cwd: movedWorkDir,
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user