The require Function
Load external modules with require and understand module caching.
The require Function is a free Lua Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
How require Works
require(modname) loads and returns a module. It searches package.path for a .lua file and package.cpath for a C library. The result is cached in package.loaded[modname] — subsequent calls return the cached value without re-executing the file.
-- First require: loads and executes math_utils.lua
local math_utils = require("math_utils")
-- Second require: returns cached value (file not re-run)
local math_utils2 = require("math_utils")
print(math_utils == math_utils2) -- true (same object)
print(package.loaded["math_utils"] == math_utils) -- trueModule Return Value
A module file should return a value — typically a table of functions. This return value is what require gives back to the caller. If the file returns nothing (or true), that's what require returns.
-- mymodule.lua:
-- local M = {}
-- function M.hello() print("Hello from module!") end
-- return M
-- In main script:
local m = require("mymodule")
m.hello() -- Hello from module!
-- The module table is the interfaceCaching in package.loaded
package.loaded is a table mapping module names to their loaded values. You can manually set an entry to preload a mock, or set it to nil to force a reload (the module file will re-execute on next require).
-- Force reload by clearing cache
package.loaded["mymodule"] = nil
local fresh = require("mymodule") -- re-executes the file
-- Preload a mock for testing
package.loaded["db"] = {
query = function() return {} end,
close = function() end,
}
local db = require("db") -- gets the mockpackage.path Format
package.path is a semicolon-separated list of patterns. The placeholder ? is replaced by the module name (with dots replaced by path separators). You can add directories to search by prepending to package.path.
print(package.path)
-- typically: ./?.lua;./?.luac;/usr/share/lua/5.4/?.lua;...
-- Add local lib directory
package.path = "./lib/?.lua;" .. package.path
-- Now require("utils") will look in ./lib/utils.luarequire vs dofile vs loadfile
require: caches, searches package.path. dofile(path): executes a file immediately, no caching, takes a direct path. loadfile(path): compiles but does not execute, returns a function. Use require for modules; dofile for one-off scripts.
-- dofile: no caching, direct path
dofile("./scripts/setup.lua")
-- loadfile: compile only, returns function
local fn, err = loadfile("./config.lua")
if fn then
local result = fn() -- execute when ready
end
-- require: best for modules
local json = require("json")require with Dots for Directories
Use dots in module names to reference files in subdirectories. require("utils.string") maps to utils/string.lua (with ? in the path pattern). This is how multi-file libraries are organized.
-- Directory structure:
-- lib/
-- utils/
-- string.lua
-- table.lua
-- init.lua
package.path = "./lib/?.lua;" .. package.path
local strUtils = require("utils.string") -- loads lib/utils/string.lua
local tblUtils = require("utils.table") -- loads lib/utils/table.luaModule Initialization Side Effects
Module files execute once when first required. Any code at the top level (outside functions) runs at require time. This is useful for one-time initialization, but be careful — side effects like network connections or file operations run at import time.
-- counter.lua:
-- local count = 0 -- initialized once on first require
-- local M = {}
-- function M.increment() count = count + 1 end
-- function M.get() return count end
-- return M
local c = require("counter")
c.increment()
c.increment()
print(c.get()) -- 2
local c2 = require("counter")
print(c2.get()) -- 2 (same instance, cached)Error Handling in require
If a module file has a syntax error or throws during loading, require raises an error. The error message includes the module name and the error from inside the file. Use pcall to handle module load failures gracefully.
local ok, mod = pcall(require, "possibly_missing")
if not ok then
print("Module not available:", mod)
-- fall back to alternative or default implementation
mod = {feature = function() return "fallback" end}
end
print(mod.feature())package.preload
package.preload is a table where you can register loader functions by module name. When require("name") is called, Lua checks preload first. This lets you register modules without files — useful for embedded Lua or testing.
package.preload["mymath"] = function()
return {
double = function(n) return n * 2 end,
triple = function(n) return n * 3 end,
}
end
local m = require("mymath")
print(m.double(5)) -- 10
print(m.triple(5)) -- 15Circular require
Circular dependencies (A requires B, B requires A) are partially handled: Lua stores a true placeholder in package.loaded before executing the module. If B tries to use A's unfinished table, it may get incomplete results. Avoid circular dependencies in module design.
-- a.lua: local b = require("b"); local M = {}; M.name = "A"; return M
-- b.lua: local a = require("a"); print("a.name:", a.name); return {}
-- When a.lua is loaded:
-- 1. a starts executing
-- 2. requires b -> b starts executing
-- 3. b requires a -> gets partial a (still loading!)
-- 4. a.name may be nil at step 3
print("Avoid circular requires in module design")Quick Check
What happens when you call require("mod") a second time?
Recap: require
Summary:
require(name)loads once, caches inpackage.loaded- Module file returns its public interface (usually a table)
- Clear
package.loaded[name]to force reload - Add to
package.pathfor custom search directories - Use
package.preloadfor in-memory modules - Avoid circular dependencies
Frequently asked questions
Is the “The require Function” lesson free?
Yes — the full text of “The require Function” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “The require Function”?
Load external modules with require and understand module caching. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “The require Function” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.