Hello everyone! I’m sleazyNx. I just made this ModuleLoader. I wasn’t planning to share it at first because there are already quite a few out there. However, when I was learning and utilizing these module loaders myself, I felt that they were kinda complicated. I decided to make my own that’s easy to comprehend and simple to utilize. I showed this to my friends and asked them to try it out. They found it easy to comprehend and simple to utilize. So, I decided to share it with all of you.
I’ve done my best to add clear comments and instructions throughout the module loader to make it easier to read and understand.
Features
- Repeating Loading – Automatically loads all ModuleScripts from Modules folders in ReplicatedStorage, ServerScriptService, and StarterPlayerScripts, including subfolders.
- Priority-Based Execution – Modules may specify a Priority value; modules with higher priority execute first, making dependencies straightforward.
- Automatic onLoad Execution – Modules that specify an onLoad function execute automatically after loading, respecting priority.
- Safe Module Access – Modules access other modules safely using
ModuleLoader:Get("Short.Path")not the rawrequiresystem. - Wait for Load – Use
ModuleLoader:WaitForLoad()to ensure all modules are loaded before accessing dependencies. - Server & Client Support – Automatically handles server-only, client-only, and shared modules.
Usage
local ModuleLoader = require(game:GetService("ReplicatedStorage"):WaitForChild("ModuleLoader"))
-- Load all modules (server or client)
ModuleLoader:Load()
-- Retrieve a module using a short path
local Data = ModuleLoader:Get("Service.Data")
Module Example
local test = {}
test.Priority = 10 -- High priority module
function test.onLoad()
print("Module loaded!")
end
return test
ModuleLoader
Summary
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local ModuleLoader = {}
ModuleLoader.__index = ModuleLoader
local modules = {} -- full path => module
local shortPaths = {} -- relative path => module
local priorities = {} -- table of {module, priority, path}
local loaded = false
-- Helper: repeatedly load all ModuleScripts in a folder
local function loadFolder(folder, rootFolder)
if not folder or not rootFolder then return end
for _, descendant in ipairs(folder:GetDescendants()) do
if descendant:IsA("ModuleScript") then
local success, module = pcall(require, descendant)
if success then
local fullPath = descendant:GetFullName()
modules[fullPath] = module
-- Create short path relative to root folder
local relativePath = descendant:GetFullName():sub(#rootFolder:GetFullName() + 2) -- +2 skips the dot
shortPaths[relativePath] = module
-- Determine priority
local priority = type(module.Priority) == "number" and module.Priority or 0
table.insert(priorities, {module = module, priority = priority, path = relativePath})
print("Loaded module:", relativePath, "Priority:", priority)
else
warn("Failed to load module:", descendant:GetFullName(), module)
end
end
end
end
-- Sort priorities descending (higher priority first)
local function sortByPriority()
table.sort(priorities, function(a, b)
return a.priority > b.priority
end)
end
-- Run onLoad functions based on priority
local function runOnLoad()
for _, entry in ipairs(priorities) do
if type(entry.module.onLoad) == "function" then
task.spawn(function()
entry.module:onLoad()
print("onLoad executed for:", entry.path)
end)
end
end
end
-- Main loader
function ModuleLoader:Load()
if loaded then return end
local foldersToLoad = {}
-- Shared modules
local sharedFolder = ReplicatedStorage:FindFirstChild("Modules")
if sharedFolder then table.insert(foldersToLoad, sharedFolder) end
-- Server modules
if RunService:IsServer() then
local serverFolder = ServerScriptService:FindFirstChild("Modules")
if serverFolder then table.insert(foldersToLoad, serverFolder) end
else
-- Client modules
local player = Players.LocalPlayer
if player then
local playerScripts = player:WaitForChild("PlayerScripts")
local clientFolder = playerScripts:FindFirstChild("Modules")
if clientFolder then table.insert(foldersToLoad, clientFolder) end
end
end
-- Load all folders recursively
for _, folder in ipairs(foldersToLoad) do
loadFolder(folder, folder)
end
-- Sort modules by priority and run onLoad
sortByPriority()
runOnLoad()
loaded = true
print("ModuleLoader: All modules loaded successfully!")
end
-- Retrieve module by short path (relative to Modules folder)
function ModuleLoader:Get(path)
local module = shortPaths[path]
if not module then
warn("Module not found:", path)
end
return module
end
-- Wait for loading to finish
function ModuleLoader:WaitForLoad()
while not loaded do
task.wait()
end
end
return ModuleLoader
ModuleLoader.rbxm (4.9 KB)