[ModuleLoader] road to upgrading my code

I was thinking about upgrading my code, because i have hundreds of modules and thousands of code lines. One solution that come to my mind was Loader. With this module, I could skip writing full paths and require calls for modules and remote events/functions by few lines of code.

local LoaderService = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")

function LoaderService.LoadModules(ModulesFolder : Folder) : {[string] : any}
	local modules = {}
	for _, module in pairs(ModulesFolder:GetDescendants()) do
		if module:IsA("ModuleScript") then
			local success, result = pcall(require, module)
			if success then
				modules[module.Name] = result
			else
				warn("Error requiring module:", module.Name, "-", result)
			end
		end
	end
	return modules
end

function LoaderService.LoadRemotes() : () -> ({ [string]: RemoteEvent }, { [string]: RemoteFunction })
	local remoteEvents = {}
	local remoteFunctions = {}
	
	for _, remote in pairs(ReplicatedStorage:GetDescendants()) do
		if remote:IsA("RemoteEvent") then
			remoteEvents[remote.Name] = remote
		elseif remote:IsA("RemoteFunction") then
			remoteFunctions[remote.Name] = remote
		end
	end
	return remoteEvents, remoteFunctions
end

return LoaderService

i make ServerLoader in ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LoaderService = require(ReplicatedStorage:WaitForChild("LoaderService"))

local ServerService = game:GetService("ServerStorage")
local ModulesFolder = ServerService:WaitForChild("Modules")
local ModuleLoader = require(ServerService:WaitForChild("ModuleLoader"))

ModuleLoader.Modules = LoaderService.LoadModules(ModulesFolder)
ModuleLoader.RemoteEvents, ModuleLoader.RemoteFunctions = LoaderService.LoadRemotes()

ModuleLoader looks like this

local ModuleLoader = {}

ModuleLoader.Modules = {}
ModuleLoader.RemoteEvents = {}
ModuleLoader.RemoteFunctions = {}

return ModuleLoader

What do you think about that? Will you add or change something?

  1. you do not need WaitForChild on server side for things that are static
  2. this module loading order is unpredictable so get ready for fun stuff
  3. this loader loads everything even if it’s not in use any more and you forget to delete it
  4. since it’s server side, clients can’t access it, you need to do something similar for client side
local foldersOrder = {"BaseModules", "DataBaseModules", "DependentModules"}

function LoaderService.LoadModules(ModulesFolder : Folder) : {[string] : any}
	local modules = {}
	for _, folderName in ipairs(foldersOrder) do
		local folder = ModulesFolder:WaitForChild(folderName)
		for _, module in pairs(folder:GetDescendants()) do
			if module:IsA("ModuleScript") then
				local success, result = pcall(require, module)
				if success then
					modules[module.Name] = result
				else
					warn("Error requiring module:", module.Name, "-", result)
				end
			end
		end
	end
	return modules
end

wyt?? is just example of folders order but it give me more control over loading

Thanks for your help :slight_smile:

In my opinion it is better than not using a module loader so I would say that its fine

Finally, after a whole day, I found the solution

OnionSuport[MODULE_LOADER]_Simplifying_module_remote_access