So, after browsing around http://guide.meteor.com/v1.3/structure.html#meteor-structure it still is not crystal clear what’s the purpose of the “imports” dir? Is it something that’s hard coded somewhere, some temporary solution that’s going away after some period or what. Who is importing the stuff that’s inside the imports directory. It’s just vague, but seems kinda important.
I wish there’s someway to annotate the meteor guide to raise issues and talk about the guides contents.
To fully use the module system and ensure that our code only runs when we ask it to, we recommend that all of your application code should be placed in the imports/ directory. This means that the Meteor build system will only bundle and include that file if it is referenced from another file using an import. Meteor will eagerly load any files outside of imports/ in the application …
One reason for this - MDG needed a way to differentiate between newer 1.3 based apps that will be using ES2015 modules and pre 1.3 apps there aren’t (but still allow them to keep running after the upgrade).
I don’t (and won’t ever) use the imports folder. It feels cluttery to me and my folders are deep enough as it is! I don’t wanna add another layer. I hope some day Meteor enforces explicit imports by default.
We are struggling with the idea of using /imports or not as well. Mantra has decided against using /imports. MDG has also said that at some time in the future (Meteor 2.0?) they will likely make lazy load/evaluation the default behavior in Meteor. Right now my inclination is not to use /imports, but we are going all in on ES6 modules.
Eh, just some confusion again: in the guide it says:
", so to opt-in to the new module system code must be placed in the imports/ directory in your application. ".
So how not to use /imports and use ES6/ES2015 modules?
That is factually incomplete. While import/export works fine outside of the scope of imports folders, everything gets evaluated right away and only load order is controlled by modules (with those files not explicitly imported falling to their point in the file structure load order control).
The package docks for modules is pretty clear about what the imports folder does:
If you would like a module to be evaluated lazily (in other words: on demand, the first time you import it, just like Node does it), then you should put that module in an imports/ directory
This is pretty straight forward. The code in /imports won’t be evaluated until it is needed, which is the intent and design of ES6 modules. The reason for the imports directories (and they can be anywhere) over just making all code follow this behavior is so that 1.3 doesn’t break existing applications. Meteor does a very good job of avoiding breaking backwards compatibility, but still giving us a way forward to using new features. imports/ is one of those ways. This is important as properly written module code should land in an imports directory so that it is lazy evaluated only when actually needed. This can cut down on startup time if done right allowing your app to render that much faster if only the files required by the current path are evaluated! (Especially true if you move to react or angular which let you lazy load your view layer as well)
Don’t ignore imports/ it will make your application better. Or use packages which have entrypoints (what I’ll be doing / am already starting to do)
While I generally appreciate the direction MDG is taking with Meteor 1.3, I absolutely hate the name of the imports directory. Especially when combined with the recommendation to put your entire app’s code in there.
Couldn’t they have named it something more sensible, like app or lib? Granted, it would probably increase the likelihood of breaking some apps in the upgrade process, but that can be easily fixed by simply renaming the directory. The name of the imports directory, however, is hardcoded, and can’t be changed for any reason whatsoever.
The way I understand it, imports works the same as public, private, server, and client worked all along. If there is one of those magic names in the folder path to your file, then it has special behavior.
With that in mind, you can structure your folders however you want as long as those folder names appear in the heiarchy:
/someComponentOfApplication
/client
main.js
/imports
-- lots of files here even subdirectories if wanted
/server
main.js
/imports
--lots of files here as well
main.js
/imports
--lots of files here for both server and client!
In that structure, the main.js files are all evaluated instantly, with the files in the imports files being available only as import. So it’s less about the idea that all files in your application should be under there, but rather that if you are going to take advantage of es6 modules, and don’t want your code included directly in the global app, then it should be under an imports directory somewhere. Another perfectly valid heiarchy:
/someComponentOfApplication
main.js #both client and server entrypoint
/imports
-- some imports for client and server
/client
-- some imports for client only
/server
-- some imports for server only
This has just one “entrypoint” for this portion of the application. The entrypoint is global and part of the bundled application automatically, and automatically evaluated.
Also valid:
/someComponentOfApplication
/imports
-- some imports for client and server
/client
-- some imports for client only
/server
-- some imports for server only
This format requires something to explicitly import the contents of the component. This is the ultimate form of removing things from global scope. In none of those am I putting the entire application code below an imports folder. Instead, I am putting the module code for someComponentOfApplication below that folder, and structuring it so some gets automatically evaluated, and some doesn’t!
we recommend that all of your application code should be placed inside the imports/ directory
(emphasis mine).
However, it then goes on to say
Meteor will load all files outside of any directory named imports/ in the application using the default file load order rules (also called “eager evaluation or loading”).
(again, emphasis mine)
Finally, there is this:
Meteor ensures that any file in any directory named server/ will only be available on the server, and likewise for files in any directory named client/. This also precludes trying to import a file to be used on the server from any directory named client/ even if it is nested in an imports/ directory and vice versa for importing client files from server/.
So I guess you might be right – using client/imports and server/imports is a possibility, although the guide recommends simply using a single monolithic top-level imports/ directory.
The meteor guid is very opinionated and that is a good thing. However, a guide is no substitute for an architect. An architect has sufficient experience with software to look at not just the opinionated defaults and recommendations, but also what tools the builders have and can make structural decisions about the app.
As per my earlier post, that is a bit of a simplification. Specifically what it means is that if there are no rules triggered by special folders, then the files will follow the following normal rules (overriden by special folders of course)
Evaluated in file name order (traversing subfolders automatically)
Evaluated before Meteor.startup functions are triggered.
Evaluated after all Meteor core and used packages.
Evaluated on both server and client.
There are three special folders which change those rules, no matter where they show up in the folder path:
Server (we know and love this one, all of our security sensitive code goes here, this code will not end up in the client bundle)
Client (Because sometimes the server just doesn’t care, code in here will not end up in the server environment).
imports (This is the new one to us, and disables the evaluation completely until specifically requested!)
Because of the complexity involved in the various ways that this can be done, and the fact that the meteor guide is intended to get you up and running, not tell you how to architect large applications, the guide buries all that complexity and just says “put it all in imports”
I’ve created a very minimal example that demonstrates what I’m talking about regarding alternative structuring of your application…
Well put. That said, I would wish that the guide would tell you about “best practices”, not just “easy” or “recommended”. But I can live with that.
Now with regards to the “special” directories, your example (and the Meteor guide) demonstrate something worth noting: namely, what happens when you nest special directories into each other:
Code in a client directory inside a imports directory will NOT be lazily loaded AND only be available on the client. Same goes if you put an imports folder inside a client directory (and of course equivalently for server).
I suppose then, the answer I was looking for is that it’s perfectly fine to have, say, three imports directories: one in client, for client-only imports, one in server, and one top-level for shared code. I wish the guide would make that clear.
It’s also perfectly fine to have more, with each of those nested under some other logical directory structure helping to keep your app organized. There is a reason I put them under a parent directory labeled “myModule” and that is to indicate the idea that you could potentially have many such directories, each with a similar heiarchy, but then some might only have server code, so everything would be under a server folder.