Adjust Meteor build rules

I’m not satisfied with Meteor’s special directories and file load order rules.

For example, I would like to have this file structure:

myapp/
  .meteor/
  app/
    base/
      base.css
      base.html
    comments/
      img/
        new-comment.png
        submit.png
      comments.server.js
      comments.client.js
      comments.js
      comments.html
      comments.css
    payments/
      payments.server.js
      payments.js
    ...

And, as a result, to achieve this:

  1. base.css should be loaded before other css files
  2. *.server.js/*.client.js files should be loaded to server/client only
  3. *.js files should be loaded to both: client and server
  4. *.js files should be loaded after *.server.js and *.client.js files
  5. media assets (images, icons, etc) should be available by url /assets/{moduleName}/{assetName} (e.g. /assets/comments/new-comment.png)

But Meteor forces me to write:

myapp/
  .meteor/
  app/
    base/
      lib/
        base.css
      base.html
    comments/
      client/
        comments.client.js
      server/
        comments.server.js
      lib/
        comments.js
      comments.html
      comments.css
    payments/
      server/
        payments.server.js
      lib/
        payments.js
  public/
    assets/
      comments/
        new-comment.png
        submit.png

Which kills all the beauty.


So I was thinking, is it possible to change Meteor’s behaviour? And the answer is Yes (with some limits).

Now I’m working on package called imkost:project-builder which will allow to create your own build rules for Meteor applications.

It’s about to be finished soon. I already tried project-builder in my project and… it sounds sort of selfish, I really love it!


What do you guys think of this? Is it a common issue or it’s just me who suffers from Meteor’s build rules?

1 Like

That something I would like to play with, even if I’m not sure how powerful a community package can get at this sort of fundamental build operations. Did you release the source code? I guess you are using the upcoming “batch” plugin API?

Also a while back there was this hackpad about a new way to control the build process. More recently @slava shared a proposal to re-factor the build tool into a stream-based model. I was excited by these two proposals, but I guess there were somehow too ambitious given the MDG and meteor community limited labor-resources. It seems we are now going with a more incremental approach, and I’m curious how much we can achieve using a community package such as yours.

Could you expands on these limits?

One other piste to explore, that would probably allow much more powerful control, would be to fork the meteor-tool package and release it as a meteor track (something like IMKOST-PROJECT-BUILDER@1.1.0.4).

No, I don’t use upcoming “batch” API. I read about new Build Plugins API and I would like to play with it when 1.2 comes out, but for now, implementation of project-builder is pretty primitive. It uses basic Meteor API for build-plugins.

I haven’t released source code yet, will do it in a few days.

Yeh, it would be cool to fork Meteor and create IMKOST-PROJECT-BUILDER) but I’m not really familiar with Meteor source code, I don’t even know where to start from. And project-builder is an almost ready solution which is easy-to-install (it’s just a package) and it works for me. There are some limitations, but they are not very critical (at least for me).


Workflow

You write application in private folder and every time you do changes, project-builder “compiles” your files to anywhere you say.

Let me show an example:

myapp/
  private/
    app/
      app.server.js
      app.client.js
      app.js
      app.html
      app.css

Then I define some rules for project-builder, project-builder will apply these rules and I will get:

myapp/
  _app/
    scripts/
      server/
        app.server.js
      client/
        app.client.js
      lib/
        app.js
    templates/
      app.html
    styles/
      app.css
  private/
    app/
      ...

Then Meteor will read application from _app directory. That’s how it works.


Limitations

I have to exclude _app folder from my code editor and add _app to .gitignore. In other words I have to “forget”, that _app even exists.

So limits are:

  1. You have to write application inside private directory
  2. “Compilation” step will add some additional time to build process
  3. You have to “forget” about folders where application is builded to

By the way, project-builder don’t “compile” all of the files every time. If you change base.html file then only it will be “compiled”.


Syntax

If you are interested of how rules are defined, here is a proposal syntax:

// packages/builder/builder.js
builder.watchDirectoryFiles('private/app', function(file) {
  var filename = file.name;
  var ext = file.ext;
  
  if (ext === 'css') {
    return file.buildTo('_app/styles');
  }
  
  if (ext === 'html') {
    return file.buildTo('_app/templates');
  }
  
  if (ext === 'js') {
    if (filename.indexOf('.server.js')) >= 0) {
      return file.buildTo('_app/scripts/server');
    }
    
    if (filename.indexOf('.client.js') >= 0) {
      return file.buildTo('_app/scripts/client');
    }
    
    file.buildTo('_app/scripts/lib');
  }
});

So you just build your project structure to one, which Meteor will understand.