Skip to content
This repository has been archived by the owner on Jun 29, 2021. It is now read-only.

No more imports directory #135

Closed
marioblas opened this issue Jun 27, 2017 · 18 comments
Closed

No more imports directory #135

marioblas opened this issue Jun 27, 2017 · 18 comments

Comments

@marioblas
Copy link

Migrated from: meteor/meteor#8341

@marioblas marioblas changed the title [Feature] No more imports directory No more imports directory Jun 28, 2017
@benjamn benjamn added this to the Meteor 1.6.1 milestone Nov 1, 2017
@elie222
Copy link

elie222 commented Nov 5, 2017

I hope this one doesn't happen. We have a legacy project that still has a lot of code that relies on globals. All new code uses imports, but the fact that we can have both right now and old code doesn't break is amazing and it would be a big loss if we couldn't update to future versions of Meteor due to this change happening.

I don't fully understand the benefit of this change either. If you don't want globals don't use them. The current system allows for both which should make everyone happy.

@mitar
Copy link

mitar commented Nov 6, 2017

I think this should be done, but not be the default. It could be a flag in package.json which turns it on for the app. Also, new apps created with meteor create could have this flag turned on.

@crapthings
Copy link

no

@mitar
Copy link

mitar commented Nov 9, 2017

But it would be also important then to have a directory for client and server with "always import" semantics.

@theodorDiaconu
Copy link

theodorDiaconu commented Nov 14, 2017

Sometimes eager loading is useful, I find myself often creating a new meteor project, going directly to /server, and creating some methods, some api endpoints, and it just works nicely. But for a serious project I only have 2 proxy files in client/main.js and server/main.js that do nothing but import from /imports. It feels a bit stupid. I feel like Meteor is the perfect hybrid between fast prototyping and a serious enterprise app. We all started with it because of its simplicity, let's not take this away.

Besides this, I also think that eager-loading for client-side will be something useful later in the future, especially if a pattern will emerge that defines routing at component level (Just a hunch)

@route("/list")
class Component {}

If we want a complex solution we can go with something like:

