Reputation: 27952
I have a plain old NodeJS project (with Typescript) and I'm really struggling to find out how to do ES6 imports for local files without having to do "../../../foo/bar" all the time.
There are loads of similar questions but all seem to revolve around babel/Webpack which I'm not using.
If I do the following:
import foo from `/bar`
it looks for it in the root folder of my PC (e.g. c:/bar) and fails.
I have tried using a .env file with NODE_PATH set to various hings ("/", "." etc) but no luck. I have also tried setting "type: 'module'" in my package.json and my tsconfig.json file has {"baseUrl": "."}
So I think I've tried every answer I can find. Am I just doing them in the wrong combination or is the solution something different?
Upvotes: 21
Views: 26894
Reputation: 144
I'm using NodeJS with typescript. This is working for me:
// tsconfig.json
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"]
},
And then import it like this:
import { JobServiceService } from '@/jobs/services/job.service.service';
Upvotes: 0
Reputation: 603
As of March 2023, a good way to eliminate the NodeJS relative paths is to use the imports
property in package.json
. For more information, please refer to this post:
In the codes below, #root is the project root.
(Please kindly upvote this answer and this post if they help you. Thanks!)
// package.json
{
"imports": {
"#root/*.js": "./*.js"
}
}
// main.js:
const Source = require('#root/path/to/Source.js');
// Source.js:
module.exports = class Source {
// ...
}
// package.json:
{
"type" : "module",
"imports": {
"#root/*.js": "./*.js"
}
}
// main.js
import { Source } from '#root/path/to/Source.js';
// Source.js:
export class Source {
// ...
}
No need to "import" or "require" any additional packages (No Babel.js, No Webpack, No RequireJS). After installing NodeJS, this method works out of the box.
IDE linkages work as expected (Ctrl-click a class name to jump directly to the source file. Also, moving the source file (by drag and drop) will automatically update the file path references. Tested on WebStorm 2022.3.2
and VS Code 1.76.2
.)
Works with both .mjs
(ECMAScript module system) and .cjs
(CommonJS) file types. Please see this reference Post on .cjs and .mjs.
No need to modify the reserved node_modules
directory
No need to set up any linux file links at the OS level
Upvotes: 12
Reputation: 5500
This was pretty simple to implement for me, using Typescript in VSCode.
In tsconfig.json
, I added "baseUrl": "./",
under compilerOptions
After a restart of VSCode, VSCode will automatically import using psuedo-absolute paths.
The paths won't begin with /
, that still points to your drive root.
If the is below the current file, it will still use a ./relative/path
, but no more ../../tree/traversing
Then I set dev in packages.json to
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env NODE_PATH=./ nodemon ./app.ts"
},
I use cross-env
. You may use the set
command and nodemon
for automatic reloading of change files.
Setting NODE_PATH
to ./
tells NodeJS to do what Visual Studio and TypeScript are doing.
I do have package.json
in my src
directory. You may not, and may need to change some pathing to adjust.
Upvotes: 1
Reputation: 18036
Here are two tricks I've used for this, with Node.js and native ES modules.
file:
dependenciesIf you want to access <project root>/bar
from a sub package two levels down, adding this to the package.json
dependencies:
"@local/bar": "file:../../bar",
..makes bar
available to the said subpackage as @local/bar
.
While relative paths are still present, they are now all in the package.json
files and the sources never need to know..
import()
Pick the root folder's path to a constant and do this:
const foo = await import(`${rootPath}/bar`);
Upvotes: 9
Reputation: 475
I am not sure what you mean by "local files without having to do "../../../foo/bar"
"
Let me explain how Javascript handles imports. Here is a basic folder structure.
C:Users/NAME/Project/randomfolder/bar.js
- Project
- Random Folder
- foo.js
- bar.js
Option 1 Probably the better option for 95% of what you will do
Let's say you are trying to import foo.js into bar.js we first get our current location of bar.js using a .
so it would be
import foo from "./Random Folder/foo.js"
If you are going the other way the .
is still used to say get current location in the folder structure but you pass a second .
so ..
then a /
to go up a folder. So to import bar.js into foo.js it would look like this:
import bar from "../bar.js"
We are going up a folder then looking for the file we want.
Option 2
But if you know you folder structure is going to be very big and you will be importing always a few folders up or down why not make a variable and then use string literals.
let folder = `../../../`
import test from `${folder}foo`
You have a few options of how to handle what you want to do.
Option 3 For NodeJS and modules
If you are using NodeJS and want to get the path not relative, the use the app-root-path module. It lets you always get your project root and then dig into to files accordingly. This can be accomplished with string literals.
var appRoot = require('app-root-path');
import foo from appRoot + "/foo/bar/folders/bla/bla"
or
import foo from `${appRoot}/foo/bar/folders/bla/bla` <-- string literals
Upvotes: -1