mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge pull request #10545 from meteor/compile-Npm.depends-packages-with-ESM-entry-points
Allow .npm/package/node_modules to be compiled in Meteor packages.
This commit is contained in:
@@ -65,7 +65,7 @@ const hasOwn = Object.prototype.hasOwnProperty;
|
||||
// Cache the (slightly post-processed) results of linker.fullLink.
|
||||
const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100;
|
||||
const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG;
|
||||
const LINKER_CACHE_SALT = 22; // Increment this number to force relinking.
|
||||
const LINKER_CACHE_SALT = 23; // Increment this number to force relinking.
|
||||
const LINKER_CACHE = new LRU({
|
||||
max: CACHE_SIZE,
|
||||
// Cache is measured in bytes. We don't care about servePath.
|
||||
|
||||
@@ -34,7 +34,7 @@ var compiler = exports;
|
||||
// dependencies. (At least for now, packages only used in target creation (eg
|
||||
// minifiers) don't require you to update BUILT_BY, though you will need to quit
|
||||
// and rerun "meteor run".)
|
||||
compiler.BUILT_BY = 'meteor/32';
|
||||
compiler.BUILT_BY = 'meteor/33';
|
||||
|
||||
// This is a list of all possible architectures that a build can target. (Client
|
||||
// is expanded into 'web.browser' and 'web.cordova')
|
||||
|
||||
@@ -375,6 +375,27 @@ export default class ImportScanner {
|
||||
_checkSourceAndTargetPaths(file) {
|
||||
file.sourcePath = this._getSourcePath(file);
|
||||
|
||||
// If we're scanning a Meteor package (as indicated by this.name), and we
|
||||
// come across a file whose sourcePath starts with .npm/, it's a file that
|
||||
// was installed by Npm.depends, so we should reroot it relative to one of
|
||||
// this.nodeModulesPaths, rather than preserving the .npm/ path.
|
||||
if (this.name && file.sourcePath.startsWith(".npm/")) {
|
||||
const parts = file.sourcePath.split("/");
|
||||
const nmi = parts.indexOf("node_modules");
|
||||
if (nmi >= 0) {
|
||||
const suffix = parts.slice(nmi + 1).join("/");
|
||||
this.nodeModulesPaths.some(nodeModulesPath => {
|
||||
const newAbsPath = pathJoin(nodeModulesPath, suffix);
|
||||
if (optimisticStatOrNull(newAbsPath)) {
|
||||
file.sourcePath = file.targetPath =
|
||||
pathRelative(this.sourceRoot, newAbsPath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (! isString(file.targetPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -426,6 +426,9 @@ _.extend(PackageSource.prototype, {
|
||||
sourceRoot: self.sourceRoot,
|
||||
uses: _.map(options.use, splitConstraint),
|
||||
getFiles() {
|
||||
// TODO We might want to call _findSources here, if we want plugins to
|
||||
// be able to import compiled files that were not explicitly included in
|
||||
// the sources array passed to Package.registerBuildPlugin.
|
||||
return {
|
||||
sources: sources
|
||||
}
|
||||
@@ -1298,10 +1301,6 @@ _.extend(PackageSource.prototype, {
|
||||
|
||||
subdirectories.forEach(subdir => {
|
||||
if (/(^|\/)node_modules\/$/.test(subdir)) {
|
||||
if (! inNodeModules) {
|
||||
sourceArch.localNodeModulesDirs[subdir] = true;
|
||||
}
|
||||
|
||||
// Defer handling node_modules until after we handle all other
|
||||
// subdirectories, so that we know whether we need to descend
|
||||
// further. If sources is still empty after we handle everything
|
||||
@@ -1309,21 +1308,29 @@ _.extend(PackageSource.prototype, {
|
||||
// imported by anthing outside of it, so we can ignore it.
|
||||
nodeModulesDir = subdir;
|
||||
|
||||
// A "local" node_modules directory is one that's managed by the
|
||||
// application developer using npm, rather than by Meteor using
|
||||
// Npm.depends, which is available only in Meteor packages, and
|
||||
// installs its dependencies into .npm/*/node_modules. Local
|
||||
// node_modules directories may contain other nested node_modules
|
||||
// directories, but we care about recording only the top-level
|
||||
// node_modules directories here (hence !inNodeModules).
|
||||
if (!inNodeModules && (isApp || !subdir.startsWith(".npm/"))) {
|
||||
sourceArch.localNodeModulesDirs[subdir] = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
sources.push(...find(subdir, depth + 1, inNodeModules));
|
||||
}
|
||||
});
|
||||
|
||||
if (isApp &&
|
||||
nodeModulesDir &&
|
||||
(! inNodeModules || sources.length > 0)) {
|
||||
if (nodeModulesDir && (!inNodeModules || sources.length > 0)) {
|
||||
// If we found a node_modules subdirectory above, and either we
|
||||
// are not already inside another node_modules directory or we
|
||||
// found source files elsewhere in this directory or its other
|
||||
// subdirectories, and we're building an app (as opposed to a
|
||||
// Meteor package), continue searching this node_modules
|
||||
// directory, so that any non-.js(on) files it contains can be
|
||||
// imported by the app (#6037).
|
||||
// subdirectories, continue searching this node_modules directory,
|
||||
// so that any non-.js(on) files it contains can be imported by
|
||||
// the app (#6037).
|
||||
sources.push(...find(nodeModulesDir, depth + 1, true));
|
||||
}
|
||||
|
||||
@@ -1336,7 +1343,27 @@ _.extend(PackageSource.prototype, {
|
||||
return sources;
|
||||
}
|
||||
|
||||
return files.withCache(() => find("", 0, false));
|
||||
const sources = find("", 0, false);
|
||||
|
||||
if (!isApp && typeof this.npmCacheDirectory === "string") {
|
||||
// If this PackageSource has an npmCacheDirectory, scan it as well for
|
||||
// sources that might need to be compiled.
|
||||
const stat = optimisticStatOrNull(this.npmCacheDirectory);
|
||||
if (stat && stat.isDirectory()) {
|
||||
const relNpmDir = files.pathRelative(
|
||||
this.sourceRoot,
|
||||
this.npmCacheDirectory,
|
||||
);
|
||||
if (! relNpmDir.startsWith("..")) {
|
||||
const relParts = relNpmDir.split("/");
|
||||
const depth = relParts.length;
|
||||
const inNodeModules = relParts.indexOf("node_modules") >= 0;
|
||||
sources.push(...find(relNpmDir, depth, inNodeModules));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sources;
|
||||
}),
|
||||
|
||||
_findAssets({
|
||||
|
||||
@@ -251,6 +251,7 @@ export class Unibuild {
|
||||
|
||||
// Figure out where the npm dependencies go.
|
||||
let node_modules = {};
|
||||
let nonLocalNodeModulesBundlePath;
|
||||
_.each(unibuild.nodeModulesDirectories, nmd => {
|
||||
const bundlePath = _.has(npmDirsToCopy, nmd.sourcePath)
|
||||
// We already have this npm directory from another unibuild.
|
||||
@@ -258,6 +259,9 @@ export class Unibuild {
|
||||
: npmDirsToCopy[nmd.sourcePath] =
|
||||
nmd.getPreferredBundlePath("isopack");
|
||||
node_modules[bundlePath] = nmd.toJSON();
|
||||
if (!nmd.local) {
|
||||
nonLocalNodeModulesBundlePath = nonLocalNodeModulesBundlePath || bundlePath;
|
||||
}
|
||||
});
|
||||
|
||||
const preferredPaths = Object.keys(node_modules);
|
||||
@@ -315,13 +319,37 @@ export class Unibuild {
|
||||
});
|
||||
|
||||
// Output other resources each to their own file
|
||||
_.each(unibuild.resources, function (resource) {
|
||||
_.each(unibuild.resources, resource => {
|
||||
if (_.contains(["head", "body"], resource.type)) {
|
||||
// already did this one
|
||||
return;
|
||||
}
|
||||
|
||||
const generatedFilename =
|
||||
let generatedFilename;
|
||||
|
||||
// Although non-local npm dependencies installed by Npm.depends start
|
||||
// with relative paths like .npm/**/node_modules/*, the files are stored
|
||||
// in the bundle under npm/node_modules, so we need to reroot relative
|
||||
// .npm/ paths against the npm/node_modules path.
|
||||
if (
|
||||
unibuild.pkg.name &&
|
||||
typeof nonLocalNodeModulesBundlePath === "string" &&
|
||||
typeof resource.path === "string" &&
|
||||
resource.path.startsWith(".npm/")
|
||||
) {
|
||||
const parts = resource.path.split("/");
|
||||
const nmi = parts.indexOf("node_modules");
|
||||
if (nmi >= 0) {
|
||||
// Skip builder.writeToGeneratedFilename below since the file already
|
||||
// (should) exist at this new generatedFilename path.
|
||||
generatedFilename = files.pathJoin(
|
||||
nonLocalNodeModulesBundlePath,
|
||||
parts.slice(nmi + 1).join("/"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
generatedFilename = generatedFilename ||
|
||||
builder.writeToGeneratedFilename(
|
||||
files.pathJoin(
|
||||
unibuildDir,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@wry/context": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.0.tgz",
|
||||
"integrity": "sha512-rVjwzFjVYXJ8pWJ8ZRCHv6meOebQvfTlvnUYUNX93Ce0KNeMTqCkf0GiOJc6BNVB96s7qfvwoLN3nUgDnSFOOg=="
|
||||
},
|
||||
"assert": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz",
|
||||
|
||||
@@ -5,6 +5,16 @@ export const ModulesTestPackage = "loaded";
|
||||
import { parse } from "acorn";
|
||||
assert.strictEqual(typeof parse, "function");
|
||||
|
||||
// Test that an npm package with a "module" entry point in its package.json
|
||||
// file can be imported.
|
||||
import { Slot } from "@wry/context";
|
||||
assert.strictEqual(typeof Slot, "function");
|
||||
const idPrefix = "/node_modules/meteor/modules-test-package/node_modules/@wry/context/lib/";
|
||||
assert.strictEqual(
|
||||
require.resolve("@wry/context"),
|
||||
idPrefix + (Meteor.isClient ? "context.esm.js" : "context.js"),
|
||||
);
|
||||
|
||||
export function checkWhere(where) {
|
||||
const { where: serverWhere } = require("./server/where.js");
|
||||
const { where: clientWhere } = require("./client/where.js");
|
||||
|
||||
@@ -6,6 +6,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"@wry/context": "0.4.0",
|
||||
"os-browserify": "0.2.0",
|
||||
"assert": "1.3.0",
|
||||
"cheerio": "0.22.0"
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
"integrity": "sha1-wM5mIMtfLB+xArIPZXQRVcq8REo="
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz",
|
||||
"integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs="
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4="
|
||||
},
|
||||
"babel-types": {
|
||||
"version": "6.25.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz",
|
||||
"integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4="
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
|
||||
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc="
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
|
||||
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4="
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
|
||||
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
@@ -37,19 +37,29 @@
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.10.5",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
|
||||
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
|
||||
},
|
||||
"ts-invariant": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.1.tgz",
|
||||
"integrity": "sha512-fdL8AZinDiVKMsOI0cOWHLprS85LWy2p/eVSctVe6fpZF9BAvO59sQYMEWQ37yybBtlKU2zkmILYmy1jrOf6+g=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ Package.registerBuildPlugin({
|
||||
npmDependencies: {
|
||||
// TODO Figure out what to do about the duplication between this list
|
||||
// and the Npm.depends list below.
|
||||
"ts-invariant": "0.4.1",
|
||||
"babel-plugin-transform-class-properties": "6.9.0",
|
||||
"babel-plugin-transform-strict-mode": "6.8.0"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
import assert from "assert";
|
||||
import { invariant } from "ts-invariant";
|
||||
|
||||
invariant(
|
||||
typeof process.versions.node === "string",
|
||||
"Meteor plugins should only run in Node.js",
|
||||
);
|
||||
|
||||
invariant(
|
||||
require.resolve("ts-invariant"),
|
||||
"/node_modules/meteor/meteor-test-plugin/node_modules/ts-invariant/lib/invariant.js",
|
||||
);
|
||||
|
||||
// This verifies that babel-plugin-transform-strict-mode is enabled.
|
||||
let expected;
|
||||
@@ -7,8 +17,8 @@ try {
|
||||
} catch (e) {
|
||||
expected = e;
|
||||
}
|
||||
assert.ok(expected instanceof TypeError);
|
||||
assert.ok(/callee/.test(expected.message));
|
||||
invariant(expected instanceof TypeError);
|
||||
invariant(/callee/.test(expected.message), expected.message);
|
||||
|
||||
Plugin.registerCompiler({
|
||||
extensions: ["arson"]
|
||||
@@ -20,8 +30,8 @@ class ArsonCompiler {
|
||||
expectedName = "compile-arson";
|
||||
|
||||
processFilesForTarget(inputFiles) {
|
||||
assert.strictEqual(this.expectedName, "compile-arson");
|
||||
assert.ok(inputFiles.length > 0);
|
||||
invariant(this.expectedName === "compile-arson", this.expectedName);
|
||||
invariant(inputFiles.length > 0);
|
||||
|
||||
let vueCheckCount = 0;
|
||||
|
||||
@@ -47,14 +57,12 @@ class ArsonCompiler {
|
||||
const vueCompilerId = file.resolve("vue-template-compiler");
|
||||
// Make sure resolution does not use the "browser" field of
|
||||
// vue-template-compiler/package.json.
|
||||
assert.strictEqual(
|
||||
vueCompilerId.split("/").pop(),
|
||||
"index.js"
|
||||
);
|
||||
const base = vueCompilerId.split("/").pop();
|
||||
invariant(base === "index.js", base);
|
||||
++vueCheckCount;
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(vueCheckCount > 0);
|
||||
invariant(vueCheckCount > 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user