If you are willing to use only a subset of the language (excluding all those symbols defined in top-level code), you may use the undocumented '-runfirst' switch. In Windows:
PS C:\Users\Glenn> Measure-Command {math -run '2+2;Exit[]'}
Days : 0
Hours : 0
Minutes : 0
Seconds : 2
Milliseconds : 200
Ticks : 22000335
TotalDays : 2.54633506944444E-05
TotalHours : 0.000611120416666667
TotalMinutes : 0.036667225
TotalSeconds : 2.2000335
TotalMilliseconds : 2200.0335
PS C:\Users\Glenn> Measure-Command {math -runfirst '2+2;Exit[]'}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 132
Ticks : 1322163
TotalDays : 1.53028125E-06
TotalHours : 3.672675E-05
TotalMinutes : 0.002203605
TotalSeconds : 0.1322163
TotalMilliseconds : 132.2163
I discovered this while trying to solve the same problem as you. I actually used it to implement a faster script reader. Just remember that using '-runfirst' restricts the language somewhat. I don't think even NIntegrate works at this stage, unfortunately.
xxx.wls. No matter how many times I runxxx.wls, it always takes 4 seconds. $\endgroup$