In realtà c'è una ragione storica più che tecnologica. In origine i web services si programmavano in C, Pascal o C++. Ed erano serviti tramite CGI.
Ma i linguaggi compilati dell'epoca non era produttivi e semplici da usare, come i linguaggi interpretati tipo Perl, che fu il primo linguaggio interpretato ad essere usato per questo tipo di attività.
Successivamente però nacque il filone dei linguaggi basati su virtual machine e bytecode. Nel tempo sono diventati sempre meno interpretati e più compilati jit. Java per esempio.
Mentre i linguaggi compilati non si sono di fatto evoluti, almeno fino all'arrivo di Go e Rust. E fai caso che proprio Go sta mangiando la torta di Node.js, PHP e pure Java EE.
Comunque sia, sia i linguaggi interpretati che basati su vm, hanno due caratteristiche: (1) semplicità della sintassi e un potente e ricco modello di programmazione, il che semplifica la vita del programmatore, (2) un meccanismo per controllare il ciclo di vita delle variabili, il che aiuta a ridurre il numero di bug.
Siccome sul web i bug sono spesso esposti al mondo, è un bel vantaggio. Stessa cosa per i tempi di sviluppo, che più sono corti e meglio è.
E poi c'è un'altra ragione storica, ovvero il costo e il tempo della compilazione. Negli anni '80 e '90 non era difficile che capitasse di modificare uno script direttamente sul server. Chiaramente, senza compilazione, si risparmiava tempo nella modifica del codice e relativo testing. E non si appesantiva il server. Un pò come oggi si preferisce l'hot reloading.