New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support a meteor.mainModule section in application package.json files. #9690

Merged
merged 5 commits into from Feb 23, 2018

Conversation

Projects
None yet
7 participants
@benjamn
Member

benjamn commented Feb 23, 2018

meteor/meteor-feature-requests#135

This change allows applications to specify specific entry points for each architecture, without relying on imports directories to determine the eagerness/laziness of modules. In other words, it will finally be possible to build a Meteor app without a special imports directory.

Specifically, if packageJson.meteor.mainModule[architecture] is defined, all modules for that architecture will be lazy except for the specified module, which will be loaded eagerly.

Possible values for architecture include "client", "server", "web", "web.browser", "web.cordova", "os", and so on, just like the second argument to api.mainModule(file, where) in Meteor packages.

In order to match existing behavior, a Meteor application might include the following in its package.json file:

"meteor": {
  "mainModule": {
    "client": "client/main.js",
    "server": "server/main.js"
  }
}

These architectures are handled independently, so omitting the "client" or "server" property would cause that architecture to revert to standard Meteor loading semantics. In other words, Meteor developers must opt into this functionality, which is crucial for backwards compatibility.

Note that this functionality applies only to application modules, since modules in Meteor packages are already lazy by default, and Meteor packages can already specify entry points by calling api.mainModule in their package.js files.

Also note that the loading behavior of non-JavaScript resources is not affected by packageJson.meteor.mainModule. Only resources added by compiler plugins via addJavaScript are subject to the new configuration option. If a compiler plugin calls addStylesheet or addHtml, those resources will still be included unconditionally in the HTML document rendered by the web server. While you could try to import these resources from JavaScript, you would only be importing any JavaScript resources the compiler plugin registered using addJavaScript, and not the actual HTML or CSS resources. I welcome feedback on this decision, but if there's no meaningful way to import a resource, making it lazy just means it won't be loaded at all.

An ulterior motive for this feature is to enable Meteor apps to have directory layouts that developers who are not familiar with Meteor can immediately understand. The special meaning of the imports directory and the surprising eagerness of modules outside of imports have always required some explanation, so this change should reduce that surprise.

Because Meteor strives to be a zero-configuration tool, this is currently the only supported option in the "meteor" section of package.json, though the available options may be expanded in the future if that's the best/only way to solve important problems. This would involve adding additional methods to the MeteorConfig class in project-context.js, and then using those methods elsewhere in the meteor/tools codebase.

@benjamn benjamn added this to the Release 1.6.2 milestone Feb 23, 2018

@hwillson

This all looks great @benjamn!

benjamn added some commits Feb 23, 2018

Support a meteor.mainModule section in application package.json files.
meteor/meteor-feature-requests#135

This change allows applications to specify specific entry points for each
architecture, without relying on `imports` directories to determine the
eagerness/laziness of modules. In other words, it will finally be possible
to build a Meteor app without a special `imports` directory.

Specifically, if `packageJson.meteor.mainModule[architecture]` is defined,
all modules for that architecture will be lazy except for the specified
module, which will be loaded eagerly.

Possible values for `architecture` include "client", "server", "web",
"web.browser", "web.cordova", "os", and so on, just like the second
argument to `api.mainModule(file, where)` in Meteor packages.

In order to match existing behavior, a Meteor application might include
the following in its `package.json` file:

  "meteor": {
    "mainModule": {
      "client": "client/main.js",
      "server": "server/main.js"
    }
  }

These architectures are handled independently, so omitting the "client" or
"server" property would cause that architecture to revert to standard
Meteor loading semantics. In other words, Meteor developers must opt into
this functionality, which is crucial for backwards compatibility.

Note that this functionality applies only to application modules, since
modules in Meteor packages are already lazy by default, and Meteor
packages can already specify entry points by calling `api.mainModule` in
their `package.js` files.

Also note that the loading behavior of non-JavaScript resources is *not*
affected by `packageJson.meteor.mainModule`. Only resources added by
compiler plugins via `addJavaScript` are subject to the new configuration
option. If a compiler plugin calls `addStylesheet` or `addHtml`, those
resources will still be included unconditionally in the HTML document
rendered by the web server. While you could try to import these resources
from JavaScript, you would only be importing any JavaScript resources the
compiler plugin registered using `addJavaScript`, and not the actual HTML
or CSS resources. I welcome feedback on this decision, but if there's no
meaningful way to import a resource, making it lazy just means it won't be
loaded at all.

An ulterior motive for this feature is to enable Meteor apps to have
directory layouts that developers who are not familiar with Meteor can
immediately understand. The special meaning of the `imports` directory and
the surprising eagerness of modules outside of `imports` have always
required some explanation, so this change should reduce that surprise.

