Refactor/move file utilities with Meteor 1.3 Imports

You are absolutely right in all of your assertions that the contents of the “module-name” in the imports syntax were not specified by the committee. Every build tool has the freedom to interpret it differently. I believe though that Meteor and NPM both will be using it as relative to the app or package directory. We just need to get our tools fixed to support our build system’s interpretation of “module-name” which I don’t believe is unusual.

Note that ESLint was at first marking absolute paths as unfound and a fix for that system is already available in the form of the NPM package “eslint-import-resolver-meteor”. I have submitted a PR to the Guide to add this.

3 Likes

Btw, does somebody know if the name of the index file is configurable?
I’d like to name it _index.js (so prefixed with underscore), that way it would always show up at the top of my directory in webstorm (and most other IDE’s).

Why do all the Mantra apps not use a /imports/ folder? Have they done something different that I’m missing? @arunoda

eg: https://github.com/mantrajs/meteor-mantra-kickstarter

@seba

I’d like to name it _index.js (so prefixed with underscore), that way it would always show up at the top

I do the exact opposite, prefix everything with _ so that index.js is always at the very bottom :slight_smile:

@joshig

Why do all the Mantra apps not use a /imports/ folder?

It may be related to the .babelrc file

{
  "presets": ["es2015", "stage-2", "react"],
  "plugins": ["react-require", "babel-root-slash-import"]
}

which uses babel-root-slash-import but that’s still confusing because .babelrc was not supported with meteor back then. Does it perhaps use a different build system like webpack? What gives?

That’s where I’m confused too, they don’t use any other build system. There is a webpack example, but I’m not using that and most projects I’ve seen don’t use that unless they really want HMR.

Either way, I’m not using /imports/ and don’t seem to be running into any problems at all. Based off that kickstarter though. It’s a topic I’ve always been curious of. I did find this: https://github.com/kadirahq/mantra/issues/172 it seems Meteor is still loading itself, but following the import paths provided if available?

Exactly. And they are now having trouble because of this.

2 Likes

@joshig, apart from the issue @rlivingston dug out for us (thank you buddy) a simple

git clone https://github.com/mantrajs/meteor-mantra-kickstarter.git
cd  meteor-mantra-kickstarter
meteor npm install && meteor run

has a host of issues with dependencies etc, so I could not even get to a point to properly test if the imports work!

But, I did try out importing a file (template.html) located outside the imports folder a few days ago only to see the server crash with a module not found error and that was when I found out about the imports folder not being optional.

As someone working on a small minimalist app, I feel strange having to refactor by adding lines of code with no immediate benefits, in the form of import statements. I remember when the first meteor tutorials prided themselves in having very few lines of code.

When imports become the default, it would be nice to add an ‘eager’ folder so we don’t lose that functionality, or an ‘eager’ prototyping package just like autopublish/insecure.

2 Likes

@joshig

I fixed babel-root-slash-import issues and now it should work properly.
See: 1.3.3 imports breaking

3 Likes

Thanks @arunoda! I’ll give it a try very soon! You’re awesome :smiley:

1 Like

For those of you who use webstorm, absolute imports do work with a trick!

/imports/something/somethingelse/somefile.js
/imports/something/somethingelse/index.js

import { /* does not work */ } from '/imports/something/somethingelse' 
import { works } from '/imports/something/somethingelse/index' 
import { works } from '/imports/something/somethingelse/index.js' 
import { works } from '/imports/something/somethingelse/somefile' 
import { works } from '/imports/something/somethingelse/somefile.js' 

This means, the presence of index.js is not detected, so the workaround is to append /index to the paths. I think this is a fairly acceptable workaround where one can:

  • harness full power of webstorm
  • use absolute paths for inter-module dependencies
  • use reative paths for module-private dependencies

Edit: Thanks to @sam for https://youtrack.jetbrains.com/issue/WEB-21450

Edit2: One should still be careful with the refactor > move action since not all paths seem to get updated correctly.

Edit3: Well, there’s been a confusion of sam’s, and it should have been @ffxsam whom I owe the thanks to :slight_smile: not that I am not thankful to Sam Hatoum for other stuff :slight_smile:

2 Likes

In webstorm you can set a resource root, so your

import thing from '/import/api/things/things.js;

will be nicely resolved. (It also autocompletes paths & filenames)

1 Like

@batist the problem is not the resource root, since it is already set by default for the project.

The problem is, index.js file. That cannot be resolved with absolute paths.

So for a file path: /import/api/things/index.js

import thing from '/import/api/things/index.js';

and

import thing from '/import/api/things/index';

and

import thing from '../../../api/things';

do resolve while

import thing from '/import/api/thing';

does not. It is a webstorm bug and is being tracked on that link from my previous post.

This bug indeed has adverse affects on file move type refactoring operations.

Ha, that’s funny. That’s a different Sam H. Perhaps it’s @ffxsam? Could also be an imposter :slight_smile:

2 Likes

It’s not a complete refactoring tool, but the atom-import-js package adds the following keybindings

Cmd+Shift+j	Import word	Import the module for the variable under the cursor.
Cmd+Shift+i	Fix imports	Import any missing modules and remove any modules that are not used.
Cmd+Shift+k	Go to word	Go to the module of the variable under the cursor.

Note Fix imports!!!

I installed it, commented out one of my imports, went to my first no-undef error, hit Cmd+Shift+j, and voila, it found the right module and put an import for it at the top of my file.

Obviously, it won’t all be that easy. The import I commented out was for one of my local modules, not something defined in a package. But, there are a ton of configuration options that I am now exploring to see if I can teach this more about my project.

I also noted that they have an “environments” option which can currently only be set to “node”. Perhaps they need help implementing a “meteor” environment? :slight_smile:

There is a batch rewriting capability mentioned at the bottom of their README!!!

3 Likes

Oh, snap! This is looking very promising! Can’t seem to get Cmd-Shift+I working in Atom, but Cmd-Shift-j and Cmd+Shift+k seems to be working just fine.

From what I can figure, .imports.json should look something like this:

{
  "appliesTo": "**",
  "useRelativePaths": false,
  "namedExports": {
    "/imports/ui/components/PageContainer": [
      "PageContainer"
    ]
  }
}

The only problem is that the we need a leading / at the beginning of the import statement. Does this have anything to do with babel-root-slash-import? Also, having to specify a list of namedExports to get the brackets around them is going to be troublesome (but not the end of the world).

Otherwise, seems to be working well.

The leading slash is a Meteor thing. My experiments led me to the exact same point. The namedExports gets around the “/” problem in addition to using the import syntax I like, but creates another maintenance issue.

I found that Cmd-Shift+I worked as long as I didn’t ask it to find any packages. i.e. if I deleted a line importing one of my methods, it added it back with no problem. But, if I deleted the import of SimpleSchema or Meteor, it gave me an exception.

Following a hunch, I defined namedExports for all of the packages that one of my modules used and Cmd-Shift+I then worked fine.

So, this is quite usable if you go through your .meteor/packages file and define namedExports corresponding to every package. But then, that seems to defeat some of the purpose.

I’m just in my initial stages of trying to understand the code, but thinking that this needs to be altered to parse and use the information from Meteor’s .meteor/package, .meteor/versions, and package.js files in the same way that it already parses package.json files. It also needs to support Meteors absolute path implementation so that we don’t have to define namedExports for our modules just to get paths right. And it needs to know what a “core” meteor package is in order to perform the grouping.

One thought that makes me hesitate to do a whole lot on this is… how much of these problems will go away in 1.5? The “/” thing, probably not. And it wouldn’t go away for legacy packages. But npm packages should work fine with this out of the box.

Maybe, due to the legacy package issue (they might be around for a long time), it’s worth customizing this to support them.

Anytway, it appears to be a promising starting point!

1 Like

It looks like needing to define namedExports more easily is an issue that goes beyond Meteor. They have an applicable issue, Auto-resolve named exports from ES2015 modules.

Looking at it, parsing all files to find the exports every time a user changes something in the editor is, of course, an issue. So they are talking about having something that does it once and then could be re-executed when needed. The details of finding the files could still be different.

I wonder if there is some by-product of the meteor build process that could be farmed to get this? That would have the downside of requiring a build to get the first version, but that’s not a bad downside. I usually do my first build before writing the first line of code.

1 Like

With import-js, eslint, and absolute paths, I feel like I’m finally getting a handle on refactoring imports. I’ve gotten to the point where I can rename a file throughout the application in five steps:

Ctrl-Shift-F
> old name
> new name
Right click > Rename
> new name

A far cry from drag-and-drop functionality. But workable.

1 Like

Just a week ago I submitted this feature request.

It didn’t get any votes. Maybe I’m not clear enough on what I think is a simple solution. Build a map of files and allow for “i dont care where it is” referencing by using an operator like tilde or other.

What do you think?

best
Jesper