Server-render es5-shim <script> tags like sockjs-shim.

Just as we were able to remove the SockJS polyfill library entirely from
the client JS bundle for modern browsers (#9353), we can do the same with
the `es5-shim` package.

The removes 28KB from the size of the minified JS bundle (before gzip).

It is no longer necessary for other packages to register weak dependencies
on `es5-shim`, because `es5-shim` will be reliably loaded in the `<head>`
if installed, which guarantees it will be evaluated before any bundled JS
in packages or the application.

In addition to loading `es5-shim` and `es5-sham` using `<script>` tags on
the client, we no longer evaluate either script on the server, since Node
8 has solid support for everything that previously needed shimming.
This commit is contained in:
Ben Newman
2017-11-13 16:54:38 -05:00
parent 879a8410ea
commit f33457a0ad
12 changed files with 68 additions and 63 deletions

View File

@@ -10,10 +10,6 @@ Npm.depends({
});
Package.onUse(function (api) {
// If the es5-shim package is installed, make sure it loads before
// babel-runtime, since babel-runtime uses some ES5 APIs like
// Object.defineProperties that are buggy in older browsers.
api.use("es5-shim", { weak: true });
api.use("modules");
api.use("promise"); // Needed by Regenerator.
api.mainModule("babel-runtime.js");

View File

@@ -7,10 +7,6 @@ Package.describe({
});
Package.onUse(function(api) {
// If the es5-shim package is installed, make sure it loads before
// ecmascript-runtime-server, since the runtime uses some ES5 APIs like
// Object.defineProperties that are buggy in older browsers.
api.use("es5-shim", { weak: true });
api.use("modules", "client");
api.use("promise", "client");
api.mainModule("runtime.js", "client");

View File

@@ -1,5 +0,0 @@
require("./import_globals.js");
require("es5-shim/es5-shim.js");
require("es5-shim/es5-sham.js");
require("./console.js");
require("./export_globals.js");

View File

@@ -0,0 +1 @@
.npm/package/node_modules/es5-shim/es5-sham.js

1
packages/es5-shim/es5-sham.min.js vendored Symbolic link
View File

@@ -0,0 +1 @@
.npm/package/node_modules/es5-shim/es5-sham.min.js

View File

@@ -0,0 +1 @@
.npm/package/node_modules/es5-shim/es5-shim.js

1
packages/es5-shim/es5-shim.min.js vendored Symbolic link
View File

@@ -0,0 +1 @@
.npm/package/node_modules/es5-shim/es5-shim.min.js

View File

@@ -1,18 +0,0 @@
if (global.Date !== Date) {
global.Date = Date;
}
if (global.parseInt !== parseInt) {
global.parseInt = parseInt;
}
if (global.parseFloat !== parseFloat) {
global.parseFloat = parseFloat;
}
var Sp = String.prototype;
if (Sp.replace !== originalStringReplace) {
// Restore the original value of String#replace, because the es5-shim
// reimplementation is buggy. See also import_globals.js.
Sp.replace = originalStringReplace;
}

View File

@@ -1,14 +0,0 @@
// Because the es5-{shim,sham}.js code assigns to Date and parseInt,
// Meteor treats them as package variables, and so declares them as
// variables in package scope, which causes some references to Date and
// parseInt in the shim/sham code to refer to those undefined package
// variables. The simplest solution seems to be to initialize the package
// variables to their appropriate global values.
Date = global.Date;
parseInt = global.parseInt;
parseFloat = global.parseFloat;
// Save the original String#replace method, because es5-shim's
// reimplementation of it causes problems in markdown/showdown.js.
// This original method will be restored in export_globals.js.
originalStringReplace = String.prototype.replace;

View File

@@ -11,6 +11,13 @@ Npm.depends({
Package.onUse(function(api) {
api.use("modules");
api.mainModule("client.js", "client");
api.use("server-render");
api.mainModule("console.js", "client");
api.mainModule("server.js", "server");
api.addAssets([
"es5-shim.js",
"es5-shim.min.js",
"es5-sham.js",
"es5-sham.min.js",
], "client");
});

View File

@@ -1,3 +1,39 @@
require("./import_globals.js");
require("es5-shim/es5-shim.js");
require("./export_globals.js");
const { onPageLoad } = require("meteor/server-render");
const hasOwn = Object.prototype.hasOwnProperty;
const minimumMajorVersions = {
chrome: 23,
firefox: 21,
ie: 10,
safari: 6,
phantomjs: 2,
};
onPageLoad(sink => {
if (doNotNeedShim(sink.request)) {
return;
}
sink.appendToHead(makeScript("shim"));
sink.appendToHead(makeScript("sham"));
});
function doNotNeedShim(request) {
const { browser, url } = request;
const query = url && url.query;
const forceEs5Shim = query && query.force_es5_shim;
if (! forceEs5Shim &&
browser &&
hasOwn.call(minimumMajorVersions, browser.name) &&
browser.major >= minimumMajorVersions[browser.name]) {
return true;
}
return false;
}
function makeScript(kind) {
return '\n<script src="/packages/es5-shim/es5-' +
kind + (
Meteor.isProduction ? ".min.js" : ".js"
) + '"></script>';
}

View File

@@ -1,11 +1,6 @@
import { onPageLoad } from "meteor/server-render";
const sockjsVersion = "0.3.4";
const scriptPath =
"/packages/sockjs-shim/sockjs-" +
sockjsVersion +
(Meteor.isProduction ? ".min.js" : ".js");
const hasOwn = Object.prototype.hasOwnProperty;
const minimumMajorVersions = {
chrome: 16,
@@ -16,21 +11,29 @@ const minimumMajorVersions = {
};
onPageLoad(sink => {
const {
browser,
url,
} = sink.request;
if (doNotNeedShim(sink.request)) {
return;
}
sink.appendToHead(makeScript(sockjsVersion));
});
function doNotNeedShim(request) {
const { browser, url } = request;
const query = url && url.query;
const forceSockJs = query && query.force_sockjs;
if (! forceSockJs &&
browser &&
hasOwn.call(minimumMajorVersions, browser.name) &&
browser.major >= minimumMajorVersions[browser.name]) {
return;
return true;
}
return false;
}
sink.appendToHead(
'<script src="' + scriptPath + '"></script>'
);
});
function makeScript(version) {
return '\n<script src="/packages/sockjs-shim/sockjs-' +
version + (
Meteor.isProduction ? ".min.js" : ".js"
) + '"></script>';
}