Alternative to "require" to allow module duplication and argument injection

As a Roblox developer, it is currently too hard to create a duplicate of a module.

Many experiences create their own module loader and use that to acquire and cache resources instead of using require directly. For experiences which need multiple environments, such as server authoritative architectures, this duplication and separation of resources/environments is a necessity, and using the standard cached results returned by the require function can easily introduce bugs.

Alternative 1

  • Wrap all modules in return function(env) ... end boilerplate, which requires us to indent our whole module, making it harder to read and edit the code.

Alternative 2

  • Never have services, and to always include an extra argument in the Class.new(env, ...) constructor when creating objects.

Alternative 3

  • Clone every module before requiring, parent it underneath a module which returns an environment, and writing local env = require(script.Parent) at the top.

No matter which way, all of these alternatives introduce extra complexity or readability problems.

Proposed API

--Script example
local module = loadmodule(ModuleScript)(5)
--ModuleScript example
local argument = ...
return {argument} -- or whatever
3 Likes

Its strange to me that we cant utilise the fact that every script’s main function is variadic, considering you can call this function through debug.loadmodule or debug.info.

Allowing debug.loadmodule (at least server side) would be so powerful.

LGTM!

You can return a function that creates the ‘module’ result.

Module results have always been cached and debug.loadmodule or module parameters will break that and cause unexpected results.
debug.loadmodule has always been breaking a lot of stuff so it’s reserved for internal tests which can ignore other engine features not working.

2 Likes