Meteor 1.3 === import statements everywhere?

(I know this technically isn’t Meteor-specific and more about es6 modules in general, but since a big part of 1.3 is modules…)

  • I am currently migrating a 1.2.x app to Meteor 1.3 beta
  • I am also using React and adding it via npm.
  • This means, as I understand it, that I will need to have the following at the top of every file that uses React :
import React from 'react'

This does not feel very DRY to me. Is there a better way? For example, can I somehow import React once for all files in a directory?

3 Likes

in the browser environment you can always add a variable to the global window object, in node there’s a global global object. So if you want React global, on startup you can say something like

import React from 'react';

function makeGlobal(key,var){
   if(typeof window !== 'undefined'){ window[key] = var; }
   if(typeof global !== 'undefined'){ global[key] = var; }
}

makeGlobal('react',React);

or something like that, then you should just have access to the react variable everywhere. although I’m not sure how 1.3 handles providing a window and global object between environments

But that makes it global for every file. Not what he wants.

Besides, DRY is a guideline, not a law. Those few import statements? My C# classes look way worse…

using App.DataProvider;
using App.Models;
using App.Structs;
using Microsoft.Practices.Unity;
using Microsoft.WindowsAzure.MobileServices.Sync;
using Prism.Commands;
using Prism.Events;
using Prism.Windows.Mvvm;
using Prism.Windows.Navigation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;

Just one example of the 100+ classes in my project.

1 Like

oh good point I didn’t realize he specified “for all files in a directory”, idrk if that’s possible. I guess you could add a build step that adds the import react from 'react'; makeGlobal('react',react') to the top of each file in the directory you choose, but at that point @andersr I’d say you should really just import them anyways. imports are a lot more explicit and give any reader an exact idea of what outside code is being used in a module, and it’s helpful for build steps like tree shaking and building chunks of code for code splitting

You only need it for your .jsx components that are stateful. Looking over my project, that’s about 1/3 of them. The others will import a whole bunch of other useful things like lodash, enums, collections etc…

Not aware of a global way to import things and if you start hiding it then it’s not going to be obvious to the guy looking at that file, what it uses. Kinda goes back to the global architecture of meteor before 1.3

1 Like

@rhywden and @efrancis - thanks for feedback and suggestions.

Yes, a build step might be the way to go. I’m thinking something like auto-import and then have an index.js file at the top of your components directory.

Yes, I can appreciate all the reasons why having an explicit import can be good, but when you are repeating the same code again and again in every file, well, that just starts to smell like something isn’t right.

@mordrax - excellent point. That will help in thinking twice if a component really needs to be a Component, so to speak.

Personally I can’t stand looking at code that is using a bunch of variables and it’s not clear where they come from. React isn’t one of those, but in general I think having the imports listed at the top is a great idea. I bet there are JavaScript IDEs that will help with identifying missing imports and stuff already.

21 Likes

When refactoring code as I seem to be perpetually doing, Webstorm works well to catch those pesky ‘blah is undefined’ as there is visual clues when one is using a import that hasn’t been imported or doesn’t have the exposed property you’re importing. You can Ctrl+Click to go to the method that’s been imported.

2 Likes

Agree completely, then if a glitch comes around, you can follow the import path directly to it than using some search to track it down. Much easier

I’ve been working on updating a client’s Meteor app to 1.3 during this beta process.

For me, the greatest strength of explicit imports is that it helps developers, not their editors or tools, to define and reason about the structure of their code base.

There are now more files and imports but far less reliance on passive dependency loading. What I mean is that Meteor 1.2 apps will load code anywhere but which leads to hidden dependencies across wide swaths of your code base.

In my application this lead to disorganized patterns like A) keeping everything in large files, or B) breaking changes when removing code that something else held a dependency on in some other file that just happened to be loaded at the end of Meteor 1.2’s load order.

While I’ve mainly utilized the app structure of meteor/todos I’ve also found a few other idioms that help reduce and isolate imports. Here’s one…

Create nested entry points within your application named after various features or topics. Import everything within a directory contained within it’s own index.js. This allows importing the whole “directory” somewhere else more on index.js module semantics.

import '/imports/api/people' => imports/api/people/index.js

This works exactly like NPM/CommonJS.

Hope that helps.

2 Likes

Do you think this would be a good thing to add to the Todos example?

That’s a great idea. I can come up with a PR that does this under /imports/ui for subdirectories like /imports/ui/components or /imports/ui/pages. ui is where I’ve found the pattern most useful anyway.

I think the best first step would be to open an issue so that we can talk about it. The example app is @tmeasday’s domain, I’d like to get his take on it.

I think it sounds great! We can talk on a issue or just on the PR if it’s not too onerous

I mean you could have a file that imports your common imports for a directory and exports them again, if you are really so worried about this, something like:

import { Meteor, React, Tracker, Todos, Lists } from './common-imports.js';

I would absolutely, strongly advocate against trying to make it happen automagically without any lines of code. I guess it’s a matter of preference but there’s a reason why the vast majority of programming languages make you write this kind of boilerplate.

Expect to see auto-linking of Meteor globals be deprecated in the near future (not 1.3 though).

6 Likes

I agree with Tom with this. We used magical global for a long time and it didn’t bring us any good rather issues.

So, importing everything is a pretty good idea. That’s might not be DRY, but it will lead to better maintainable projects in the long run.

We can later on build tools to do common stuff and code generation.

4 Likes

I’d like to reiterate: DRY is a guideline, not a law.

This goes for several developing principles - terse versus verbosity, for example.

1 Like

I don’t think DRY really applies here.DRY is about avoiding duplication of logic so there’s a single source of truth for business logic and UI behaviour, particularly to avoid the bugs that come from having the same logic in multiple places and then forgetting to update one of them. Import statements aren’t part of that for me, they are wiring not logic.

4 Likes

Yes, code generation!