Outstanding improvements! Eagerly waiting for stable release.
Can I import from specific files in other packages, like:
`import {Posts} from âmy-modular-package/collectionsâ ?
I think the interface should be:
-
autoimport
package likeinsecure
andautopublish
as suggested by @luisherranz:
- when
autoimport
is removed, amain.server.js
file is generated which solves the following problem mentioned by @benjamn:
It would include ddp
etc and be the equivalent of the following extremely familiar code:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
});
This would bridge the gap to the Node world. The end goal would be that the app could run on NPM without using the meteor
command. I donât know all the implications and implementation challenges if any, but even if it couldnât currently run on NPM, it would pave the way in that direction. It would be a good marketing move to blend in with the rest of NPM. I think itâs important for non-meteor developers to be able to look at Meteor and immediately see something that gives the semblance of something they are familiar with. It would also give advanced developers the opportunity to customize something they couldnât before. And of course it would solve the problem of having all the standard packages loaded in the correct order on startup. Many frameworks generate this sort of entry script for you to modify, so itâs hardly irregular.
Lastly, if the autoimport
package was added back, this would automatically be commented out or ignored.
- Included packages behave like this:
LEGACY ATMOSPHERE PACKAGES:
-
without
autoimport
package: are given a chance to run files in specified sequence without exporting any variables into global scope. The purpose here is to make sure things like the override of built-ins still occur, but without forcing anything new into global scope. However, the interaction between one package to another would continue with the same contract its always had. -
/w
autoimport
package: like they currently do.
NPM PACKAGES:
-
without
autoimport
package: just as you would expect, no special behavior. -
/w
autoimport
package: if ameteor-onstartup
script is specified inpackage.json
it will run any special code that needs to happen on startup such as built-in overrides, global exports, adding blaze templates, etc.api.export
would need to exist in this script, but the whole thing would run in the regular package scope so built-in overrides could be applied to any used sub-packages. There would be ameteor-ontest-startup
possibility as well. Meteor-specificpackage.js
files would obviously not be needed anymoreâwe are now a pure NPM package! The main idea here is A) to solve redundancy: if you import and export all your code properly from the files themselves, you shouldnât have to export anything frompackage.js
or set the file load order; while preserving something Meteor package already rely on: B) running code on startup that does things like override built-ins (but in an NPM-idiomatic way via scripts).
This will delegate the non-standard stuff we allow to seep through the current package system to happen in an optional smaller confined place than before, and without requiring developers to make packages the old Atmosphere way. Like, if you really wanna do that fancy automated/implicit stuff within an NPM package, you can, but besides the special script you will have to make your package look and behave like a regular NPM package. We are now âguidingâ developers into the âpit of NPM package success.â
Ideally, the meteor-onstartup
script wouldnât need to exist (just as if autoimport
wasnât included), and package developers instruct application developers in what to do to get their code running (the choice will be theirs), but obviously itâs of the utmost importance we are backwards compatible, especially as package developers migrate to the NPM style while application developers remain in the Atmosphere styleâthatâs the problem we are trying to solve here; and I also think it remains extremely important that things are as easy and automated as possible for novice developers; even advanced onesâif we can continue to provide the option that, for example, the meteor collection hooks package automatically makes some overrides to your collections, we should. I personally donât like to be told what needs to be implicit and what needs to be explicit, the decision should be mineâwe need to add the explicit option, not simultaneously get rid of the implicit option we are already the best in the business at offering.
Interestingly, I suspect this to be the most important and most common use case, as most application developers will likely stick with the implicit package loading option for a long time to come, while package developers (likely more advanced developers) will want to switch to the more advanced pure NPM import/export approach. Thatâs why itâs so important we consider and get this use case right.
Another important thing to note is this: the same NPM package can be used with autoimport
on as we all as off. Without autoimport
, application developers must follow the directions to import the file and call the code that will run onStartup
routines, whereas application developers with autoimport
included will have the meteor-onstartup
script for the given package handle that for them. In that way, the new NPM packages we are guiding package developers to create will service both use cases while otherwise looking like a standard NPM package. Slam dunk!
- THE CLINCHER: a solution for partial lazy-loading should be a first class priority so developers can migrate/upgrade their app incrementally or simply be able to take advantage of file-order-control where they need:
to accomplish this, rather than having an imports
folder, statically detect which files are ever imported, and automatically remove them from the list of files âeagerlyâ loaded. This would only be a behavior that occurs when the autoimport
package is still included. It would greatly ease the path towards removing the autoimport
package altogether, i.e. after you manually imported all files ever used.
In addition, this would nicely solve the confusion discussed by @serkandurusoy and @SkinnyGeek1010 above:
-
Without the
autoimport
package, developers manually add any assets, templates, css files, etc contained within packages. Thereâs just gonna have to be some sort of Meteor configuration file at the application level that starts to become common practice to use:meteor.config.js
. In it you can specify which assets from which packages are sent to the client. Ultimately this should evolve 2 directions: A) Webpackâs feature to include assets within js files which become part of chunks, and B) the following idea where Meteor provides a router in the core, which efficiently doubles as a way to specify how code splitting occurs across multiple entry points: -
FUTURE: I know webpack and code-splitting is for a post 1.3 release, but it seems to me that if MDG brought a router into core and coupled the router with custom webpack-like code-splitting features, we could greatly simplify the Webpack interface and make it feel more natural.
Why/How? Description of chunks emitted would live in the same location as the route definition, no config file other than route definitions needed. As for require.ensure
, weâd implement that separately (and again on our own, not using Webpack under the hood). When you rely less on routes in single-page apps, code splitting becomes all about require.ensure
anyway.
How/Why? The common code is loaded based on whatâs in main.client.js
and only a second request is needed wherever you wish (e.g. a route, or upon routeless action) to ensure you have anything else you need, while of course achieving the goal of never loading more than you need until you need it.
If we simply had require.ensure
without even âlazy entry point routesâ weâd have already done 90% of the job. I personally am a lot less interested in defining entry points than just being able to load a batch of code/chunks manually when I need it, but I also assume lots of people would prefer the route-based approach as well since it would allow for a single request on page load. Starting with just require.ensure
could be a great feature to do in a 1.3.1 to phase the development of all this.
Perhaps, we never need a code splitting config file (i hate that F#!ing file), and all our chunking is done within code using require.ensure
, as well as including any assets (yes, via javascript) that need to be sent to the client within that chunk. This implicit automated approach would mean one less concept Meteor developers have to learn (for the most part). Itâs a lot easier to explain just use require.ensure
. In addition, what I think might make a lot of sense is instead of specifying your code in the callback to ensure
, utilize something like a decorator (almost like âuse strictâ) at the top of a function to annotate specific exported functions as being the starting point of a given chunk:*
FlowRouter.route('/blog/:postId', {
action: function(params, queryParams) {
@chunk(['additional', 'dependencies'])
import {post, comment} from "lib/model";
//etc
}
});
That would create a chunk according to similar rules as Webpack containing âadditionalâ and âdependenciesâ chunks, and the âlib/modelâ module. The transpilation result would be the contents of action
function being passed as the callback to ensure
. This would save us the unnatural nesting that comes along with ensure
â itâs a seemingly small thing, but would give code-splitting a magically harmless feel, and because of that frictionless would lead to an explosion in its usage. If we could find a standards-based way to achieve something like that decorator instead of having to use a callback, I think weâd be on to something. It would be a very simple and special interface to be sure.
Up until that route, Meteor would have only loaded the common chunks/modules. If itâs the first route, Meteor could just make requests for 2 files. Iâd be fine with that. If the router was added to the core by MDG, well it could likely figure out how to make that first request load only one javascript file. In either case, unlike webpack, we wouldnât need complicated âwebpack.config.jsâ files. Transpilation and building would be a totally separate affair in our case, currently handled by build plugins. The biggest concern MDG has had with Webpackâs interface is all the extra advanced work it expects of developers to configure. Itâs too much boilerplate. Thatâs not the Meteor way, and I wholeheartedly agree thatâs a good decision. I hate all that boilerplate config. Yuck! Lastly, Iâd like to reiterate that by not having to pass all your code in a callback to ensure
we havenât disrupted the hierarchy of your code â we have let it remain flat, which is awesome! Otherwise, importing and exporting is business as usual, not caring if you are doing it asynchronously in chunks.
As for arguments against duplicating what Webpack does and rolling our own, my response would be: code splitting is the best of Webpack, their interface is poor, and we already have other ways to perform the duties of loaders, i.e. the Build Plugin APIâso letâs focus on just getting code-splitting right. Introducing the webpack configuration into Meteor or any app is a lot of extra boilerplate; and since Webpack does a lot more than just code splitting is too advanced and cumbersome for even intermediate developers. My hunch is that a way better automated interface could be developed, definitely if only code-splitting was addressed. I also feel like building for the client is so important it should be something part of ES7 or ES8. I know thatâs farther outside the realm of typical language currently features being tacked on (since it deals both with the server and the client), but code-splitting is only going to become a bigger and bigger problem as the web progresses and our apps get even bigger. As I was saying above, wouldnât it be a lot simpler if entry point bundle configuration happened in the routerâthere seems like there are options to implicitly do this and keep transpilation of various file types separate.
Meteor, being the only true option in town when it comes to reactive universal apps, might be the perfect guys to pioneer a format/interface for code-splitting and the other isomorphic package implementations for NPM discussed above. I.e. a set of tools for NPM that exist outside of Meteor. Unlike Blaze, which was barely supported outside of Meteor, I think in this particular caseâgiven Meteor being a longtime pioneer of the isomorphic web and knowing it better than anyoneâwe may be able to offer something to the greater NPM community that they actually wanna use, especially if we promote it properly (like we never did with Blaze).
It seems we are at a placeâthanks to @benjamn 's amazing workâwhere the foundation import/export functionality is done, and now we need to flush out the interface. I know all of it wonât get done in 1.3, but hopefully we can have a nice roadmap of how weâd like to evolve the interface here. WE NEED TO THINK ABOUT THE END GAME HERE TO GET THE NEXT STEPS RIGHT. Thatâs my main message.
What Iâve presented here is one possible end game. Iâm sure Iâve missed some things and misunderstood some thingsâlet it be a template for thinking of the bigger picture we want for Meteor. To sum it up, from my perspective, we donât want only explicit (and certainly not only implicit, or we wouldnât be having this conversation today). We would like both implicit, explicit, and more importantly a way to gracefully upgrade from implicit to explicit or simply maintain partial implicit + explicit apps. To do this we need to tackle the resulting matrix of adding the fact that packages may also be developed along this spectrum. And to top it off, we need to at least know our âwebpack strategyâ, which Iâm voting should be a custom version all our own focusing just on code-splitting (Iâm pretty sure I read somewhere that @benjamn is thinking the same).
Thatâs all she wrote. âŚ@benjamn , curious what you think about the idea of removing any lazily loaded packages from the set of eagerly loaded packages via automatic static detection of whether one its modules is imported??
@faceyspacey Are you a real person or a Discourse post length edge case test function gone wild?
In that case it would have been Jeffâed a long time ago.
In the doc you gave an example of importing a package by NOT using a relative syntax. So what is your search order in that case (given that you have to search packages and node modulesâŚ)?
@tarmes this ASCII-art directory tree illustrates how Meteor packages are installed in bundles. In short, Meteor packages are treated much like âglobalâ node_modules
, in the sense that they can be imported without relative paths from anywhere in app code, and they can also be shadowed/overridden if the app installs Node modules locally (in /app/node_modules
or /app/client/node_modules
or wherever). Given this directory structure, the lookup rules are the same as the ones used by Node.
In the not-too-distant future, I foresee more and more Meteor packages simply becoming npm packages that apps can install locally, so treating them like npm packages now is a step in the right direction, not just an implementation trick.
@benjamn in your presentation: http://benjamn.github.io/empirenode-2015 , last slide mention http://rollupjs.org/ Is any plan to integrate this bundler beside webpack on meteor ??
I made a small github repo that shows some basics of using this new import/require syntax with npm react components. Might come in handy for somone so here it is.
This app uses the react component formsy
and integrates decently with aldeed:simple-schema
.
I feel the same way. Webpack is hard to configure and could be easily made simplier. However, where I disagree with you is: we should re-code the entire thing in the Meteor build process. Itâs a though I was entertaining too until I decided to check how this can be done.
Be ready for days and days of headache just to understand how Webpack is working behind the scene. If you think Webpack config are complex, this is a very complex engineering problem that has been solved very well. I think it would be an incredibly big job (and quite frankly a waste of time) to try to do EXACTLY the same thing just to get a simplier way of using it.
Instead, why not making Webpack easier to use? Why not find a better API Meteor users could use to simplify the integration of Webpack with their projects?
What if integrating Webpack was not a matter of writing a âcomplexâ config file (quite frankly itâs not when youâre use to). What if all you needed was to add the few packages that you needed? Example:
meteor add webpack:webpack
meteor add webpack:jsx-loader
meteor add webpack:sass-loader
And use the exact same structure than Meteor 1.3.
When the gap between Meteor and Webpack is that small, whatâs the point of reinventing the wheel?
Beginners donât need to opt-in as soon as they learn but they could just by adding a few packages. What do you think?
Hey @faceyspacey I challenge you to put a max 100 Words/600 Characters tl;dr at the beginning of your posts.
FYI: That post has 2528 words & 15170 characters. At avg. tech reading wpm that is 15-20 min. Without replying.
So: I love your posts (they are full of great ideas ) but often thereâs no time to read it all (esp. on mobile) and I believe many people, incl. MDG Employees, feel the same way. A gist is great to navigate⌠I already feel bad not to be able to read it all due to work, real life, projects etc. Donât have your contributions fall under the table because it is too hard to stay on-top.
// off-topic over
This sounds amazing @benoitt ! I think this coupled with whatever folder structure MDG settles on (in their guides) for 1.3 would make for a killer setup. Having a default config with easy loader support solved 80% of use cases.
How would you handle builds?
@jeremybyu I think you should post the âgotchasâ over at the meteor issue tracker so that they reach the right audience and get resolved.
@benjamn Is there (or will there be) some API we can use to load modules over HTTP (or HTTP/2) at will? SystemJS has this so that itâs possible to load an entry point when you say so (and the entry point can use any of AMD, CJS, or ES2015 module formats). SystemJS will then know how to fetch all dependencies for that entry point (they can be separate files, all stuffed through a single HTTP/2 connection).
Yes, Iâm also interested in that to create a plugin platform for Wekan. These plugins would be loaded dynamically at runtime depending on the current board.
theyâve gone out of their way to make sure theyâre not just supporting straight up ES6 modules but also all backwards compatibility by supporting the old globals and load order, it sounds like you donât have anything to worry about
they specifically say âlazy evaluationâ to avoid that mishap. when I first read that I thought the same and almost jumped with excitement until I realized itâs just evaluation
I really like the idea of making Webpack stupid simple and hiding it behind some âMeteor magicâ, but I imagine a different approach to make it stupid simple for beginners.
If Meteor included a router in its core (and it really should!), or a common API for community routers to interact with, we could follow a convention for defining routes that includes the routing info and the entry points for that route. Iâve always liked the client/
server
/ both/
directory convention because it forces familiarity and structure, which IMO Meteor needs more of. Along those same lines, if we had a router in core we could define routes with something like this
// routes/login.js
export default {
route: '/login',
title: 'Log In',
entry: '../client/components/login.jsx',
styles: ['../client/styles/a.css', '../client/styles/b.css']
authenticated: false,
lazyLoad: true; //optional
}
// routes/home.js
export default {
route: '/home',
title: 'Home Page',
entry: '../client/components/home/entry.jsx',
authenticated: true, //this could use the core accounts package, maybe
//allow the user to define their own auth function here
//too if they use some other auth solution
failedAuthenticationRoute: '/login'
lazyLoad: true;
}
```
That way a router in the core could just require everything in the `/routes/...` directory and create a definition for each route based off of that. The build system could then use the same `/routes/...` directory to generate a bundle for each route by looking at what the `entry` file imports. Whether it used SystemJS or Webpack in the background wouldn't matter, and something like this would keep in line with the "Meteor" way of making advanced development features easy for complete noobs. It could also open up the possibility to server side rendering pretty easily. Dynamically generated routes would require some API to achieve the same affect.
This could be kept in a package so you could just do `meteor add routes` and you'd be set. I'd be one happy camper if we had something like that.
when will 1.3 be released? is it ok to use 1.3 features to develop new app right now?
I imagine you should be prepared to potentially make major changes as the release is being actively developed.