Как изменить встроенные операторы require с помощью codemod (jscodeshift)?
Привет, я пытаюсь написать codemod, который перемещает мою инструкцию require из верхней части файла во внутреннюю функцию конструктора класса.
const moduleA = require('moduleA');
const moduleB = require('../moduleB');
class Example {
constructor(context) {
super(context);
this.lazy("moduleA", () => { new moduleA() }
this.lazy("moduleB", () => { new moduleB() }
}
async callThis() {
this.moduleA.callThatMethod();
}
}
Эти операторы require поверх файла занимают много времени, которое используется только в том случае, если этот API вызывается хотя бы один раз. Так как требование в любом случае кэшируется Node.js на уровне процесса. Я пытаюсь переместить
require
оператор внутри стрелочной функции.
Как ниже
class Example {
constructor(context) {
super(context);
this.lazy("moduleA", () => {
const moduleA = require('moduleA');
return new moduleA()
}
this.lazy("moduleB", () => {
const moduleB = require('../moduleB');
return new moduleB()
}
}
async callThis() {
this.moduleA.callThatMethod();
}
}
У меня проблемы с достижением этого, потому что я не знаю, как выбрать определенную "ленивую" функцию, а затем переместить верхнюю часть требования.
Любая помощь очень ценится, спасибо
1 ответ
Вам не нужен jscodeshift для такого простого преобразования. С помощью моего инструмента Putout вы можете легко удалить файлы верхнего уровня
.require
, и добавьте его в
lazy
функция:
const isTopLevel = (vars, {parentPath}) => parentPath.isProgram();
export const match = () => ({
'const moduleA = require("moduleA")': isTopLevel,
'const moduleB = require("../moduleB")': isTopLevel,
});
export const replace = () => ({
'const moduleA = require("moduleA")': '',
'const moduleB = require("../moduleB")': '',
'() => new moduleA(context)': `{
const moduleA = require("moduleA");
return new moduleA();
}`,
'() => new moduleB(context)': `{
const moduleA = require("../moduleB");
return new moduleB();
}`,
});
Если вам нужно отфильтровать
this.lazy
и иметь много разных модулей, вы можете использовать PutoutScript со значениями шаблона
__a
а также
__b
используется для определения и замены
Identifier
из
id
а также
StringLiteral
из
CallExpression
callee
внутри
VariableDeclarator
init
в
const moduleA = require('moduleA')
VariableDeclaration
:
☝️ Это то, с чем вам ДОЛЖЕН иметь дело при постоянном использовании jscodeshift .
const isTopLevel = ({parentPath}) => parentPath.isProgram();
export const match = () => ({
// filter out cases where require path contains name
'const __a = require(__b)': ({__a, __b}, path) => {
if (!isTopLevel(path))
return false;
// ☝️ __a: Identifier & {name: string}
// ☝️ __b: StringLiteral & {value: string};
return __b.value.includes(__a.name);
},
// filter out 'this.lazy'
'() => new __a(context)': ({__a}, path) => {
// ☝️ parentPath: CallExpression & {callee: MemberExpression}
return compare(path.parentPath.node.callee, 'this.lazy');
}
});
export const replace = () => ({
// remove top-level require according to 'match'-condition'
'const __a = require(__b)': '',
// insert 'require'
'() => new __a(context)': ({__a}) => {
return `() => {
const __a = require("${__a.name}");
return new __a();
}`
},
});
- ☝️ Putout на основе Babel имеет мощный декларативный API и множество встроенных преобразований .
- ☝️ Устали писать длинные рулоны кода , посмотрите сравнение преобразователей кода .