Function to reset module script require cache in plugins

Plugins want to flush the require cache so that they can run code that you’re actively working on.

Right now you have to clone the script before you do this, which gives you a fresh instance with no require cache.

This is a problem because lua loses hierarchical context when this happens. The game doesn’t know where this cloned module is supposed to exist. Debugging tools can’t associate the clone script with the original.

It becomes impossible to debug scripts being run by a plugin.

So I want a function that would let me wipe the cache of a module so that it can be required again.

13 Likes

It’s messy and will probably deoptimize luau, but there is one way you can do this.

local cache = {}
local requiring = {}
local function nocache_require( moduleScript: ModuleScript )
	local hasCache = cache[ moduleScript ]
	if ( hasCache ) then return hasCache end
	if ( requiring[ moduleScript ] ) then
		table.insert( requiring[ moduleScript ], coroutine.running() )
		return coroutine.yield()
	end
	requiring[ moduleScript ] = {}

	local module, parseError = loadstring( moduleScript.Source )
	if ( parseError ) then error( parseError, 2 ) end

	local moduleEnvironment = setmetatable( {
		script = moduleScript,
		require = nocache_require, -- this cache system is required for this to work properly, just use resetCache when necessary
	}, {
		__index = getfenv( module )
	} )

	setfenv( module, moduleEnvironment )

	local output = module() -- let's assume that you are following the rules of module scripts
	
	for index, thread in requiring[ moduleScript ] do
		task.spawn( thread, output )
		requiring[ moduleScript ][ index ] = nil
	end
	requiring[ moduleScript ] = nil
	
	return output
end

local function resetCache()
	table.clear( cache )
end

But yeah, it really sucks that we need a workaround for this to work. I vouch that we need a way to clear the module script cache-- even if only usable with plugins.

Edit: I just realized this is a year old. I thought it meant January 22nd instead of 2022. Oops.

1 Like

This should really be an engine feature, and work across all of Roblox.

4 Likes

I was mentally screaming at my plugin why it wouldn’t calculate properly. Only to realize it was using a cached module that was not updated.

For a quick fix, close and re-open the studio instance.
Though I really wish this existed so my end users wouldn’t need to re-open studio each time, but for the meantime i will instruct them to do so.

I believe also when running require() on the command bar, will create a cache on the module. And the only way to delete the cache is like doing what you did, or restarting studio. Can be a bit annoying whenever you want to test out a modules methods, then you change something and its using the old module cache, when you require and test again.

1 Like

I don’t believe we’ll ever get this functionality, but you can do something like @xKiiyoko did

nvm I'm stupid

or just make the module return a function that returns the actual module like:

return function()
...
    local module = {}
...
    return module
end

This is also good in situations where it’s better to pass in some arguments for the module script rather than figuring them out by itself.