Как заменить whereHas, ибо он слишком медленный?
whereHas делает обычный exists. Он даже и близко не медленный. Проблема в отсутствии индексов (на categories.name и в колонках, связывающих две таблицы).
Если подумать, то лучше два простых и быстрых запросов чем один тяжелый.
В любом случае я думаю категория/ии вам в шаблоне отдельно все равно где-то понадобятся, значит можно сначала получить ее/их по имени, а затем получить статьи$categories = Category::whereName($name)->get();
$articles = Article:with('types')->whereIn('id', $categories->pluck('id'))->paginate(10);
Если же вы настаиваете на одном запросе, вам придется использовать Join-ы,  что также плохо скажется на производительности