Skip to content

Conversation

@paulyoung
Copy link
Contributor

This pull request addresses the issue described in #352 (comment).

This means that modules can be required without setting process.env.NODE_PATH or renaming the output directory to node_modules.

@garyb
Copy link
Member

garyb commented Mar 4, 2015

Seems like a good solution to me, I'm not sure why we didn't do this in the first place! 👍

@paf31
Copy link
Contributor

paf31 commented Mar 4, 2015

I'm not sure I see the benefit of this, sorry. To be honest, I don't fully understand the issue yet :)

The way I understand it, CommonJS defines what the module loader should do, which is why I like that we do the minimum possible work when generating imports.

Maybe the relative path could be a command line option, but I'm not sure I like making ../ the default. Maybe I'm missing something.

@paulyoung
Copy link
Contributor Author

No need to apologize! I thought it was better to make the change and submit a pull request rather than open an issue for this one.

I think the benefit is that people can use psc-make and then require any of the generated modules (including the entry point) without running into Cannot find module errors.

It took me a while to find the linked issue and make things work otherwise and both workarounds aren't ideal, it seems.

@garyb
Copy link
Member

garyb commented Mar 7, 2015

Hmm, I see your point @paf31, but yeah I think it would be nice to have as a command line option. Avoiding the copy etc. stage during compliation would be handy, as it seems to have tripped up a few people.

@paulyoung
Copy link
Contributor Author

Might want to consider making the ES6 module format an option too.

@paf31
Copy link
Contributor

paf31 commented Mar 8, 2015

I like the ES6 module idea, maybe as a separate option for now.

I guess what I don't understand is: why not just set -o output/node_modules or something?

@paulyoung
Copy link
Contributor Author

My concern was that a package in node_modules/ might conflict with my output. It hadn't occurred to me to use a subdirectory.

@paf31
Copy link
Contributor

paf31 commented Mar 8, 2015

Could you try it and see if it solves your problem? It might not, but if it does, we could just change the default output directory to that.

@paulyoung
Copy link
Contributor Author

That works, although obviously I now need to do:

var Main = require("./output/node_modules/Main");

instead of:

var Main = require("Main");

which seems reasonable to me.

@paulyoung
Copy link
Contributor Author

I'm happy to submit a pull request which changes the default output directory, if that's what people want.

@paf31
Copy link
Contributor

paf31 commented Mar 8, 2015

I'm trying to think if it will mess up any tools, but honestly I'm not sure. Maybe pulp, which would be bad. It's probably worth checking.

@paulyoung
Copy link
Contributor Author

Pulp has a hard-coded build path instead of deferring to psc-make:

https://github.com/bodil/pulp/blob/e73b9c29ac7e02e6f487037d8c2c6898915f70a7/index.js#L163

I just confirmed locally that even with the change to psc-make, pulp build will still use output/

@paulyoung
Copy link
Contributor Author

To clarify, I'm not pushing for this either way.

Manually setting output/node_modules/ works for me, but would also be glad to contribute a change.

@michaelficarra
Copy link
Contributor

It feels like a bit of a hack to abuse the node_modules directory in the node module resolution algorithm. I think relative imports are better. 👍

@paf31
Copy link
Contributor

paf31 commented Mar 9, 2015

How is it a hack? Doesn't CommonJS define the resolution algorithm? My concern is that we end up tying the import code to the particular way in which we lay out things on disk, which means we might not be able to play well with other modules later.

@michaelficarra
Copy link
Contributor

No, node specifies their module resolution algorithm here: https://nodejs.org/docs/latest/api/modules.html#modules_all_together

I'm sure other module resolution algorithms for CommonJS systems would implement relative modules, but would be very unlikely to include node_modules directories in their algorithm.

@garyb
Copy link
Member

garyb commented Apr 6, 2015

What about this one? I'm still on the side of slightly preferring relative imports to relying on node_modules to resolve...

@paf31
Copy link
Contributor

paf31 commented Apr 6, 2015

I don't really fully understand the benefit of this. If the goal is just to be able to run the Main module without renaming, then I don't think it's worth it.

The current approach isn't a hack at all - we create a valid set of CommonJS modules, each in their own directory. How they get used, and how they reference each other depends on the CommonJS implementation and its module resolution algorithm. The approach is simple (a module name is a String) and works well with NodeJS and also with Browserify, but I don't know about any others.

On the other hand, using ../ forces us to lay files out on disk in a particular arrangement. What if we don't even want all the modules to be available locally on disk? I can imagine an algorithm which looks certain modules up in other ways, from a web server, or whatever. That's why I don't like the filename approach.

@garyb
Copy link
Member

garyb commented Apr 6, 2015

The other consideration is that by doing it this way we're trampling on the module name space root - without using ./ or ../ it means the PS-generated modules can only ever be placed in the root, with the relative URLs they could be placed under a PS namespace or something like that if so desired.

@paf31
Copy link
Contributor

paf31 commented Apr 6, 2015

To offer an alternative, I would merge a PR which made this a command line option.

@garyb
Copy link
Member

garyb commented Apr 6, 2015

That would work for me, it could be the psc-make equivalent of --browser-namespace for psc.

@paf31
Copy link
Contributor

paf31 commented Apr 6, 2015

True.

A better example of a different algorithm would be a situation in which you wanted one set of modules to be placed in node_modules, and the rest in node_modules/my-module/node_modules, for whatever reason (maybe different teams are responsible for different modules). Point is, the rename is just one way of making things work with Node, but there are other ways, and we should be free to lay modules out on disk as we choose.

@paf31
Copy link
Contributor

paf31 commented Apr 6, 2015

One more thought: I don't think it's the job of psc-make to package modules perfectly for any one target. That's better done by a tool like pulp IMO.

I think psc-make should do the minimal amount of work to create a valid set of modules, which it currently does. The fact that we have to do manual work right now is just a result of the lack of better tools, but that I don't think we should build such tools into psc-make.

@kritzcreek
Copy link
Member

The way I currently use my PureScript modules is with @ethul's brilliant https://github.com/ethul/purs-loader and webpack. I can then import functions from that module with whatever import syntax I prefer.
For example:

  • ES6 destructuring & "Usual" ES6 import

https://github.com/kRITZCREEK/squirrelzon/blob/master/src/js/components/Shoppingcart.js

So I think if people want to improve their imports they should use a packaging tool that does that. The compilers/make-tool's job is rather to enable packaging tools to use the output.

PS: A nice sideeffect of this is, that I can now use ES6 syntax in my FFI declarations.

@starper
Copy link

starper commented May 26, 2015

I've found one example where it could be very useful. Let's say you have some js library MyLib downloaded using npm and you wrap it using FFI like this:

module MyLib where
foreign import foo """
  function foo (a) {
    return require('mylib').foo(a);
  } """ :: a -> a

Then you compile it using psc-make (after this it can be bundled using webpack, for example). If your output folder is node_modules then the original mylib will be replaced with compiled one, but if output folder is something like app\node_modules (app may also contain index.js file which requires Main module) then compiled MyLib module would require itself. Relative imports will solve this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants