mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Include dynamic stubs in linked meteorInstall bundles.
This commit is contained in:
@@ -162,13 +162,15 @@ _.extend(Module.prototype, {
|
||||
servePath: self.combinedServePath,
|
||||
};
|
||||
|
||||
const results = [result];
|
||||
|
||||
// An array of strings and SourceNode objects.
|
||||
let chunks = [];
|
||||
let fileCount = 0;
|
||||
|
||||
// Emit each file
|
||||
if (self.meteorInstallOptions) {
|
||||
const tree = self._buildModuleTree();
|
||||
const tree = self._buildModuleTree(results, sourceWidth);
|
||||
fileCount = self._chunkifyModuleTree(tree, chunks, sourceWidth);
|
||||
result.exportsName =
|
||||
self._chunkifyEagerRequires(chunks, fileCount, sourceWidth);
|
||||
@@ -216,19 +218,20 @@ _.extend(Module.prototype, {
|
||||
}
|
||||
);
|
||||
|
||||
return [result];
|
||||
return results;
|
||||
}),
|
||||
|
||||
// Builds a tree of nested objects where the properties are names of
|
||||
// files or directories, and the values are either nested objects
|
||||
// (representing directories) or File objects (representing modules).
|
||||
// Bare files and lazy files that are never imported are ignored.
|
||||
_buildModuleTree() {
|
||||
_buildModuleTree(results, sourceWidth) {
|
||||
assert.ok(this.meteorInstallOptions);
|
||||
|
||||
// Tree of File objects for all non-dynamic modules.
|
||||
const tree = {};
|
||||
|
||||
_.each(this.files, function (file) {
|
||||
_.each(this.files, file => {
|
||||
if (file.bare) {
|
||||
// Bare files will be added in between the synchronous require
|
||||
// calls in _chunkifyEagerRequires.
|
||||
@@ -242,22 +245,71 @@ _.extend(Module.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = file.installPath.split("/");
|
||||
let t = tree;
|
||||
_.each(parts, function (part, i) {
|
||||
const isLastPart = i === parts.length - 1;
|
||||
t = _.has(t, part)
|
||||
? t[part]
|
||||
: t[part] = isLastPart ? file : {};
|
||||
});
|
||||
const dynamic = file.lazy && file.imported === "dynamic";
|
||||
|
||||
if (dynamic) {
|
||||
const servePath = "dynamic/" + file.installPath;
|
||||
const { code: source, map } =
|
||||
file.getPrelinkedOutput({
|
||||
sourceWidth: sourceWidth,
|
||||
noLineNumbers: this.noLineNumbers
|
||||
}).toStringWithSourceMap({
|
||||
file: servePath,
|
||||
});
|
||||
|
||||
results.push({
|
||||
source,
|
||||
servePath,
|
||||
sourceMap: map && map.toJSON(),
|
||||
dynamic: true,
|
||||
});
|
||||
|
||||
const entry = {
|
||||
version: file.sourceHash,
|
||||
};
|
||||
|
||||
if (! _.isEmpty(file.deps)) {
|
||||
entry.deps = file.deps;
|
||||
}
|
||||
|
||||
if (file.installPath.endsWith("/package.json") &&
|
||||
file.jsonData) {
|
||||
const main = file.jsonData.main;
|
||||
if (_.isString(main)) {
|
||||
entry.main = main;
|
||||
}
|
||||
|
||||
const browser = file.jsonData.browser;
|
||||
if (_.isString(browser)) {
|
||||
entry.browser = browser;
|
||||
}
|
||||
}
|
||||
|
||||
this._addToTree([entry], file.installPath, tree);
|
||||
|
||||
} else {
|
||||
// If the file is not dynamic, then it should be included in the
|
||||
// initial bundle, so we add it to the static tree.
|
||||
this._addToTree(file, file.installPath, tree);
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
},
|
||||
|
||||
// Takes the tree generated by _buildModuleTree and populates the chunks
|
||||
_addToTree(obj, path, tree) {
|
||||
const parts = path.split("/");
|
||||
const lastIndex = parts.length - 1;
|
||||
parts.forEach((part, i) => {
|
||||
tree = _.has(tree, part)
|
||||
? tree[part]
|
||||
: tree[part] = i < lastIndex ? {} : obj;
|
||||
});
|
||||
},
|
||||
|
||||
// Take the tree generated in getPrelinkedFiles and populate the chunks
|
||||
// array with strings and SourceNode objects that can be combined into a
|
||||
// single SourceNode object. Returns the count of modules in the tree.
|
||||
// single SourceNode object. Return the count of modules in the tree.
|
||||
_chunkifyModuleTree(tree, chunks, sourceWidth) {
|
||||
const self = this;
|
||||
|
||||
@@ -268,12 +320,18 @@ _.extend(Module.prototype, {
|
||||
let moduleCount = 0;
|
||||
|
||||
function walk(t) {
|
||||
if (t instanceof File) {
|
||||
if (Array.isArray(t)) {
|
||||
++moduleCount;
|
||||
chunks.push(JSON.stringify(t, null, 2));
|
||||
|
||||
} else if (t instanceof File) {
|
||||
++moduleCount;
|
||||
|
||||
chunks.push(t.getPrelinkedOutput({
|
||||
sourceWidth,
|
||||
noLineNumbers: self.noLineNumbers
|
||||
}));
|
||||
|
||||
} else if (_.isObject(t)) {
|
||||
chunks.push("{");
|
||||
const keys = _.keys(t);
|
||||
@@ -424,20 +482,16 @@ var File = function (inputFile, module) {
|
||||
self.servePath = inputFile.servePath;
|
||||
|
||||
// Module identifiers imported or required by this module, if any.
|
||||
if (Array.isArray(inputFile.deps)) {
|
||||
self.deps = inputFile.deps;
|
||||
} else if (inputFile.deps && typeof inputFile.deps === "object") {
|
||||
self.deps = Object.keys(inputFile.deps);
|
||||
} else {
|
||||
self.deps = [];
|
||||
}
|
||||
// Excludes dynamically imported dependencies, and may exclude
|
||||
// dependencies already included in the non-dynamic initial bundle.
|
||||
self.deps = getNonDynamicDeps(inputFile.deps);
|
||||
|
||||
// True if the input file should not be evaluated eagerly.
|
||||
self.lazy = inputFile.lazy; // could be `true`, `false` or `undefined` <sigh>
|
||||
|
||||
// True if the file is an eagerly evaluated entry point, or if some
|
||||
// other file imports or requires it.
|
||||
self.imported = !!inputFile.imported;
|
||||
// True if the file is eagerly imported, "dynamic" if the file is
|
||||
// dynamically imported.
|
||||
self.imported = inputFile.imported;
|
||||
|
||||
// Boolean indicating whether this file is the main entry point module
|
||||
// for its package.
|
||||
@@ -450,10 +504,28 @@ var File = function (inputFile, module) {
|
||||
// Is an Object, not a string.
|
||||
self.sourceMap = inputFile.sourceMap;
|
||||
|
||||
// If inputFile is a JSON file, its parsed data will be exposed via the
|
||||
// .jsonData property.
|
||||
self.jsonData = inputFile.jsonData || null;
|
||||
|
||||
// The Module containing this file.
|
||||
self.module = module;
|
||||
};
|
||||
|
||||
function getNonDynamicDeps(inputFileDeps) {
|
||||
const nonDynamicDeps = Object.create(null);
|
||||
|
||||
if (! _.isEmpty(inputFileDeps)) {
|
||||
_.each(inputFileDeps, (info, id) => {
|
||||
if (! info.dynamic) {
|
||||
nonDynamicDeps[id] = info;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Object.keys(nonDynamicDeps);
|
||||
}
|
||||
|
||||
_.extend(File.prototype, {
|
||||
// Return the globals in this file as an array of symbol names. For
|
||||
// example: if the code references 'Foo.bar.baz' and 'Quux', and
|
||||
@@ -513,19 +585,12 @@ _.extend(File.prototype, {
|
||||
|
||||
_getClosureHeader() {
|
||||
if (this._useMeteorInstall()) {
|
||||
var header = "";
|
||||
|
||||
if (this.deps.length > 0) {
|
||||
header += "[";
|
||||
_.each(this.deps, dep => {
|
||||
header += JSON.stringify(dep) + ",";
|
||||
});
|
||||
}
|
||||
|
||||
const headerParts = [
|
||||
header,
|
||||
"function("
|
||||
];
|
||||
// The wrapper function is named "module" so that the UglifyJS
|
||||
// minifier will parse it as a function declaration, because
|
||||
// UglifyJS has trouble parsing single function expressions. If the
|
||||
// module refers to `module`, however, it will be referring to the
|
||||
// parameter of that name, rather than the function name.
|
||||
const headerParts = ["function module("];
|
||||
|
||||
if (this.source.match(/\b__dirname\b/)) {
|
||||
headerParts.push("require,exports,module,__filename,__dirname");
|
||||
@@ -548,14 +613,9 @@ _.extend(File.prototype, {
|
||||
},
|
||||
|
||||
_getClosureFooter() {
|
||||
if (this._useMeteorInstall()) {
|
||||
var footer = "}";
|
||||
if (this.deps.length > 0) {
|
||||
footer += "]";
|
||||
}
|
||||
return footer;
|
||||
}
|
||||
return "}).call(this);\n";
|
||||
return this._useMeteorInstall()
|
||||
? "}"
|
||||
: "}).call(this);\n";
|
||||
},
|
||||
|
||||
// Options:
|
||||
@@ -1057,6 +1117,10 @@ export var fullLink = Profile("linker.fullLink", function (inputFiles, {
|
||||
var headerContent = (new Array(headerLines + 1).join(';'));
|
||||
|
||||
return _.map(prelinkedFiles, function (file) {
|
||||
if (file.dynamic) {
|
||||
return file;
|
||||
}
|
||||
|
||||
if (file.sourceMap) {
|
||||
var sourceMap = file.sourceMap;
|
||||
sourceMap.mappings = headerContent + sourceMap.mappings;
|
||||
|
||||
Reference in New Issue
Block a user