Some developers are following a trend of importing code by directory in NodeJS using the fs module.

Benefits of this approach:

  • Modules are imported simply by existing in a directory. They can be used as named exports.
import { users } = from "../models";

or
const { users } = require('../models');
  • There is no need to update a giant index file. (Fewer lines of code; less boilerplate)
  • There may be a business or architectural requirement to do this, which will make the rest of the article a moot point.

Am I missing a benefit? Let me know and I’ll add it. I’m not trying to mislead by leaving out facts.

Why it isn’t worth it

1. The behavior is unexpected

Not all developers may be aware of the import trick, especially since it’s usually limited to certain directories, like models. Those developers may break the existing pattern and import a module directly.

const users = require("./models/users");

Another developer could then copy/paste the same import for their model, resulting in two diverging patterns in the codebase.

2. Unused files could be shipped to customers

If the code sample above did not verify extensions, there could be a module called .DS_Store(on a Mac, at least).

A large file named oxford-dictionary.js would bypass that filter. While it may not cause bugs, it unnecessarily increases the size of the code. That may seem like an extreme example (it is), but it’s not uncommon to have extra files in a directory. Many developers include *.spec.js or *.test.js files alongside the code they’re testing to keep code portable. Those files would be included in the application given the code sample above.

A denylist could filter unwanted files, but where does that stop? The time spent catching or debugging the edge cases may be more than someone would ever spend typing module.exports.users = require('./users'); or export { default } from './users';

Some tree-shaking code bundlers, like webpack, may be smart enough to remove unused files, or they may be too dumb to include the files you actually wanted.

3. There are security concerns

The strategy of including code changed from an allowlist to a denylist. With an allowlist, only the modules you want to include are imported. A denylist is flawed in this situation because of the need to think of every combination of names to exclude.

If a hacker or disgruntled employee obtains access to a server, they could include bitcoin-miner.js in the directory, subtly using your server and process ID (PID) to run their code. All they need to do is restart the process.

4. Code editors (IDEs) can’t find your definitions

Some IDEs, like VSCode, use statically defined import statements to navigate a codebase. However, with dynamic importing through the file system, some features stop working:

  • Go to Definition The editor will tell you that there are no definitions found for the target module.
  • Rename Symbols Changing the file name does not update references, and renaming the references does not update the file name.
  • Go to References The IDE won’t know where your module is used. As far as it is concerned, your module does not exist.
  • Intellisense/Auto-complete When importing from a module, you won’t have a list of named exports in the context menu.

#dynamic-import #readability #nodejs #architecture #code-quality

Don’t dynamically import code in a directory
1.15 GEEK