Can required modules have descendants?

Issue

I’m working on a module that needs to reference a large set of data from a different module and wondering if I can have that module dataset within the same uploaded model instead of requiring it with an asset link.

Key Questions

Does requiring modules work the same way as InsertService in that the entire Model is loaded (including descendants) or does it only load the MainModule and none of the descendants?

If I have a module that is called MainModule published with a secondary module inside of it and the module is called using require(AssetLink), can I require the secondary module within the MainModule by using require(script.SecondaryModule) in the MainModule code?

I’m not sure whether requiring a module with an asset link will insert the whole model like with InsertService, but I do know that you cannot call require(script.SecondaryModule) as requiring a module is the same as calling that code within the script that required the module. Calling require(script.SecondaryModule) would be the same as trying to require a module called “SecondaryModule” under the script that had required the main module. So, based on that, I would assume it is impossible to call this secondary module contained within the main module as there is no variable referencing the main module itself.

1 Like

I didn’t know the original script reference was carried between modules. Yeah, like you said, that makes it impossible. It would also make it pointless for a module to have any descendants in the first place since you wouldn’t be able to reference them within the module. That’s really good to know. Thanks!

1 Like

When you require a module, it will only run the code from that ModuleScript unless the module requires any of its descendant ModuleScripts. For example, if the script hierarchy looks like this:

MainModule
    ModuleScriptB -- Child of MainModule

It would be possible to access ModuleScriptB like so:

-- MainModule Code
local MainModule = {}
local ModuleScriptB = require(script.ModuleScriptB)

function MainModule.exampleFunction()
	return(ModuleScriptB.exampleVariable)
end

return MainModule

------------------------------

-- ModuleScriptB Code
local ModuleScriptB = {}
ModuleScriptB.exampleVariable = "This is the value of the exampleVariable from ModuleScriptB"

return ModuleScriptB

------------------------------

-- Code for Server Script that requires MainModule
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MainModule = require(ReplicatedStorage.MainModule)

print(MainModule.exampleFunction()) -- This outputs: "This is the value of the exampleVariable from ModuleScriptB"

This would work in the same way when requiring by assetID, too:

-- Everything else is the same except that the require in the Server Script would go from this:
local MainModule = require(ReplicatedStorage.MainModule)

-- To this:
local MainModule = require(assetID)

In theory, you could store a reference to ModuleScriptB inside of the MainModule so that you could require it directly from the server script but I wouldn’t recommend that. I’m only showing it as an example here to illustrate what’s possible:

Click here for Example #2
-- MainModule Code
local MainModule = {}
local MainModule.ModuleScriptB = script.ModuleScriptB

return MainModule

------------------------------

-- ModuleScriptB Code

local ModuleScriptB = {}
ModuleScriptB.anotherExample = "Test"
ModuleScriptB.exampleVariable = "This is the value of the exampleVariable from ModuleScriptB"

return ModuleScriptB

------------------------------

-- Code for Server Script that requires MainModule

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MainModule = require(ReplicatedStorage.MainModule)

print(require(MainModule.ModuleScriptB)) --[[ This outputs a table:
{
["anotherExample"] = "Test",
["exampleVariable"] = "This is the value of the exampleVariable from ModuleScriptB"
}
--]]

This would work in the same way when requiring by assetID:

-- Everything else is the same except that the require in the Server Script would go from this:
local MainModule = require(ReplicatedStorage.MainModule)

-- To this:
local MainModule = require(assetID)

Resources

ModuleScripts - Roblox Creator Documentation
Script Architecture - Roblox Creator Documentation

That’s contradictory to what @Kaid3n22 said. He noted that the script reference is carried between modules so require(script.ModuleScriptB) would return nil if Kaiden is correct.

Because the require for ModuleScriptB is included in the MainModule for the first example, that code runs directly inside of the main ModuleScript after it was required by the server script.

This means that script.ModuleScriptB would not return nil because the ModuleScript is trying to index ModuleScriptB and not the server script.


I tested the examples that I included in my post beforehand to make sure that it works as described. Here’s a model I published containing those examples if you would like to test it: ModuleScript Example - Roblox

1 Like

After doing some testing, I haven’t found this to be the case at all. Every time I reference the script variable, it’s always the module. Do you have a source that explains that the script variable is carried between modules, I can’t seem to find one and through my limited testing, script is never the original script variable.

I just tried this out myself, and I also didn’t find it to be the case. I had gotten this from around 4-5 months ago, which it had done as I had said. I assume Roblox did some update, or I was doing something wrong.

1 Like