Drop encoding library
Commit f4a43cca440535a63592877c9bdbbe28636d803c attempted to fix a IE
bug in the SOL library. Unfortunately, it did it by pulling in the
entire NPM encoding library, which is insanely large (190kb after
minification and compression). This is almost equivalent to the rest of
our javascript put together! That's nuts, and I don't think anyone
would argue that's a binary hit worth taking for IE9 support.
This commit removes it, and swaps in an inline polyfill from the mozilla
recommendations, that compresses much....much smaller.
Before this patchset build prints:
app.bundle.js.gz 522 KiB [emitted] [big]
After this patchset:
app.bundle.js.gz 332 KiB [emitted] [big]
If you don't want to break out a calculator, that's 190KB savings in the
root filesystem, and should cut the initial page load time (on slow
connections) by nearly 30 percent.
Note: text-encodings was never pinned in the package-lock.json, hence
why you don't see a diff removing it from package lock. This was a miss
on the original commiters part, although it doesn't really matter, as
it's now removed.
PS: A reviewer may note, I could've moved the polyfill into its own
file. Considering the serial console is the only page that uses that,
and it's not that big I elected not to, to make removing it analagous
with removing xterm/the serial console.
Bonus content!
Added a (commented out) webpack config that allows you to generate the
webui as individual gzipped fragments, instead of one bundle. This
allows you to see file sizes on a package by package basis, and was how
I found this commit in question.
Testing:
This is where this patchset gets hairy. I dont' have an IE9 instance to
test on. Given it's low usage, and the fact that it's a relatively
straightforward change we can probably just wait for someone to tell us
it's broken again.
Enjoy the sweet sweet savings.
Signed-off-by: Ed Tanous <ed@tanous.net>
Change-Id: I2820ff1c4b33d725ebc63490793a72fe600b8ed3
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/app/common/directives/serial-console.js b/app/common/directives/serial-console.js
index 6e0137a..59ffe78 100644
--- a/app/common/directives/serial-console.js
+++ b/app/common/directives/serial-console.js
@@ -35,14 +35,89 @@
return rect;
}
-/*
-TextEncoder/TextDecoder does not support IE.
-Use text-encoding instead in IE
-More detail at https://caniuse.com/#feat=textencoder
-*/
-import {TextDecoder} from 'text-encoding';
-if (!window['TextDecoder']) {
- window['TextDecoder'] = TextDecoder;
+// Add a TextEncoder polyfill to handle ie9 properly. (does anyone still use
+// that anymore? Grabbed from
+// https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder#Polyfill
+if (typeof TextEncoder === 'undefined') {
+ TextEncoder = function TextEncoder() {};
+ TextEncoder.prototype.encode = function encode(str) {
+ 'use strict';
+ var Len = str.length, resPos = -1;
+ // The Uint8Array's length must be at least 3x the length of the string
+ // because an invalid UTF-16
+ // takes up the equivelent space of 3 UTF-8 characters to encode it
+ // properly. However, Array's have an auto expanding length and 1.5x should
+ // be just the right balance for most uses.
+ var resArr = typeof Uint8Array === 'undefined' ? new Array(Len * 1.5) :
+ new Uint8Array(Len * 3);
+ for (var point = 0, nextcode = 0, i = 0; i !== Len;) {
+ point = str.charCodeAt(i), i += 1;
+ if (point >= 0xD800 && point <= 0xDBFF) {
+ if (i === Len) {
+ resArr[resPos += 1] = 0xef /*0b11101111*/;
+ resArr[resPos += 1] = 0xbf /*0b10111111*/;
+ resArr[resPos += 1] = 0xbd /*0b10111101*/;
+ break;
+ }
+ // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+ nextcode = str.charCodeAt(i);
+ if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
+ point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
+ i += 1;
+ if (point > 0xffff) {
+ resArr[resPos += 1] = (0x1e /*0b11110*/ << 3) | (point >>> 18);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | ((point >>> 12) & 0x3f /*0b00111111*/);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | ((point >>> 6) & 0x3f /*0b00111111*/);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
+ continue;
+ }
+ } else {
+ resArr[resPos += 1] = 0xef /*0b11101111*/;
+ resArr[resPos += 1] = 0xbf /*0b10111111*/;
+ resArr[resPos += 1] = 0xbd /*0b10111101*/;
+ continue;
+ }
+ }
+ if (point <= 0x007f) {
+ resArr[resPos += 1] = (0x0 /*0b0*/ << 7) | point;
+ } else if (point <= 0x07ff) {
+ resArr[resPos += 1] = (0x6 /*0b110*/ << 5) | (point >>> 6);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
+ } else {
+ resArr[resPos += 1] = (0xe /*0b1110*/ << 4) | (point >>> 12);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | ((point >>> 6) & 0x3f /*0b00111111*/);
+ resArr[resPos += 1] =
+ (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
+ }
+ }
+ if (typeof Uint8Array !== 'undefined')
+ return resArr.subarray(0, resPos + 1);
+ // else // IE 6-9
+ resArr.length = resPos + 1; // trim off extra weight
+ return resArr;
+ };
+ TextEncoder.prototype.toString = function() {
+ return '[object TextEncoder]'
+ };
+ try { // Object.defineProperty only works on DOM prototypes in IE8
+ Object.defineProperty(TextEncoder.prototype, 'encoding', {
+ get: function() {
+ if (TextEncoder.prototype.isPrototypeOf(this))
+ return 'utf-8';
+ else
+ throw TypeError('Illegal invocation');
+ }
+ });
+ } catch (e) { /*IE6-8 fallback*/
+ TextEncoder.prototype.encoding = 'utf-8';
+ }
+ if (typeof Symbol !== 'undefined')
+ TextEncoder.prototype[Symbol.toStringTag] = 'TextEncoder';
}
window.angular && (function(angular) {
diff --git a/package-lock.json b/package-lock.json
index 47b22a2..5608491 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9825,11 +9825,6 @@
}
}
},
- "text-encoding": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz",
- "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA=="
- },
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
diff --git a/package.json b/package.json
index 7e808df..fd51898 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,6 @@
"ng-toast": "2.0.0",
"pkg-dir": "4.2.0",
"regenerator-runtime": "0.13.5",
- "text-encoding": "0.7.0",
"xterm": "3.14.5"
},
"peerDependencies": {},
@@ -77,8 +76,8 @@
"html-webpack-plugin": "4.2.0",
"ignore-assets-webpack-plugin": "2.0.1",
"mini-css-extract-plugin": "0.9.0",
- "node-sass": "4.13.1",
"node-gyp": "6.1.0",
+ "node-sass": "4.13.1",
"null-loader": "4.0.0",
"raw-loader": "4.0.1",
"rimraf": "3.0.2",
diff --git a/webpack.config.js b/webpack.config.js
index 7630954..58bf47d 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -142,6 +142,33 @@
})
];
+ // Comment in to see per-module js sizes. This is useful in debugging "why is
+ // my binary so big"
+ /*
+ config.optimization = {
+ runtimeChunk: 'single',
+ splitChunks: {
+ chunks: 'all',
+ maxInitialRequests: Infinity,
+ minSize: 0,
+ cacheGroups: {
+ vendor: {
+ test: /[\\/]node_modules[\\/]/,
+ name(module) {
+ // get the name. E.g. node_modules/packageName/not/this/part.js
+ // or node_modules/packageName
+ const packageName =
+ module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
+
+ // npm package names are URL-safe, but some servers don't like @
+ symbols return `${packageName.replace('@', '')}`;
+ },
+ },
+ },
+ },
+ };
+ */
+
// Add build specific plugins
if (isProd) {
config.plugins.push(new CompressionPlugin({deleteOriginalAssets: true}));