Play Solo Mode ModuleScript Caching

Context: If you didn’t already know, calling require() on a ModuleScript returns a cached version if require() has been called once before on that same ModuleScript, albeit locally (the server and client have separate cached versions.)

When clicking the “Play” button in studio, studio acts as both a client and server in just one window. I’m not entirely sure how separate the server and client tasks are, but Play would be a better emulation of a real server if the server and the client’s cached ModuleScripts were separated. Here’s an example to illustrate the issue.

TestModule [ReplicatedStorage]

[code]local TestModule = {}

local A = 0
TestModule.A = 0

function TestModule:Test()
A = 42
self.A = 42
end

function TestModule:GetLocalA()
return A
end

return TestModule[/code]

ServerTest [ServerScriptService]

[code]local TestModule = require(game.ReplicatedStorage.TestModule)

print(“SERVER TEST”)
print("===========")

print("local A = " … TestModule:GetLocalA())
print("TestModule.A = " … TestModule.A)

print("===========")
print(“TEST()”)
TestModule:Test()
print("===========")

print("local A = " … TestModule:GetLocalA())
print("TestModule.A = " … TestModule.A)

print("===========")[/code]

ClientTest [StarterPlayerScripts]

[code]local TestModule = require(game.ReplicatedStorage.TestModule)

print(“CLIENT TEST”)
print("===========")

print("local A = " … TestModule:GetLocalA())
print("TestModule.A = " … TestModule.A)

print("===========")
print(“TEST()”)
TestModule:Test()
print("===========")

print("local A = " … TestModule:GetLocalA())
print("TestModule.A = " … TestModule.A)

print("===========")[/code]

Here are the outputs of these two scripts.

[code]

SERVER TEST

local A = 0
TestModule.A = 0

TEST()

local A = 42
TestModule.A = 42

CLIENT TEST

local A = 42
TestModule.A = 42

TEST()

local A = 42
TestModule.A = 42
===========[/code]

As you can see, whichever script runs first (the server) calls require() on the ModuleScript, creating a cached version of the ModuleScript. Then, the client script runs, and the result from require() is the cached version of the ModuleScript. This isn’t how it works on a server, so I think that it would be best to separate the ModuleScript caches for the server and the client in Play mode.

Thanks!

I think the whole bug is all of the environments are the same in terms of client and server, which affects _G and Remote, and all server-only functions.
It would be nice if it could be fixed by identifying what is a local script and what is a server script, but I am not sure how massive the implementation would be.

Just like FLU said, scripts in Play Solo don’t have separate environments, which is why you can use LocalPlayer from a script in Workspace; or write to DataStore from a LocalScript; or allowing LocalScripts to run in non-local places…

What I always do is just have my module run the server code if it’s on the server or play solo, then run the client code if it’s on the client or play solo.