Path to module when importing

I’m started to pick up a bit of speed with Steal but I don’t quite get how the modules are located yet.

When I have:

import can from 'can';

It appears as though the node_modules folder is used by default. I would like to import one of my application modules in the same way:

import localisation from 'localisation';

I understand that one can use relative paths but that is quite annoying since one needs to keep in mind where you are in the folder structure. Moving a file would also mean changing the path.

It seems as though I can use paths option in the package.json configuration:

{
  "system": {
	"paths": {
	  "localisation":  "./src/services/localisation.js"
	}
  }
}

However, it is going to become rather tedious to do this for each file.

Is there some way to map by convention / mask? And if so, what would the import look like?

You can use your project name like “myhub/lib/library”

Thanks Justin but I don’t quite get how that relates.

Can you point me to the documentation perhaps where I can get a better understanding of the structure?

I mean, where does the “lib” fit?

The reason I ask is that the default package.json has this:

"directories": {
  "lib": "src"
},

Is this the same lib, and what does it do?

Will this path structure work for both import and the paths option?

I saw on a video that one can use the ~ as the project name.

Should I ideally be importing for using the full “absolute” path?

I think @justinbmeyer gave you the answer you were looking for, and you’re just misunderstanding some other things, however this may not be the case. Let me try and explain.

If you have a directory structure like:

myhub
├── package.json
└── src
    ├── mylibbylib
    ├── myapp.html
    ├── myapp.js
    ├── myapp.less
    └── index.html

(where myhub is the parent directory containing the package.json)

The package.json has to be told that the src/ directory is where all the magic happens (everything above src/ is just boilerplate and won’t be needed to be looked at for “self” import statements).

Telling package.json about where all the magic happens is done using system.directories.lib within package.json like:

    "directories": {
      "lib": "src"
    }

By “self” import statements, I mean those that look like:

import foo from 'myhub/mylibbylib/bar/bar'; // => myhub/src/mylibbylib/bar/bar.js

OR

import foo from '~/mylibbylib/bar/bar'; // => myhub/src/mylibbylib/bar/bar.js

(these import statements will work from within any .js file within your project)

So, essentially, ~/ and myhub/ point to myhub/src/ on the filesystem because that is how you set things up in your package.json using the system.directories.lib config. If, for instance, you changed system.directories.lib to src/mylibbylib then your import statements would have to become:

import foo from 'myhub/bar/bar'; // => myhub/src/mylibbylib/bar/bar.js

OR

import foo from '~/bar/bar'; // => myhub/src/mylibbylib/bar/bar.js

The directory myhub/src/mylibbylib would become the new main root for import because you’re sepcifying “name of your app” (myhub) points to here. In this case you would lose some flexibility as everything would have to be inside mylibbylib now, at least to maintain sane imports.

Another (final) example would be if you renamed src/ to blah/. You would need to update package.json, because now StealJS doesn’t know where to look when encountering an import statement that starts with the name of your package (myhub):

    "directories": {
      "lib": "blah"
    }

Once you did this, you would not have to change your import statements; the following would continue to work:

import foo from 'myhub/mylibbylib/bar/bar'; // => myhub/blah/mylibbylib/bar/bar.js

Because you updated the package.json to tell StealJS about the new main root location for imports.

Not sure if that helps at all.

Edit:

Additionally, regarding your question:

Will this path structure work for both import and the paths option?

It is my understanding that paths for the system.paths option in package.json must be actual paths, and wildcard expansion of things like ~ and myhub (or whatever is the name of your app) will not work here.

That does help, thanks.

You could shorten your import slightly from:

import foo from 'myhub/mylibbylib/bar/bar';

To

import foo from 'myhub/mylibbylib/bar/';

Leaving that trailing trailing slash after {name}/ is shorthand for {name}/{name}.js… but perhaps you knew that :slight_smile:

So you are saying all imports should use a full path, then? It isn’t a train smash, I guess.

I was thinking that perhaps there is some convention that I could map a part of the path in some configuration:

"models": "myhub/src/models/",
"models": "myhub/src/models/*-model.js" // <-- or even this

Then I could import like so:

import foo from 'models/bar/';
import foo from 'bar-model'; // <-- or even this

Anyway, thanks for your input. I’ll stick to the full path unless something else pops up :slight_smile:

Haha, yeah, I added the extra bar to be more explicit while explaining things :wink:

Looking at the docs, it looks like it actually may be possible to do what you want:

http://stealjs.com/docs/System.paths.html#section_Wildcardpaths

Take a look.

That does look useful… I’ll give it a bash.

Looking at the docs, it looks like it actually may be possible to do what you want.

Yes, it’s possible, but you can only use a mask with a two-part module name. Something like libs/*. So you can’t make localisation and somethingelse both hit the same path unless everything else does. However you can make libs/localisation and libs/somethingelse get mapped to a particular location.

It’s important to understand that the primary identifier that steal uses are module names and not url locations. Read through this: StealJS - moduleName

This is why I would still probably use ~/libs/somethingelse in 1.0 or projectName/libs/somethingelse before that.

It keeps the module name rooted to the current package/project name. If you ever wanted to share its code, things would work as projectName should be unique, but libs is probably not.

Course you could set up a map for lib/* to projectName/lib/* and then you can just write lib/somethingelse.