What does "./" mean in an ES6 import statement?

In the context of linking to files in HTML and when using the command line, I’m aware “./” just means the same directory and this can be omitted when linking to a file in HTML, but I’m not sure why this is needed/what it means exactly in an ES6 import statement.

Does it also mean “the same directory” in an import statement?

As a note, in the challenge ES6: Understand the Differences Between import and require it says “In most cases, the file path requires a ./ before it; otherwise, node will look in the node_modules directory first trying to load it as a dependency”. (Side note about that challenge – if you try to add ./ before the file path in the challenge it doesn’t pass, for some technical reason related to using the window object, discussed in this thread.)

I also recall when I worked on a React app, I had to include “./” – it didn’t work when I tried omitting it, as would work with HTML linking, which was a head scratcher.

Hello Nataliecardot. Yes it refers to file or folder that stays at the same level
Example:
node_modules
public
src
App.css
App.js

Like these cases u import like this
import ‘./App.css’ coz they are at the same level if it were folder u would name folder name import whatever file it is js css. Good luck to your studies

1 Like

JS modules were not a thing when Node was first built, and so it uses a module format called CommonJS. In CommonJS, you import modules like require('my-module').

Node has a built-in package manager called NPM. You can install modules via NPM, and those modules go into the node_modules folder.

Node’s implementation of CommonJS is designed so that you don’t need to write require('./path/to/node_modules/some/path/to/my/module/index.js'). Instead, the module is always a folder, and in that folder there will be an index.js file (it can be any other name, but that is the default).

So then, require('my-module') is telling Node to:

  1. look in node_modules
  2. for a folder called my-module
  3. then load the index.js file from there.

This means that there has to be some way to differentiate your own files from those in node_modules: this is done by explicitly stating the path to the file: require('./my-file'), or require('../some/file/in/another/folder').


Actual ES modules do not know about any of this (and say nothing about how to find and load the modules). They generally require a fully-qualified path, so import foo from "my-module" will either break, or the parser will assume you want a function called foo that is exported from a file called my-module.js that’s lives alongside the file you’re importing from, in the same folder.

What this means is that to import modules in a project that uses NPM, you’d need to write something like (for example), import React from "../../node_modules/react/index" every time you needed to bring React into scope.

This is not anyone’s idea of a fun developer experience, so module bundlers (for example Webpack) will parse your code when they run, checking import statements to allow you to use the Node/NPM/CommonJS style where:

  • If the path is unqualified, like import React from "react", it’s probably an NPM installed package, look in node_modules like Node does and load the module’s main file.
  • If the path is qualified, like import MyComponent from "../components/MyComponent, it’s a specific file, load that file.

This is a specific convenience allowed by module bundlers (or plugins for module bundlers) to handle the way Node deals with modules.

Very minor aside, but the way Node deals with modules may possibly have been a serious design error. Node’s original designer is currently building an alternative to Node (Deno), and that doesn’t use a package manager & sticks to the ES specifications for modules, using fully-qualified URL paths, e.g. import { assertEqual } from "https://deno.land/std/testing/asserts.ts"; (which actually works pretty well in practise).

1 Like