Because Meteor strives to be a zero-configuration tool, this is currently
the only supported option in the "meteor" section of `package.json`,
though the available options may be expanded in the future if that's the
best/only way to solve important problems. This would involve adding
additional methods to the `MeteorConfig` class in `project-context.js`,
and then using those methods elsewhere in the `meteor/tools` codebase.

@benjamn benjamn force-pushed the meteor-config-mainModule branch from 7303de0 to 31c39f0 Feb 23, 2018

@abernix

Brief comments, but this LGTM. This will certainly make code written outside the Meteor-mindset more easily introducible into a Meteor project, and that's super exciting!

}
_ensureInitialized() {
if (! _.has(this, "_config")) {

This comment has been minimized.

@abernix

abernix Feb 23, 2018

Member

This file certainly isn't void of Underscore usage, but any particular reason for introducing new _ usage here?

This comment has been minimized.

@benjamn

benjamn Feb 23, 2018

Member

There's just so much _ already there, I'm sure someone will clean this up whenever project-context.js gets modernized.

// Use a Resolver to allow the mainModule strings to omit .js or
// .json file extensions, and to enable resolving directories
// containing package.json or index.js files.

This comment has been minimized.

@abernix

benjamn added some commits Feb 23, 2018

@benjamn benjamn self-assigned this Feb 23, 2018

@benjamn

This comment has been minimized.

Member

benjamn commented Feb 23, 2018

Related to my last paragraph above, #8165 has been blocked for a long time because we never decided on a way to specify configuration options (like a custom command to install npm packages). Once we've established this precedent for using the "meteor" section of package.json, it will be much easier to consider additional options, though I think we should maintain a rigorous standard of necessity and backwards compatibility.

@benjamn benjamn merged commit 5cc7176 into devel Feb 23, 2018

18 checks passed

CLA Author has signed the Meteor CLA.
Details
ci/circleci: Docs Your tests passed on CircleCI!
Details
ci/circleci: Get Ready Your tests passed on CircleCI!
Details
ci/circleci: Group 0 Your tests passed on CircleCI!
Details
ci/circleci: Group 1 Your tests passed on CircleCI!
Details
ci/circleci: Group 10 Your tests passed on CircleCI!
Details
ci/circleci: Group 11 Your tests passed on CircleCI!
Details
ci/circleci: Group 2 Your tests passed on CircleCI!
Details
ci/circleci: Group 3 Your tests passed on CircleCI!
Details
ci/circleci: Group 4 Your tests passed on CircleCI!
Details
ci/circleci: Group 5 Your tests passed on CircleCI!
Details
ci/circleci: Group 6 Your tests passed on CircleCI!
Details
ci/circleci: Group 7 Your tests passed on CircleCI!
Details
ci/circleci: Group 8 Your tests passed on CircleCI!
Details
ci/circleci: Group 9 Your tests passed on CircleCI!
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

benjamn added a commit that referenced this pull request Mar 1, 2018

Use meteor.{mainModule,testModule} for `meteor create` starter apps.
In order for Meteor to maintain its commitment to being a
zero-configuration tool, any configuration options that we add must come
pre-configured in the best way possible for newly created apps.

In particular, the default new Meteor app must contain a reasonable
testing story, or else we are signalling to the community that testing is
an afterthought.

With that said, this PR is still a work in progress. I welcome your
feedback on how best to configure the default `meteor create` starter app.

Builds on #9690 and #9714.
@pravdomil

This comment has been minimized.

Contributor

pravdomil commented Mar 8, 2018

if anybody is interested I've created package that searches for meteor.mainModule in node_modules and it imports corresponding entry points into your app

https://github.com/pravdomil/Support-meteor-mainModule-in-node_modules/

@mitar

This comment has been minimized.

Collaborator

mitar commented Apr 22, 2018

In history, it is written:

To disable eager loading of modules on a given architecture, simply provide a mainModule value of false:

I do not get this. What does this mean? If you set it to false, how anything loads?

@benjamn

This comment has been minimized.

Member

benjamn commented Apr 23, 2018

@mitar You might have an app that's purely server-side or purely client-side, as far as application code is concerned. Of course Meteor packages can still load server and/or client code however they please.

@mitar

This comment has been minimized.

Collaborator

mitar commented Apr 23, 2018

Interesting, thanks.

@Batistleman

This comment has been minimized.

Batistleman commented May 6, 2018

Awesome! Would the following configuration work for a 'default' meteor setup?

"meteor": {
  "mainModule": {
    "client": "client/",
    "server": "server/"
  }
}

And how does does the new system relate to reloading files (server/client) in development mode?

@steph643

This comment has been minimized.

steph643 commented Jun 7, 2018

Just tested this new feature: amazing!

I think it is unfortunate entry points are only for js files. Having one rule for all files would be easier to explain and understand. Additionally, wouldn't this allow to include different ressources for modern and legacy browsers? Also, this would be useful to quickly enable/disable some CSS during testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment