No, for example the mentioned AET module is mainly targeted to render entities via the token filter in the body field of other entities. Then the render
method is more appropriate to bubble up the metadata and also not to replace placeholders too early. But this not perfect, either.
You find a better example in the core media embed filter, where in a token you would merge with $bubbleable_metadata
:
\Drupal\media\Plugin\Filter\MediaEmbed::renderIntoDomNode()
/**
* Renders the given render array into the given DOM node.
*
* @param array $build
* The render array to render in isolation.
* @param \DOMNode $node
* The DOM node to render into.
* @param \Drupal\filter\FilterProcessResult $result
* The accumulated result of filter processing, updated with the metadata
* bubbled during rendering.
*/
protected function renderIntoDomNode(array $build, \DOMNode $node, FilterProcessResult &$result) {
// We need to render the embedded entity:
// - without replacing placeholders, so that the placeholders are
// only replaced at the last possible moment. Hence we cannot use
// either renderPlain() or renderRoot(), so we must use render().
// - without bubbling beyond this filter, because filters must
// ensure that the bubbleable metadata for the changes they make
// when filtering text makes it onto the FilterProcessResult
// object that they return ($result). To prevent that bubbling, we
// must wrap the call to render() in a render context.
$markup = $this->renderer->executeInRenderContext(new RenderContext(), function () use (&$build) {
return $this->renderer->render($build);
});
$result = $result->merge(BubbleableMetadata::createFromRenderArray($build));
static::replaceNodeContent($node, $markup);
}