In the previous chapter, Command Configuration, we built the "Menu" for our CLI. We created a configuration object that tells the system about the session command (its name, alias, and rules).
However, we carefully avoided writing the actual code that runs the command. We simply pointed to it. In this chapter, we will explain why we did that and how it makes our application faster.
Imagine moving into a new house. You have 50 boxes of stuff.
Our CLI tool might eventually have 20, 50, or 100 commands. Some of these commands might require heavy libraries (like a QR code generator for our session command).
If we load the code for all 100 commands every time the user types anything, the CLI will feel slow and "laggy" to start.
The Solution: We use Lazy Command Loading. We only load the heavy code for the session command if the user explicitly asks for it.
In standard JavaScript/TypeScript, you usually see imports at the top of a file. This is "Eager" loading.
// Eager Loading (Bad for performance here)
import logic from './session.js' // Loads immediately!
const session = {
// logic is already loaded
run: logic
}
To achieve "Lazy" loading, we use a special function called import(). Instead of running immediately, it waits until we call it.
Let's look at the load property we wrote in our configuration file in Chapter 1.
// inside index.ts
const session = {
// ... name and rules
// The Lazy Loader
load: () => import('./session.js'),
}
Explanation:
() => ...: This is an arrow function. It wraps the import so it doesn't execute yet. It's just a set of instructions waiting to be triggered.import('./session.js'): This tells JavaScript to go find session.js and read it into memory.
Now, let's create the file that actually does the work. This file sits quietly on the disk until the load function summons it.
// session.js
// This file is NOT loaded at startup
export default function sessionLogic() {
console.log("I have been summoned!")
// Heavy logic, QR codes, and UI go here
}
Explanation:
export default. This allows the importer to grab the main function easily.qrcode-terminal or complex React components) in this file as we want. They won't slow down the CLI startup.
What actually happens when the user types session?
session.js yet).session.load() function.session.js from the hard drive.Here is the flow:
How does the main program handle this? The import() function returns a Promise. A Promise is JavaScript's way of saying, "I don't have this yet, but I will give it to you in a millisecond."
Here is a simplified version of the code that runs your commands:
// The imaginary CLI runner
async function executeCommand(commandConfig) {
// 1. Trigger the lazy load
// "await" means: Stop and wait for the file to load!
const module = await commandConfig.load()
// 2. Get the default function from the file
const runAction = module.default
// 3. Execute it
runAction()
}
Explanation:
async/await: These keywords are required because loading a file takes time (even if just a fraction of a second).module.default: When you use import(), the result is an object containing all exports. We grab the default export we defined in session.js.session
In our specific case, the session command is going to display a QR code and a UI for remote connections.
If we look forward to Terminal UI Components, we will see that we need to import UI libraries (like React/Ink). These libraries are powerful but large.
By using Lazy Command Loading:
help or version never have to wait for the UI libraries to load.You have successfully set up a high-performance architecture for your CLI!
load function and dynamic import().
Now that we have successfully loaded the session.js file, what goes inside it? We need to build a user interface to show the user their session status.
Next Chapter: Terminal UI Components
Generated by Code IQ