The import statement is used to load ES6 modules, and it only works inside an ES6 module. Because ES6 modules are loaded asynchronously, the require() statement cannot load ES6 modules. As we said earlier, ES6 modules are recognized by Node.js by the .mjs extension. The ECMAScript TC-39 committee has (or plans to) officially register that file extension with the recognized authorities so that regular tools will recognize both file extensions as JavaScript.
The module specifier one hands to the import statement is interpreted as a URL. For the time being, Node.js will only accept file: URL because of the security implications of loading modules over the Internet. Because it's a URL, some characters such as :, ?, #, or % must receive special treatment. For example:
import './foo?search'; import './foo#hash';
These are valid module specifiers where ?search and #hash have the sort of meaning you'd expect in a URL. So long as Node.js only supports file: URL for import statements, we cannot make use of that feature, but we have to keep it in mind and avoid using these strings in module URL.
One can install custom module loader hooks that could conceivably use those URL parts for some purpose.
The module search algorithm is similar to what we described for require. If the specifier begins with ./, ../, or /, the specifier is interpreted as a pathname. Otherwise, it is interpreted as a top-level module similar to the require statement, with one big difference. The import statement will not search for a global module. This is frowned on, but if one must use a global module, that can be accomplished with a symbolic link.
For documentation, see https://nodejs.org/api/esm.html.