Although there was a comment in this code about not applying .meteorignore
files to the contents of node_modules directories, I'm pretty sure that
was the wrong decision, because .meteorignore merely limits what Meteor
tries to compile as application code, and does not actually modify or hide
node_modules files from other parts of Meteor (or Node).
In other words, there's no harm in letting .meteorignore apply to
node_modules, and there may be a LOT of benefit, because it allows the
developer to fight back when compilation descends unexpectedly into an npm
package that contains non-.js[on] files for which a compiler plugin has
been registered, an obscure but not uncommon behavior originally intended
to allow importing CSS assets from npm packages:
* https://github.com/meteor/meteor/issues/6037
* 43659ff561
* a073280e3f
* https://github.com/meteor/meteor/issues/5242
* https://github.com/meteor/meteor/issues/6846
* https://github.com/meteor/meteor/issues/7406
However, we now have a much more powerful tool for selectively compiling
specific npm packages: #9771. In light of this new approach, we should
probably remove the promiscuous node_modules compilation behavior
altogether, as it might speed up rebuild times for many applications whose
developers don't know or care that this behavior exists. For example,
abandoning this behavior would prevent the problem reported here:
https://github.com/meteor/meteor/issues/6950
In the meantime, this commit makes .meteorignore work for node_modules.
Before this change,
meteor create --list
would produce output containing the following line:
todos-react: https://github.com/meteor/todos#react
but "meteor create --example todos-react" would create the blaze version of the todos example.
This was because for some reason the code is using a # to append the name of the branch, instead of /tree/.
Console.isInteractive() will be false during our Circle CI test runs,
since we set the METEOR_HEADLESS environment variable, so this change
should help prevent spurious test failures like these:
https://circleci.com/gh/meteor/meteor/15305.
If a package in node_modules needs to be compiled for older browsers,
simply symlink the package directory into your application somewhere, and
then import the package as you normally would.
Because of the symlink, code within the package will be compiled as if it
was part of your application, and any imports that refer to modules in the
package will automatically use the compiled code rather than the raw code
from node_modules.
Note that you can also symlink individual files to make them be compiled
like application modules, rather than linking an entire package directory.
Creating symlinks could be considered a form of configuration, but
otherwise this is a zero-configuration solution to selectively compiling
packages within node_modules, which has been something of a holy grail in
the JavaScript community lately.
https://github.com/meteor/meteor-feature-requests/issues/6
The bulk of this commit implements `builder.copyNodeModulesDirectory` to
allow more than one `node_modules` directory to be copied to the same
destination with as much safe symlinking as possible.
However, the crux of the fix for #9738 is the removal of the call to
`builder.generateFilename`, which deserves additional explanation.
If multiple directories are copied to the same output path by the builder,
in some cases it makes sense to ensure distinct directory names by adding
numeric suffixes to some of the directories.
In general, `builder.generateFilename` can get away with this renaming
only if the exact names of the directories are an implementation detail.
However, the code changed by this commit was altering the names of
`node_modules` directories whenever a package had both an `Npm.depends`
and a local `node_modules` directory.
Not only is it totally invalid to change the name of a `node_modules`
directory, but there is also no harm in copying the contents of multiple
`node_modules` directories into one final directory called `node_modules`.
Should fix#9738.
This should shave down bundle sizes by 14.4 kb for many non-blaze projects.
The other core meteor packages have not depended on `underscore` since #9362. However, we are only able to remove this last dependency now due to the previous commit, which eliminated usages of `underscore` from apps that did not have the package listed in their `packages` files. This was causing CI test failures that now should be corrected.
Any meteor apps currently using `_` without `underscore` listed in their `packages` file will need to add the package explicitly.
Version number of `meteor-base` bumped from 1.3.0 to 1.4.0.
There are only a few uses of `underscore` in these apps, and two of them actually used `underscore` without having it explicitly listed in their `packages` file.
This is a problem, because the apps were relying on the dependency from `meteor-base`, which we want to remove to cut down bundle sizes.
For the `modules` test app, I've added `underscore` to the `packages` file, because it is using `_` in an assertion about the module system. For the other app and all other uses of `_`, rather than add `underscore` to the `packages` files, I took the modernization route and replaced the functions with their ES6 equivalents, and then removed `underscore` from all `packages` files.
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.
Setting meteor.testModule is a great way to specify test entry points
explicitly, rather than relying on Meteor's isTestFilePath heuristics:
https://github.com/meteor/meteor/blob/devel/tools/isobuild/test-files.js
The syntax is identical to meteor.mainModule, so you can set an explicit
meteor.testModule.{client,server,...} for each platform. If a testModule
is not specified for a platform, then Meteor's existing rules about test
file paths apply for that platform, as before.
If a testModule is specified, that module will always be loaded eagerly
when running `meteor test`, in addition to any other modules that load
eagerly because of meteor.mainModule or other rules regarding module
loading. If you run `meteor test` without the `--full-app` option, then no
application JS modules other than the testModule (and any modules imported
by it) will be loaded eagerly.
If meteor.mainModule.{client,server,...} === false, no modules will be
loaded eagerly for that architecture. This is useful if you have an app
with no special app/{client,server} directory structure and you want to
specify an entry point for just the client (or just the server), without
accidentally loading everything on the other architecture.
Determining if Meteor package files should be loaded lazily or eagerly is
a lot easier than doing so for application files, so we should just do
that separately, to avoid any risk of application directory layout logic
interfering with package behavior.
https://github.com/meteor/meteor-feature-requests/issues/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.