package.json or meteor settings, or a special .meteor/config.js file (I can't say which is best))

"meteor-load": {
     "eager": {
        "client": ["./client"],
        "server": ["./server"], 
        "both": ["./lib"]
    },
    "entry": {
        "client": "./imports/startup/client/index.js",
        "server": "./imports/startup/server/index.js"
    }
}

But if we do this, what impact would it have on reloading ? Would we still benefit from a server-only restart if I modify something from server ?

Another elegant way I foresee is:

meteor --entry-client="" --entry-server=""
  • If we specify --entry of any kind => no eager loading applies.
  • These should also be specified when doing the build

@andyrichardson
Copy link

I think only importing files which are specified would be a huge improvement.

It would also allow for building inside of the project directory and preventing this error:

WARNING: The output directory is under your source tree.
Your generated files may get interpreted as source code!
Consider building into a different directory instead
meteor build ../output

@benjamn benjamn modified the milestones: Meteor 1.6.1, Meteor 1.6.2 Jan 10, 2018
@benjamn
Copy link
Contributor

benjamn commented Jan 10, 2018

Given the valid concerns that have been raised in this thread (thanks!), I just want to (re)assure you all that this feature will be implemented in a way that adds flexibility in terms of which directories/modules are eagerly loaded, rather than just eliminating the imports mechanism, and of course the changes will be opt-in—an important principle for us (i.e., backwards compatibility whenever possible).

benjamn pushed a commit to meteor/meteor that referenced this issue 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 above would cause that platform 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 informed 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.

For example, #8165 has been blocked for a long time because we haven't had
a standard way to specify a custom command to install npm packages. Once
we have a precedent for using the "meteor" section of `package.json`, it
will be much easier to consider additional options, even though we should
maintain a rigorous standard of necessity.
@benjamn
Copy link
Contributor

benjamn commented Feb 23, 2018

This is happening!

benjamn pushed a commit to meteor/meteor that referenced this issue 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.
@gaurav-
Copy link

gaurav- commented Mar 12, 2018

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.

@benjamn that's a very noble ulterior motive :) Personally. I'd be looking forward to simplifying the configuration of my meteor+webpack build after this upgrade.

How would it affect the "absolute" import paths though? i.e. would the equivalent of '/imports/module/path' be '/module/path' or module/path? I hope it's the latter; that would match the convention followed by most non-meteor apps using es modules.

@benjamn
Copy link
Contributor

benjamn commented Mar 12, 2018

It’s relative to the root directory of the application, so I think you would want imports/module/path or ./imports/module/path, without an initial / character.

If we made absolute imports (with an initial /) work (and I think we probably should, just for completeness), it would still be relative to the application root, not the file system root.

Does that answer your question?

@gaurav-
Copy link

gaurav- commented Mar 12, 2018

@benjamn, my question was actually entirely focused on the first paragraph of your answer. You're right that I want imports/module/path to work. So if I understood correctly, that's how it would be in 1.6.2 after opting-in to this feature, right?

Just to give you some more context of my setup: the imports directory of my app is a symlink to a common folder outside the meteor app, that is also used by webpack to bundle the client-side. This shared code has import paths like module/path. Thanks to babel-plugin-module-resolver and some webpack configuration, importing such "base paths" (without initial / or .) works the same way in both meteor and webpack builds.

As a side note, I've always found the absolute imports (with initial /) to be misleading because it's not the real root of the filesystem. I'm agnostic about supporting it with this new feature though, as long as it doesn't come at the cost of the behavior described above 🤞

@benjamn
Copy link
Contributor

benjamn commented Mar 12, 2018

If that setup works with Meteor now, I’m pretty sure we can keep it working with this feature, though I would encourage you to try the latest beta 1.6.2-beta.12 to be sure (there’s still plenty of time to fix it if it doesn’t work!).

@gaurav-
Copy link

gaurav- commented Mar 13, 2018

I tested a minimal app created with:

meteor create --release 1.6.2-beta.12 --minimal test-meteor-1.6.2

Works: import '/module/path';
Doesn't work: import 'module/path' (throws Error: Cannot find module 'module/path')

Can't test my whole app for now, but hope to do so some time next week.

If it's open for consideration, I'd suggest supporting the base path imports so that:

  1. Meteor can remove yet another point of surprise, since import paths with initial / seem to be uncommon in other popular conventions like create-react-app.
  2. It would be (relatively) easier to share the same code between meteor and other bundlers. In my own case, I'd be able to reduce (maybe even eliminate) the configuration code specifically for that purpose.

@benjamn
Copy link
Contributor

benjamn commented Mar 27, 2018

@gaurav- You need to do import ./module/path, otherwise it looks like you're importing the path module from a module package installed in node_modules. Changing this behavior is not open for consideration, since this is how the entire Node/CommonJS/ECMAScript ecosystem works.

@merlinstardust
Copy link

Which release is the mainModule in and when will it be the official release? I discovered via History.md that 1.7 is available, but there's nothing on the blog, and it was not the set release for my new project yesterday.

@benjamn benjamn modified the milestones: Meteor 1.6.2, Meteor 1.7 Jun 6, 2018
@benjamn
Copy link
Contributor

benjamn commented Jun 6, 2018

@merlinpatt Meteor 1.7 (and 1.7.0.1) has it!

Given that new Meteor apps no longer need an imports/ directory (because they use meteor.mainModule), and existing Meteor apps can opt into this functionality, I think we've satisfied the spirit of this feature request!

@benjamn benjamn closed this as completed Jun 6, 2018
@sakulstra
Copy link

follow up question here :)
is cordova treated as modern or legacy or is there a separate entry point - which one is used if none is specified for cordova?

@awatson1978
Copy link

What great work. Thank you, thank you, thank you! Finally refactored the /imports directory to /client/app and then back to /app. So great to have back the ability to structure the directory layout how we want!!! Thank you!!!!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests