TL;DR we want to write the Meteor Guide using ES2015 modules, we need your help to find out what needs to be done in Meteor 1.3 to make this possible. Look at the list below and see if there are some concerns we missed!
Background
If you’ve been following along with the Meteor Guide, you know we’ve basically been writing it targeting Meteor as you can use it today - this means Meteor 1.2.1 and all of its flaws. In this spirit, we have been writing the app structure guide and example app in the packages-only style: all of the app code is organized in Meteor packages, which are currently the only way of achieving “modules” in a Meteor 1.2 app.
However, Ben’s working on adding first-class support for ES2015 modules - require
, import
, export
, and friends - which will be shipping as the big new feature in Meteor 1.3.
Given this and the challenges around building an app out of Meteor packages, I think @tmeasday and I have been considering writing the initial version of the guide targeting ES2015 modules instead of Meteor’s classic package-scope variables, load order, and eagerly-evaluated code.
To that end, today we had a productive discussion with @benjamn, @debergalis, and @zol to see what it would take to be able to ship Meteor 1.3 with modules and the first version of the Meteor Guide together.
What would it mean to have the first Meteor Guide target modules?
In order for the first version of the Meteor Guide to target ES2015 modules instead of the classic load order approach or package-first development, we would need to be absolutely sure that this is the best way to build apps in Meteor as of 1.3. The only way that can be true is if there are no hidden blockers for doing so - we need to make sure this stuff works with all of the crucial packages, patterns, and frameworks people are using to build their apps.
Topics that need to be discussed and resolved to write the Meteor Guide against ES2015 modules
In our meeting we basically went through the points one-by-one. I tried to write down the main points for discussion.
-
Testing: Realistically we need a sensible way to unit test a module in a reasonably isolated way.
- Ben: Perhaps testing just comes down to not eagerly-loading application code, and just loading the modules you want to test?
- Tom: Whole app testing might not actually be related to modules. We should just find out if we can simulate the
meteor test-packages
experience with a module. This is basically “compile the package as usual, but also include theonTest
files and dependencies”. - Ben: We could just have a “sub-app” in
test/
that is loaded when you are running tests, and those could have modules that are test-only. - Could we have
.meteor/packages
just specify which packages are test-only, dev-only, etc. For example, you could havemocha
as an app dependency, but only in test mode. - You’d also have an eagerly-loaded test runner where you can register tests to be run.
-
meteor test
could accept an argument that filters the tests based on the name they were registered with, or the module in which the tests are defined. Should also start a test database, etc. - Matt would like to see the hypothetical guide article that outlines how you write and run your tests in the module world. Then we can make sure the module system supports all of that.
- Tom will write the testing article against an idealized module system, if we ship the guide before modules ship, we’ll just omit that section or put it in some “future” area.
-
Blaze: How do blaze templates, which don’t have any concept of
import
/export
, work with this? Can you co-locate templates and their JS logic?- We could make these lazily evaluated, and only be executed when you import them
-
{{> templateName}}
meansTemplate.templateName
. In module world, do we need to firstimport templateName from ‘../module/templateName.html’
somehow? Answer: no, given the other discussions about Blaze/React, it’s not worth making major changes to the Spacebars syntax at the moment. - Sashko/Matt say - it’s OK if all template files are eagerly evaluated and work as they do now. Sashko says it’s important to him that all code can be put in the
imports
directory, including templates, so that we can make the code structure nice for the guide. - For further discussion: How important is it that feature code (JS, HTML, CSS, images, etc) can be co-located?
-
Build plugins: Do build plugins work as-is? how do you use modules with CoffeeScript, does this open up TypeScript? Have we compared what we are building to what is needed by the Angular/Angular2 community? What about CSS pre-processors?
- The dependency tree is analyzed based on the output code - so as long as the CoffeeScript compiler outputs
require(‘myFile.coffee’)
, we’ll detect that dependency. - LESS does all of its own importing and exports CSS, which could either be added as a style tag or a JavaScript resource. The CSS pre-processor stuff isn’t affected by ES2015 module work for Meteor 1.3, and will work just as before.
- The dependency tree is analyzed based on the output code - so as long as the CoffeeScript compiler outputs
-
Meteor package system: What’s it for? Should people start shipping reusable Meteor code on NPM as of 1.3?
- Meteor packages are really good at doing totally different things on the client and the server - you can set up the full stack just by adding the package
- For example, for DDP, you’d need to
import ‘ddp/client’
on the client andimport ‘ddp/server’
on the server if you want different functionality, but in a Meteor package you can just useddp
and it does the right thing. -
client/
andserver/
directories in NPM packages don’t have a special meaning at the moment, but they could - or we could have a specialpackage.json
format. Probably won’t tackle this for 1.3. - If you don’t have the above special build system requirements, there is basically no reason you need to publish your package on Atmosphere over NPM - this also removes the need for robotic wrapper packages that just re-bundle the same code that’s already on NPM.
-
Assets: What about assets like fonts and images? In the current package system, you can organize them in
package.js
, but in a Meteor app today you’d have to put everything inpublic/
. What do you do in module world?- Modules are about loading things that compile to JavaScript code
- Images aren’t something you would ‘require’ since there is no JavaScript content involved
- Perhaps you should be able to stick images anywhere in the app (not just
public/
), and have a sane way of referring to them - Idea from Sashko: Perhaps we want
getPathToAsset(‘../relative/path’);
, so that you can put images next to templates and refer to them without having to know the absolute path to the containing directory.
-
Apps with multiple entry points/UIs/services: Right now, you can have lots of packages and lots of apps, is this possible with modules? Do you need to make modules into NPM packages for this? Are Meteor packages still the way to go? If so, do you still need to list all of the files?
- Didn’t have time to address this in the meeting.
-
Cordova: Can you import Cordova plugins?
- We don’t yet have a good mental model here yet. It would be nice if you could import a cordova plugin, and make sure the necessary side effects run.
- These things can work like “legacy” meteor packages - the dependency scanner doesn’t need to understand them. This is one advantage over using Webpack in Meteor 1.3 - it assumes everything is a node-style JavaScript module.
-
File structure: Do we want to keep the
imports
directory convention proposed in the PR?- Ben says backwards compatibility with the existing loading logic was important to him, and
imports
is just one way to get that. - Other ways are special file names, special comments, etc.
- Matt says this directory should sound more “default” and less “opting into a fancy new feature”
- Ben said one big reason was that the LESS package picked this name.
modules
is another possibility, feels likenode_modules
. This is kind of a bike-shedding topic overall. - We could also have an app “control file” that just specifies entry point. Either a JSON file we can statically read, or a JavaScript file that just imports stuff inside conditionals somehow.
- Ben says backwards compatibility with the existing loading logic was important to him, and
Please give us feedback!
What concerns do you foresee in the world where a Meteor app is built our of ES2015 modules? Did we miss anything in our discussion/analysis? Please let us know!
Thanks,
Sashko