Simple ModuleLoader

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 raw require system.
  • 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)

ModuleLoader Creator Store

1 Like