Meteor 1.3 *early beta* now available

Hey and thanks for the awesome beta! I just got a chance to try it out and it’s really looking nice!! :thumbsup:

I have a little (maybe dumb) question though:

How can I export a variable to the global namespace? Yes, I do understand that the idea is to prevent such thing, but sometimes it’s nice being able to play around with a variable in the browser console during development. E.g. if you’re trying to figure out how to deal with moment.js.

1 Like

I agree, which is why I made it a standard function in my projects now:

/lib/helpers.js:

export function globalizeData(mongoCollection, astroClass) {
  if (process.env.NODE_ENV === 'development') {
    global.Collections = Object.assign({}, global.Collections, mongoCollection);
    global.Models = Object.assign({}, global.models, astroClass);
  }
}

And then in my /lib/collections/whatever.js file:

globalizeData({MyCollection}, {SomeAstronomyClass});

The short answer: global.variableName = value

3 Likes

@wursttheke there’s a reliable global variable that you can assign properties to!

1 Like

I’m having some trouble with imports, all of a sudden (in beta 11).

Error: Cannot find module '../../../client/actions/audio'

But this worked before, and I didn’t change anything. /client/actions/audio also used to work fine, and that bombs too.

Is it not yet possible to deploy a 1.3 app to Meteor free hosting? Trying now and getting a refresh page with “this site has crashed…administrators can check the logs…” but the logs are bare save for /hit messages.

Any way around this or just patience?

Edit: False alarm. I was doing something doofy. Carry on :slight_smile:

1 Like

How long till it’s going to be released? Can’t wait.

1 Like

It seems that meteor only includes npm packages if the node_modules directory is in the same directory as the .meteor directory.

Is this correct? Is there a way to make meteor look for another location (like the parent directory)?

How do I take out the super annoying tests on the page?

What tests? Did you add some packages to your app that are adding tests?

Is there a guide for 1.3 already available as WIP? We want to start moving over to NPM packages but frankly have no idea at all about how to use NPM and the import syntax properly.

Here’s a README to get you started: https://github.com/meteor/meteor/blob/release-1.3/packages/modules/README.md

@benjamn: let’s say I have a file case.js, which contains a case model and should export it. Would I use export default Case; or just export Case? Or both? I think using default is rather bad, as people could name the import however they like, which might lead to inconsistent code.

And would something like the following work?

import { Meteor } from 'meteor/meteor';

export const Users = Meteor.users;

Object.keys(exports).forEach(function addDenyRules (collection) {
  exports[collection].deny({
    insert: () => true,
    update: () => true,
    remove: () => true
  });
});

Nothing inherently bad about export default. Someone could just as easily rename Case if you had done a plain export Case too:

import {Case as blahblahblah} from 'case';

My data/model files each have a Mongo collection and an Astronomy class in them, so I wind up doing this:

/lib/collections/games.js

export const Games = new Mongo.Collection('games');
export const Game = Astro.Class({
  // ...
});

That way I can import either or both as needed.

1 Like

Honestly we’re really not sure; there are arguments in both directions – In terms of recommendations we are going to see how the JS community in general goes with this.

At the moment I’ve been doing export default if there’s an obvious single thing a file exports.

5 Likes

I’ve also been usually exporting just a single thing from a file as default. It’s the easiest to write on both the export and import sides.

export default
class Foo extends Bar {...}

Using only default exports also makes code easier to statically analyze. The analyzer knows either the program needs the whole file, or it doesn’t. Exporting a bunch of named exports is more difficult to statically analyze, especially if one export depends on another export of the same file, because the analyzer also has to infer things from the code if the compile process wishes to prune unused code.

@trusktr do you have an example of that? I mean, I thought with the exception of rollup which does treeshaking, for all other aspects of import/exports its either file in or out. No inbetween. Not sure to what “compile process” you reference to?

You can both export and export default, but I think it’s always good to export a default even if you also export other stuff from a file. For example

import {Mongo} from 'meteor/mongo';

export default const Books = new Mongo.Collection('books');

export const nextChapter = function*(bookId) {
  let index = 0;
  const book = Books.findOne(bookId);
  while(index < book.chapters.length) {
    yield Chapters.findOne(book.chapters[index]);
    index+=1;
  }
}

Then if you are importing this module, the most common case is that you will get the collection, but in a more granulized way, you can also get other related functionality.

1 Like

@ffxsam @tmeasday @trusktr Thanks for your answers. I’ll omit default exports for now, as I think things should be consistent. The new ES6 module system would be much better without default exports IMO. Maybe there will be some recommendations in the future :slight_smile:

1 Like

@dinos I was speaking theoretically. But this strengthens the point of having files with single default exports, because then the set of files that are ever imported become the “tree-shaking” mechanism without need for actual tree-shaking analysis. So, with default exports/imports we can easily know if some file will be included in a bundle or not. That is more difficult to determine with files containing lots of named exports (in theory). So, if the compiler (in theory) is more simple and just includes whole files without dead-code-elimination, then having single default exports in every file is the method of choice to use for eliminating unused code in the compiled result (although that does mean more work splitting things into files compared to just naming exports in a single file). If you have a compiler (theoretical or not) that can perform sophisticated tree shaking, then bunching named exports together may not be a problem, but at least we know it won’t be a problem if we stick to single default exports.

Example: Suppose we have utilities.js that has tons of named exports. We can import like this:

import {one, two, three} from `./utilities`

The compiler would need to perform dead-code-elimination to drop unused code from utilities.js.

Now, suppose instead of named exports we put each export into separate files: utilities/one.js, utilities/two.js, utilities/three.js, etc. We can import like this:

import one from `./utilities/one`
import two from `./utilities/two`
import three from `./utilities/three`

That was more work to split the exports into separate files, and more verbose to import, but now the bundler only needs to include files that are ever imported, without needing to perform tree-shaking/dead-code-elimination, under the assumption that anything you ever import will be used.

It all depends on the use case too. For app code, use whichever is easier since you’re probably using 100% of your app code. But, when writing a library (like lodash, for example) make it easy to import specific things so that dead-code-elimination is implicit simply due to the end user importing only what’s needed. Library authors don’t know if the end user’s bundler will support dead-code-elimination, so using well-defined single default exports eliminates the need for the dead-code-elimination.

2 Likes