āMeteor 1.3 Application Structure for Dummiesā
Hi Guys,
I guess thatās what best describe my doubts:
The guide says: āit is recommended that you write your application to use ES2015ā¦ provide backwards compatibility with applications written for Meteor 1.2 and earlierā. Does it means eager loading will eventually be deprecated? Should I hurry?
The guide says āYou may combine both eager loading and lazy loading using import in a single appā. What happens to Atmosphere packages added by Meteor add <package> and go inside .Meteor folder, not imports? When do I need to import them on my code, when I donāt?
If I declare importing one atmosphere package, what happens with the load order of the rest of the undeclared ones? Is it a declare all packages or none deal?
Do I have to declare import on all NPM packages? If I choose to work with the eager loading path only, how would that works?
The Guide mentions the āLoad orderā, but they are actually all loaded at the same time as all files are minified and gziped into one single .js, .css. html files, etcā¦ Are there plans to actually splitting code and load on client only as needed?
Is it mandatory to declare import { Meteor } from 'meteor/meteor' ? If so, where is the best possible place? What would one gain / loose by declaring it later in the application?
import surely means a lot for larger projects with larger teams. I understand that this is because it helps modularizing the application and avoid crowding Global space into a messy thing. It also replaces the not so elegant lib folder and file naming schemes to assure code dependency order. But for smaller teams / projects, what other benefits can one expect? Improved app / load speed? Would the extra complexity pay off? Can we justify it?
I will let someone more experienced amswer your questions as Iām also trying to grasp this, but using module imports is entirely optional at this time. You can still use the old way if you prefer. Touching on you last question, it may even be the preferred way for small projects, depending on your requirements.
Like you said, there is currently no lazy loading or code splitting, since everything is compiled to a single file. At least thatās my understanding.
@tmeasday not really ground breaking but where would you suggest to put some basic html files that arenāt really ui like a simple head.html containing the <head> head tag as it grows in an application? Directly inside the /client/head.html
edit: i assume my guess to be right looking at this commit:
It would be a really nice addition to make an alternative application structure recommendation for large projects suggesting package-esq structure. Like what is being done at https://github.com/TelescopeJS/Telescope
There are many articles out there with some very neat ideas,
Both. There would be NPM packages as well as Meteor packages.
Have a look at < https://github.com/TelescopeJS/Telescope > for example. This is a very good way to structure a large app. Other large apps can be structured in a similar way.
You misunderstand. Iām very familiar with that approach - and most Meteor devs involved in large app development probably are too. However, imagine a world with no atmosphere or Meteor package manager. How would we go about writing a package structured app where current ālocalā packages are not Meteor packages, but npm modules.
So, more:
how to write npm modules
how to manage dependencies
how to have local (private) modules
etc.
Like it or not, the fact is that MDG are becoming more mainstream JS - and that means npm. I donāt expect the Meteor package manager to disappear overnight, but npm is clearly the way weāre being steered - and thatās also the direction most ātraditionalā Meteor devs are least comfortable with.
Iād considered writing something for this myself, but Iām currently too involved with project work to devote much time to it.
I tried looking into doing that myself, I had it to a point but then I realize it isnāt worth it unless the a submodule itself is packageable.
The main reason was we now have import and that allows us to pick and choose which parts we would want in the application to load given the scope (using eslint). In the older versions of Meteor everything was loaded and packages were the only good way of limiting scope, but that is no longer the case.
Other issues:
There is also no inherit version from parent so you would need to sync up manually.
You lose some of the IDE type checks because the eslint-meteor-import-resolver will only check that the package is valid, it will not follow down to read a file since it wonāt know how to resolve it.
because of the above, some refactoring tools are not available to you either.
Thereās more boilerplate code
Iāve had issues with this on Java land too. Where an application is broken down into separate projects and it ends up it a lot of plumbing code for small amounts of code like https://github.com/TelescopeJS/Telescope/tree/master/packages/nova-forms-tags. Things wouldāve been easier to just lump most of it into one project.
When packaging I usually recommend it to be broken down by tiers (i.e. server-side, client-side, domain, services/messaging) in JEE you would do that because of their packaging structure (WAR, EAR, EJB, Web services) and refactor out reusable components that can be maintained outside the project as needed (i.e. someone from another project asked for it).
I tried to do it on Meteor, but when I did it it was more plumbing for little benefit. Meteor has well defined API starting points for client and server (i.e. put stuff into the client and server folder). The only annoying part about Meteor is anything outside those and imports are loaded in both so the only thing I would have in that common area is a gulpfile.js and JSON configuration files because the tools need it that way.
Anyway donāt let me detract you, you may have better experience.
Iād disagree, and my career experience has mostly been in being the lead software architect / tech on multi-million line applications with teams of as many as 80 engineers and a co-lead on one with over 200.
That structure was developed largely because modules werenāt built into the language yet. I could see having it discussed as an alternative, but Iād rather see a much better article focused on getting the most out of modules for the mainstream large application.
In the Guideās 1.3 Migration article the Recommendations: Modules section has a specific recommendation to convert local packages that were not created for the purpose of sharing code between applications from packages to modules within your app. In other words, the best reasons the local package organization arose have gone away. So local packages should go away in favor of the standard direction ECMAScript has chosen.
I believe that ES6 modules actually now offer a richer organization capability for large projects versus a single, usually big and flat, packages or node_modules directory. Building a full tree of all of my moduleās dependencies on each other when they are in packages involves parsing every package.js and packages.json. With modules and a little organization, much of that tree can just appear in the directory structure. The interfaces are also better defined and more flexible in modules.
The only weakness Iāve seen in the module approach is that it is a bit weak on privacy. But, at least you can easily see every fileās dependencies. It would be trivial to write your own scanning mechanism to enforce whatever rules you choose about importing across certain directory boundaries. If I were writing a large product using multiple developers in Meteor today, Iād consider something like requiring an explicit comment to an export, something like // public export, that is allowed to be imported by modules that are not within or under the current directory and then creating a little script that can scan for imports that violate that between running lint and running tests.
But that even illustrates my point about the flexibility of the module system for large projects. It defines my interfaces very nicely, gets rid of global hell, and enables me to easily make rules that fit my project in a manner that follows a standard that goes well beyond Meteor ā ECMAScipt.
Putting all of my imports/ui/ code into imports/ui/client has dramatically reduced my build times when working on my React components. Only a client refresh is done. Is there any reason not to do this? If not, perhaps it should be the recommended structure in the Meteor Guide.
Iām surprised. Is there a reported issue on this? Changes in any file within an āimportsā directory that is not explicitly imported into server code should not trigger a server rebuild as there are no server dependencies on the file.
Iām starting a new project and finally decided to ditch Blaze/Coffeescript to try React and see how much better it is.
I noticed how long it took to get UI changes reflected (5 seconds or so) and noticed the server was rebuilding every time. I moved imports/ui to imports/client/ui, kinda the opposed of @jpillar but it really helped with build times! Now client changes just refresh the browser in a second or two.
If this isnāt considered a bug then the guide should really suggest a structure with a client folder under imports. Note that having imports under client does not change anything, the server will still rebuild for client changes.
I think this is probably a good recommendation to makeā¦ perhaps we can just recommend imports/client instead of imports/ui until this is improved? What do you think @tmeasday?
Regarding the client/server code separation, how would you structure your imports ? For instance, I want to create a token login module for my app. There is business logic that happens on the client side only and some on the server.
Client :
Read the query url to extract token from parameters (in startup.js ?)
Call the login method and handle the callback
Server :
Generate the token
Login handler
How do I structure my imports, so when I import my module api on the client side I only get the client api and the same for server? Also, I would have codes that would need to be run at startup.
Here is a startup from how it could be done but I need your opinion
/imports
/token-login
index.js
token-login.js # Defines the api object TokenLogin
/client
token-login.client.js # Defines logic to call the login method
startup.js # Code extracting the token form url
/server
token-login.server.js # Defines the login method
Would it be better to have two different object like LoginTokenClient and LoginTokenServer ?
That is a pretty reasonable approach. Youāre following the packages-only structure, expect within the /imports folder; and using the classic directory naming conventions in your feature.
The only consideration that I can think of is whether the classic directories should go up a level, and whether to put your feature in an /imports/features dir.
How do you name additional functions within a ācomponentā, āmoduleā etc? Sometimes I may have plenty of them in external files within a folder located in the same place with the component or module, and name the folder āhelpersā, though they are not typical Meteor template helpers, just additional functions that are extracted into separate files to keep the actual Meteor templates code/logic clear.
Renaming the folder to āfunctionsā seem to be not correct because sometimes I can store there constants and not functionsā¦ :-/ While lib is also reserved keyword for foldersā¦ And I donāt want that to load automatically before I specifically import that function to a helper etcā¦ I wonder if there is a better approachā¦