Если ты в ноде, то можешь использовать readFileSync, хотя это и не рекомендуется.
Реплейсить в несколько проходов в любом случае - не стоит. По простому я бы сделал arr = base.split(/\{% (.*?) %\}/g) и проход через for(let i=1; i < arr.length; i+=2) { ... }.
Ну и в принципе если ты свой шаблонизатор пишешь который в теории будет усложняться, то лучше сразу без регулярок обойтись - "по взрослому" делать ast и\или конечный автомат.