Мой код выполняет const cfg = require('./config')
, так что либо config.js
, либо config.json
будет прочитано. В целом это работает отлично. Проблема, с которой я сталкиваюсь, заключается во время тестирования.
Код тестирования повторяется на следующих этапах:
- очистить требуемый кэш для
require.resolve('./config.json')
- write
config.json
с данными для проверки - проверить код, содержащий
const cfg = require('./config')
Все выше работает нормально. Проблема возникает, когда тест пытается проверить, что config.js
также работает.
- очистить требуемый кеш для
require.resolve('./config.json')
- delete
config.json
- написать
config.js
- проверить код, содержащий
const cfg = require('./config')
Попытка чтения config.js
через require('./config')
не удалась, поскольку require.resolve('./config')
все еще разрешается в файл .json
которого больше не существует.
Поведение может быть объяснено тем, что каталог где-то кэшируется, поэтому запись config.js
не отражается в поиске по запросу узла. Но это всего лишь предположение.
Изменение порядка проверок так, чтобы сначала выполнялись .js
тесты, а затем результаты .json
с той же проблемой, но в обратном порядке.
поведение одинаково на версиях узла 6+;Я не проверял более ранние версии.
Как можно сделать так, чтобы узел возвращал экспорт файла .js
в этом сценарии?
Следующая проблема иллюстрирует следующее. Указав расширение в операторе require (измените const withExt = false
на true
), оно выполнится успешно.
'use strict'
/* eslint-disable no-console */
const fs = require('fs');
const fullConfigName = `${process.cwd()}/xyzzy`;
function cleanup (ext) {
// remove any files created with the default names
try {fs.unlinkSync(`${fullConfigName}.${ext}`)} catch (e) {
console.log(`failed to cleanup ${ext}`, e.code || e.message);
}
// clear the require cache
delete require.cache[`${fullConfigName}.${ext}`];
}
function writeFile (extension) {
let config;
if (extension === 'json') {
config = JSON.stringify({some: 'i was json'}) + '\n';
} else {
config = 'module.exports = {someSetting: "i was a module"}\n'
}
fs.writeFileSync(`${fullConfigName}.${extension}`, config, 'utf8');
}
function main () {
cleanup('js');
cleanup('json');
//const configName = fullConfigName;
const configName = './xyzzy';
const withExt = false;
const exts = false ? ['json', 'js'] : ['js', 'json'];
exts.forEach(ext => {
const extPart = withExt ? `.${ext}` : '';
console.log(`writing ${configName}.${ext}`);
writeFile(ext);
const fileToRequire = `${configName}${extPart}`;
console.log(`requiring ${fileToRequire}`);
const resolved = require.resolve(fileToRequire);
console.log(`require.resolve result ${resolved}`);
try {
const contents = require(`${fileToRequire}`);
console.log('contents', contents);
} catch (e) {
console.log('require failed', e.code || e.message);
}
console.log(module.children.map(c => {
return {
id: c.id,
exports: c.exports,
filename: c.filename,
loaded: c.loaded,
}
}));
const cache = Object.keys(require.cache).filter(k => true || k.startsWith(fullConfigName));
console.log('cache:', cache);
console.log(`${ext} - cleanup`);
cleanup(ext);
})
}
main ()