perf(tools): vendor jszip + docx-preview for archive/transmittal/classifier
Same pattern as the browse fix. archive, transmittal, classifier previously CDN-loaded jszip + docx-preview on first preview of a .zip / .docx file via shared/preview-lib.js's loadLibrary helper. That meant each first-preview blocked on a CDN round-trip + parse, and broke entirely under restrictive networks or CSPs. Vendor both libs under shared/vendor/ and concat them at the top of each tool's build, ahead of init.js. window.JSZip + window.docx are now defined immediately on page load. Drop the redundant loadLibrary calls (and classifier's stray <script src="cdn..."> tag in the template, plus archive's bespoke loadJSZip helper in export.js). xlsx (SheetJS) intentionally stays CDN-loaded — at ~900 KB it's too large to inline, and only fires on .xlsx preview which is a rarer path. Bundle size impact (uncompressed): archive: 304 KB → 476 KB (+172 KB) transmittal: 449 KB → 621 KB (+172 KB) classifier: 252 KB → 424 KB (+172 KB) With the gzip middleware (~75% reduction on HTML) and ETag-cached revalidation now in place, the wire-size delta is ~40 KB per tool on the first load and 0 on every subsequent load until redeploy.
This commit is contained in:
parent
c22bb19dab
commit
eaecaaee29
9 changed files with 42 additions and 31 deletions
|
|
@ -27,8 +27,14 @@ concat_files \
|
||||||
"css/print.css" \
|
"css/print.css" \
|
||||||
> "$css_temp"
|
> "$css_temp"
|
||||||
|
|
||||||
# JavaScript files to concatenate in order
|
# JavaScript files to concatenate in order. Vendored libraries first
|
||||||
|
# (jszip, docx-preview) so window.JSZip + window.docx are defined before
|
||||||
|
# any tool code runs — replaces the previous CDN loadLibrary() calls in
|
||||||
|
# table.js + export.js. xlsx is intentionally still CDN-loaded on demand
|
||||||
|
# (~900 KB; too large to inline).
|
||||||
concat_files \
|
concat_files \
|
||||||
|
"../shared/vendor/jszip.min.js" \
|
||||||
|
"../shared/vendor/docx-preview.min.js" \
|
||||||
"../shared/zddc.js" \
|
"../shared/zddc.js" \
|
||||||
"../shared/hash.js" \
|
"../shared/hash.js" \
|
||||||
"../shared/theme.js" \
|
"../shared/theme.js" \
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,12 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if JSZip is loaded
|
// JSZip is vendored (concat'd by build.sh), so window.JSZip is
|
||||||
|
// already defined. Defensive check in case a future refactor
|
||||||
|
// reorders things.
|
||||||
if (typeof JSZip === 'undefined') {
|
if (typeof JSZip === 'undefined') {
|
||||||
// Dynamically load JSZip
|
alert('JSZip library not bundled — rebuild archive with shared/vendor/jszip.min.js');
|
||||||
await loadJSZip();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const zip = new JSZip();
|
const zip = new JSZip();
|
||||||
|
|
@ -123,17 +125,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load JSZip library dynamically
|
|
||||||
function loadJSZip() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js';
|
|
||||||
script.onload = resolve;
|
|
||||||
script.onerror = reject;
|
|
||||||
document.head.appendChild(script);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show progress indicator
|
// Show progress indicator
|
||||||
function showProgress(message, current, total) {
|
function showProgress(message, current, total) {
|
||||||
let progressDiv = document.getElementById('progressIndicator');
|
let progressDiv = document.getElementById('progressIndicator');
|
||||||
|
|
@ -260,7 +251,6 @@
|
||||||
rowsToCSV,
|
rowsToCSV,
|
||||||
exportCSV,
|
exportCSV,
|
||||||
downloadSelected,
|
downloadSelected,
|
||||||
loadJSZip,
|
|
||||||
showProgress,
|
showProgress,
|
||||||
hideProgress,
|
hideProgress,
|
||||||
downloadFile,
|
downloadFile,
|
||||||
|
|
|
||||||
|
|
@ -609,9 +609,9 @@
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await loadLibrary('https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js');
|
// jszip + docx-preview are vendored (concatenated by build.sh
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/docx-preview@latest/dist/docx-preview.min.js');
|
// ahead of every tool module), so window.JSZip and window.docx
|
||||||
|
// are already defined here.
|
||||||
const arrayBuffer = await (file.handle
|
const arrayBuffer = await (file.handle
|
||||||
? file.handle.getFile().then(f => f.arrayBuffer())
|
? file.handle.getFile().then(f => f.arrayBuffer())
|
||||||
: fetch(file.url).then(r => r.arrayBuffer()));
|
: fetch(file.url).then(r => r.arrayBuffer()));
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,14 @@ concat_files \
|
||||||
"css/spreadsheet.css" \
|
"css/spreadsheet.css" \
|
||||||
> "$css_temp"
|
> "$css_temp"
|
||||||
|
|
||||||
# JavaScript files to concatenate in order
|
# JavaScript files to concatenate in order. Vendored libraries first
|
||||||
|
# (jszip, docx-preview) so window.JSZip + window.docx are defined before
|
||||||
|
# any tool code runs. Replaces the previous <script src="cdn..."> tag in
|
||||||
|
# template.html plus the loadLibrary CDN calls in preview.js. xlsx stays
|
||||||
|
# CDN-loaded on demand (~900 KB; too large to inline).
|
||||||
concat_files \
|
concat_files \
|
||||||
|
"../shared/vendor/jszip.min.js" \
|
||||||
|
"../shared/vendor/docx-preview.min.js" \
|
||||||
"../shared/zddc.js" \
|
"../shared/zddc.js" \
|
||||||
"../shared/hash.js" \
|
"../shared/hash.js" \
|
||||||
"../shared/theme.js" \
|
"../shared/theme.js" \
|
||||||
|
|
|
||||||
|
|
@ -383,9 +383,7 @@
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/jszip@3/dist/jszip.min.js');
|
// jszip + docx-preview vendored by build.sh — already in scope.
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/docx-preview@latest/dist/docx-preview.min.js');
|
|
||||||
|
|
||||||
const blob = await getFileBlob(file);
|
const blob = await getFileBlob(file);
|
||||||
const arrayBuffer = await blob.arrayBuffer();
|
const arrayBuffer = await blob.arrayBuffer();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>ZDDC Classifier</title>
|
<title>ZDDC Classifier</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="{{FAVICON}}">
|
<link rel="icon" type="image/svg+xml" href="{{FAVICON}}">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
|
||||||
<style>
|
<style>
|
||||||
{{CSS_PLACEHOLDER}}
|
{{CSS_PLACEHOLDER}}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
8
shared/vendor/docx-preview.min.js
vendored
Normal file
8
shared/vendor/docx-preview.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -36,8 +36,13 @@ concat_files \
|
||||||
"css/print.css" \
|
"css/print.css" \
|
||||||
> "$css_temp"
|
> "$css_temp"
|
||||||
|
|
||||||
# JavaScript files to concatenate in order
|
# JavaScript files to concatenate in order. Vendored libraries first
|
||||||
|
# (jszip, docx-preview) so window.JSZip + window.docx are defined before
|
||||||
|
# any tool code runs — replaces the previous CDN loadLibrary() calls
|
||||||
|
# scattered through files-preview.js. xlsx stays CDN-loaded on demand.
|
||||||
concat_files \
|
concat_files \
|
||||||
|
"../shared/vendor/jszip.min.js" \
|
||||||
|
"../shared/vendor/docx-preview.min.js" \
|
||||||
"../shared/zddc.js" \
|
"../shared/zddc.js" \
|
||||||
"../shared/hash.js" \
|
"../shared/hash.js" \
|
||||||
"../shared/theme.js" \
|
"../shared/theme.js" \
|
||||||
|
|
|
||||||
|
|
@ -200,8 +200,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/jszip@3/dist/jszip.min.js');
|
// jszip + docx-preview vendored by build.sh — already in scope.
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/docx-preview@latest/dist/docx-preview.min.js');
|
|
||||||
var arrayBuffer = await getFileArrayBuffer(file);
|
var arrayBuffer = await getFileArrayBuffer(file);
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
await window.docx.renderAsync(arrayBuffer, container);
|
await window.docx.renderAsync(arrayBuffer, container);
|
||||||
|
|
@ -474,7 +473,7 @@
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
updatePreviewStatus('Loading ZIP...');
|
updatePreviewStatus('Loading ZIP...');
|
||||||
await loadLibrary('https://cdn.jsdelivr.net/npm/jszip@3/dist/jszip.min.js');
|
// JSZip vendored by build.sh — already in scope.
|
||||||
var arrayBuffer = await zipFile.arrayBuffer();
|
var arrayBuffer = await zipFile.arrayBuffer();
|
||||||
var zip = await JSZip.loadAsync(arrayBuffer);
|
var zip = await JSZip.loadAsync(arrayBuffer);
|
||||||
var sourceEntries = [];
|
var sourceEntries = [];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue