Galooshi / import-js

A tool to simplify importing JS modules
MIT License
524 stars 70 forks source link

"includes" configuration option to add other sibling source roots? #504

Open indigoviolet opened 6 years ago

indigoviolet commented 6 years ago

In our set up, we have a 'shared' directory that applies to multiple of our "apps"

something like,

root/shared
root/apps/web
root/apps/dashboard

and we use Webpack to resolve across these directories.

How would I convince import-js to look in these other locations? Would it make sense to add an includes configuration option analogous to excludes?

trotzig commented 6 years ago

and we use Webpack to resolve across these directories.

Can you explain what this means? For instance, what does an import look like from lets say root/apps/dashboard/foo.js to root/shared/bar.js?

indigoviolet commented 6 years ago

The import looks like

import bar from 'shared/bar'

Then, somewhere in our Webpack config we have

resolve: {
  modules: ['./node_modules', './shared']
}
trotzig commented 6 years ago

Okay, cool.

Is import-js picking up exports from the shared folder and just making the imports look weird? Or are they not found at all? I'm asking because if the import statements are there but wrong, you might be able to solve this with the moduleNameFormatter configuration option: https://github.com/Galooshi/import-js#modulenameformatter

trotzig commented 6 years ago

Oh, wait. Maybe there is a package.json in each of the apps folders? That would make import-js stop there when searching for imports.

indigoviolet commented 6 years ago

They aren't found at all, and yes, you're exactly right - there is a package.json in each of the apps folders. That's why I'd like to explicitly tell import-js about the other folders it should look in.

trotzig commented 6 years ago

I understand the issue. Having an includes config option which would allow sibling projects to be searched could be a little tricky because the file watcher we use (watchman) needs a common root. I'm not saying it's impossible though, just that it would require some work.

One workaround I can think of is to try adding symlinks inside the different apps folders. If I'm not mistaken, watchman will traverse symlinks as well.

indigoviolet commented 6 years ago

Cool, I'll try the symlinks option and report back.

Re: watchman's requirement for a common root, is it necessary to watch the sibling projects? Could it work with the assumption that changes to the sibling directories requires a restart of the daemon?

Thanks for being so responsive!

trotzig commented 6 years ago

I guess that would work given that we document it properly with the potential addition of includes.

indigoviolet commented 6 years ago

Unfortunately the symlinks approach does not seem to work.

I verified that it does work when I copy the directory instead of creating the symlink.

It doesn't look like watchman supports symlinks completely: https://github.com/facebook/watchman/issues/105

~However one of the suggestions in that thread (https://github.com/facebook/watchman/issues/105#issuecomment-296390118) which causes 'shared' to mimic a node_modules package did work for me.~

indigoviolet commented 6 years ago

Actually I think I was mistaken about the node_modules hack - I still had the copied folder in scope. Doing the test correctly shows that the symlink approach doesn't work at all for me.

Just documenting a version of the copying hack for future reference:

You could use https://github.com/wix/wml to do

wml add shared app/shared wml start

Add app/shared to .gitignore

trotzig commented 6 years ago

Interesting, thanks for trying it out. I recently worked in a project which made use of Lerna (https://github.com/lerna/lerna) and import-js was able to resolve imports across sibling packages. And if I'm not mistaken, Lerna uses symlinks to "bootstrap" package dependencies.

Ninja edit: I just realize in a Lerna setup the "shared" packages are listed as dependencies in package.json. When import-js resolves imports from package dependencies, it doesn't use watchman. It simply grabs exports directly from the index file pointed out in e.g. node_modules/shared-package/package.json.

Another way to solve the problem you have could be to allow the watchman root to be overridden in config. I'd be happy to review a PR exploring a solution.

indigoviolet commented 6 years ago

I think that one difference from the lerna setup is that our sibling root is not a package -- it isn't exporting everything from under it in an index file. Since #344 is still open, my guess is that this approach won't work without adding a burden of changing the exports.

arggh commented 5 years ago

I was looking for a somewhat similar solution, with this kind of monorepo structure (Meteor environment):

/project
  /meteor-packages
    /package1
    /package2
    /package2
  /app1
    /packages
       /package1 *symlink -> ../../../meteor-packages/package1*
  /app2
    /packages
       /package2 *symlink -> ../../../meteor-packages/package2*
  /app3

Each app has it's own package.json and therefore it's own .importjs.js config.

To use ImportJS with the Meteor packages, I have to temporarily move the package directory over to one of the app folders, run the batch ImportJS command, then move the package directory back to /meteor-packages.