zero-query 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -123
- package/cli.js +186 -114
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +2605 -0
- package/dist/zquery.min.js +17 -0
- package/index.js +1 -0
- package/package.json +5 -3
- package/src/router.js +24 -1
package/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* zQuery CLI
|
|
@@ -8,21 +8,22 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
* zquery build Build the zQuery library (dist/)
|
|
11
|
-
* zquery build --watch Build & watch for library changes
|
|
12
11
|
*
|
|
13
12
|
* zquery bundle [entry] Bundle an app's ES modules into one file
|
|
14
13
|
* zquery bundle scripts/app.js Specify entry explicitly
|
|
15
|
-
* zquery bundle -o
|
|
16
|
-
* zquery bundle --
|
|
14
|
+
* zquery bundle -o build/ Custom output directory
|
|
15
|
+
* zquery bundle --html other.html Use a specific HTML file instead of auto-detected
|
|
17
16
|
* zquery bundle --watch Watch & rebuild on changes
|
|
18
|
-
* zquery bundle --html index.html Rewrite <script type="module"> to use bundle
|
|
19
17
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Smart defaults (no flags needed for typical projects):
|
|
19
|
+
* - Entry is auto-detected from index.html's <script type="module" src="...">
|
|
20
|
+
* - zquery.min.js is always embedded (auto-built if not found)
|
|
21
|
+
* - index.html is always rewritten and assets are copied
|
|
22
|
+
* - Output goes to dist/ next to the detected index.html
|
|
22
23
|
*
|
|
23
24
|
* Examples:
|
|
24
|
-
* cd my-
|
|
25
|
-
* npx zero-query bundle scripts/app.js
|
|
25
|
+
* cd my-app && npx zero-query bundle # just works!
|
|
26
|
+
* npx zero-query bundle path/to/scripts/app.js # works from anywhere
|
|
26
27
|
*/
|
|
27
28
|
|
|
28
29
|
const fs = require('fs');
|
|
@@ -410,38 +411,70 @@ function bundleApp() {
|
|
|
410
411
|
process.exit(1);
|
|
411
412
|
}
|
|
412
413
|
|
|
413
|
-
const includeLib = flag('include-lib', 'L');
|
|
414
414
|
const outPath = option('out', 'o', null);
|
|
415
|
-
const htmlFile = option('html', null, null);
|
|
416
415
|
const watchMode = flag('watch', 'w');
|
|
417
416
|
|
|
418
|
-
//
|
|
417
|
+
// Auto-detect index.html by walking up from the entry file, then check cwd
|
|
418
|
+
let htmlFile = option('html', null, null);
|
|
419
|
+
let htmlAbs = htmlFile ? path.resolve(projectRoot, htmlFile) : null;
|
|
420
|
+
if (!htmlFile) {
|
|
421
|
+
const htmlCandidates = [];
|
|
422
|
+
// Walk up from the entry file's directory to cwd looking for index.html
|
|
423
|
+
let entryDir = path.dirname(entry);
|
|
424
|
+
while (entryDir.length >= projectRoot.length) {
|
|
425
|
+
htmlCandidates.push(path.join(entryDir, 'index.html'));
|
|
426
|
+
const parent = path.dirname(entryDir);
|
|
427
|
+
if (parent === entryDir) break;
|
|
428
|
+
entryDir = parent;
|
|
429
|
+
}
|
|
430
|
+
// Also check cwd and public/
|
|
431
|
+
htmlCandidates.push(path.join(projectRoot, 'index.html'));
|
|
432
|
+
htmlCandidates.push(path.join(projectRoot, 'public/index.html'));
|
|
433
|
+
for (const candidate of htmlCandidates) {
|
|
434
|
+
if (fs.existsSync(candidate)) {
|
|
435
|
+
htmlAbs = candidate;
|
|
436
|
+
htmlFile = path.relative(projectRoot, candidate);
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Derive output directory:
|
|
443
|
+
// -o flag → use that path
|
|
444
|
+
// else → dist/ next to the detected HTML file (or cwd/dist/ as fallback)
|
|
419
445
|
const entryRel = path.relative(projectRoot, entry);
|
|
420
446
|
const entryName = path.basename(entry, '.js');
|
|
421
|
-
let
|
|
447
|
+
let baseDistDir;
|
|
422
448
|
if (outPath) {
|
|
423
449
|
const resolved = path.resolve(projectRoot, outPath);
|
|
424
|
-
// -o accepts a directory path or a file path (directory is extracted)
|
|
425
450
|
if (outPath.endsWith('/') || outPath.endsWith('\\') || !path.extname(outPath) ||
|
|
426
451
|
(fs.existsSync(resolved) && fs.statSync(resolved).isDirectory())) {
|
|
427
|
-
|
|
452
|
+
baseDistDir = resolved;
|
|
428
453
|
} else {
|
|
429
|
-
|
|
454
|
+
baseDistDir = path.dirname(resolved);
|
|
430
455
|
}
|
|
456
|
+
} else if (htmlAbs) {
|
|
457
|
+
baseDistDir = path.join(path.dirname(htmlAbs), 'dist');
|
|
431
458
|
} else {
|
|
432
|
-
|
|
459
|
+
baseDistDir = path.join(projectRoot, 'dist');
|
|
433
460
|
}
|
|
434
461
|
|
|
462
|
+
// Two output sub-directories: server/ (with <base href="/">) and local/ (relative paths)
|
|
463
|
+
const serverDir = path.join(baseDistDir, 'server');
|
|
464
|
+
const localDir = path.join(baseDistDir, 'local');
|
|
465
|
+
|
|
435
466
|
console.log(`\n zQuery App Bundler`);
|
|
436
467
|
console.log(` Entry: ${entryRel}`);
|
|
437
|
-
console.log(` Output: ${path.relative(projectRoot,
|
|
438
|
-
|
|
468
|
+
console.log(` Output: ${path.relative(projectRoot, baseDistDir)}/server/ & local/`);
|
|
469
|
+
console.log(` Library: embedded`);
|
|
470
|
+
console.log(` HTML: ${htmlFile || 'not found (no index.html detected)'}`);
|
|
439
471
|
console.log('');
|
|
440
472
|
|
|
441
473
|
function doBuild() {
|
|
442
474
|
const start = Date.now();
|
|
443
475
|
|
|
444
|
-
if (!fs.existsSync(
|
|
476
|
+
if (!fs.existsSync(serverDir)) fs.mkdirSync(serverDir, { recursive: true });
|
|
477
|
+
if (!fs.existsSync(localDir)) fs.mkdirSync(localDir, { recursive: true });
|
|
445
478
|
|
|
446
479
|
// Walk the import graph
|
|
447
480
|
const files = walkImportGraph(entry);
|
|
@@ -457,26 +490,49 @@ function bundleApp() {
|
|
|
457
490
|
return `// --- ${rel} ${'—'.repeat(Math.max(1, 60 - rel.length))}\n${code.trim()}`;
|
|
458
491
|
});
|
|
459
492
|
|
|
460
|
-
//
|
|
493
|
+
// Embed zquery.min.js — always included
|
|
461
494
|
let libSection = '';
|
|
462
|
-
|
|
463
|
-
|
|
495
|
+
{
|
|
496
|
+
const pkgSrcDir = path.join(__dirname, 'src');
|
|
497
|
+
const pkgMinFile = path.join(__dirname, 'dist', 'zquery.min.js');
|
|
498
|
+
|
|
499
|
+
// Always rebuild the library from source when running from the repo/package
|
|
500
|
+
// so that dist/ stays current with the latest source changes.
|
|
501
|
+
if (fs.existsSync(pkgSrcDir) && fs.existsSync(path.join(__dirname, 'index.js'))) {
|
|
502
|
+
console.log(`\n Building library from source...`);
|
|
503
|
+
const prevCwd = process.cwd();
|
|
504
|
+
try {
|
|
505
|
+
process.chdir(__dirname);
|
|
506
|
+
buildLibrary();
|
|
507
|
+
} finally {
|
|
508
|
+
process.chdir(prevCwd);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Now look for the library in common locations
|
|
513
|
+
const htmlDir = htmlAbs ? path.dirname(htmlAbs) : null;
|
|
464
514
|
const libCandidates = [
|
|
515
|
+
// Prefer the freshly-built package dist
|
|
516
|
+
path.join(__dirname, 'dist/zquery.min.js'),
|
|
517
|
+
// Then check project-local locations
|
|
518
|
+
htmlDir && path.join(htmlDir, 'scripts/vendor/zquery.min.js'),
|
|
519
|
+
htmlDir && path.join(htmlDir, 'vendor/zquery.min.js'),
|
|
465
520
|
path.join(projectRoot, 'scripts/vendor/zquery.min.js'),
|
|
466
521
|
path.join(projectRoot, 'vendor/zquery.min.js'),
|
|
467
522
|
path.join(projectRoot, 'lib/zquery.min.js'),
|
|
468
523
|
path.join(projectRoot, 'dist/zquery.min.js'),
|
|
469
524
|
path.join(projectRoot, 'zquery.min.js'),
|
|
470
|
-
|
|
471
|
-
path.join(__dirname, 'dist/zquery.min.js'),
|
|
472
|
-
];
|
|
525
|
+
].filter(Boolean);
|
|
473
526
|
const libPath = libCandidates.find(p => fs.existsSync(p));
|
|
527
|
+
|
|
474
528
|
if (libPath) {
|
|
475
|
-
|
|
476
|
-
|
|
529
|
+
const libBytes = fs.statSync(libPath).size;
|
|
530
|
+
libSection = `// --- zquery.min.js (library) ${'—'.repeat(34)}\n${fs.readFileSync(libPath, 'utf-8').trim()}\n\n`
|
|
531
|
+
+ `// --- Build-time metadata ————————————————————————————\nif(typeof $!=="undefined"){$.meta=Object.assign($.meta||{},{libSize:${libBytes}});}\n\n`;
|
|
532
|
+
console.log(` Embedded library from ${path.relative(projectRoot, libPath)} (${(libBytes / 1024).toFixed(1)} KB)`);
|
|
477
533
|
} else {
|
|
478
|
-
console.warn(`\n ⚠ Could not find zquery.min.js
|
|
479
|
-
console.warn(`
|
|
534
|
+
console.warn(`\n ⚠ Could not find zquery.min.js anywhere`);
|
|
535
|
+
console.warn(` Place zquery.min.js in scripts/vendor/, vendor/, lib/, or dist/`);
|
|
480
536
|
}
|
|
481
537
|
}
|
|
482
538
|
|
|
@@ -503,28 +559,35 @@ function bundleApp() {
|
|
|
503
559
|
|
|
504
560
|
// Content-hashed output filenames (z-<name>.<hash>.js)
|
|
505
561
|
const contentHash = crypto.createHash('sha256').update(bundle).digest('hex').slice(0, 8);
|
|
506
|
-
const
|
|
507
|
-
const
|
|
562
|
+
const bundleBase = `z-${entryName}.${contentHash}.js`;
|
|
563
|
+
const minBase = `z-${entryName}.${contentHash}.min.js`;
|
|
508
564
|
|
|
509
|
-
// Remove previous hashed builds
|
|
565
|
+
// Remove previous hashed builds from both output directories
|
|
510
566
|
const escName = entryName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
511
567
|
const cleanRe = new RegExp(`^z-${escName}\\.[a-f0-9]{8}\\.(?:min\\.)?js$`);
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
568
|
+
for (const dir of [serverDir, localDir]) {
|
|
569
|
+
if (fs.existsSync(dir)) {
|
|
570
|
+
for (const f of fs.readdirSync(dir)) {
|
|
571
|
+
if (cleanRe.test(f)) fs.unlinkSync(path.join(dir, f));
|
|
572
|
+
}
|
|
515
573
|
}
|
|
516
574
|
}
|
|
517
575
|
|
|
576
|
+
// Write bundle into server/ (canonical), then copy to local/
|
|
577
|
+
const bundleFile = path.join(serverDir, bundleBase);
|
|
578
|
+
const minFile = path.join(serverDir, minBase);
|
|
518
579
|
fs.writeFileSync(bundleFile, bundle, 'utf-8');
|
|
519
580
|
fs.writeFileSync(minFile, minify(bundle, banner), 'utf-8');
|
|
581
|
+
fs.copyFileSync(bundleFile, path.join(localDir, bundleBase));
|
|
582
|
+
fs.copyFileSync(minFile, path.join(localDir, minBase));
|
|
520
583
|
|
|
521
|
-
console.log(`\n ✓ ${
|
|
522
|
-
console.log(` ✓ ${
|
|
584
|
+
console.log(`\n ✓ ${bundleBase} (${sizeKB(fs.readFileSync(bundleFile))} KB)`);
|
|
585
|
+
console.log(` ✓ ${minBase} (${sizeKB(fs.readFileSync(minFile))} KB)`);
|
|
523
586
|
|
|
524
|
-
//
|
|
587
|
+
// Rewrite index.html → two variants (server/ and local/)
|
|
525
588
|
if (htmlFile) {
|
|
526
589
|
const bundledFileSet = new Set(files);
|
|
527
|
-
rewriteHtml(projectRoot, htmlFile, bundleFile,
|
|
590
|
+
rewriteHtml(projectRoot, htmlFile, bundleFile, true, bundledFileSet, serverDir, localDir);
|
|
528
591
|
}
|
|
529
592
|
|
|
530
593
|
const elapsed = Date.now() - start;
|
|
@@ -572,18 +635,21 @@ function copyDirSync(src, dest) {
|
|
|
572
635
|
|
|
573
636
|
/**
|
|
574
637
|
* Rewrite an HTML file to replace the module <script> with the bundle.
|
|
575
|
-
* Copies all referenced assets
|
|
576
|
-
*
|
|
638
|
+
* Copies all referenced assets into both server/ and local/ dist dirs,
|
|
639
|
+
* then writes two index.html variants:
|
|
640
|
+
* server/index.html — has <base href="/"> for SPA deep-route support
|
|
641
|
+
* local/index.html — no <base>, relative paths for file:// access
|
|
642
|
+
*
|
|
643
|
+
* Both are fully static HTML with no dynamic loading.
|
|
577
644
|
*/
|
|
578
|
-
function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFiles) {
|
|
645
|
+
function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFiles, serverDir, localDir) {
|
|
579
646
|
const htmlPath = path.resolve(projectRoot, htmlRelPath);
|
|
580
647
|
if (!fs.existsSync(htmlPath)) {
|
|
581
648
|
console.warn(` ⚠ HTML file not found: ${htmlRelPath}`);
|
|
582
649
|
return;
|
|
583
650
|
}
|
|
584
651
|
|
|
585
|
-
const htmlDir
|
|
586
|
-
const distDir = path.dirname(bundleFile);
|
|
652
|
+
const htmlDir = path.dirname(htmlPath);
|
|
587
653
|
let html = fs.readFileSync(htmlPath, 'utf-8');
|
|
588
654
|
|
|
589
655
|
// Collect all asset references from the HTML (src=, href= on link/script/img)
|
|
@@ -592,37 +658,29 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
|
|
|
592
658
|
let m;
|
|
593
659
|
while ((m = assetRe.exec(html)) !== null) {
|
|
594
660
|
const ref = m[1];
|
|
595
|
-
// Skip absolute URLs, data URIs, protocol-relative, and anchors
|
|
596
661
|
if (ref.startsWith('http') || ref.startsWith('//') || ref.startsWith('data:') || ref.startsWith('#')) continue;
|
|
597
|
-
// Skip the module entry (already bundled)
|
|
598
662
|
const refAbs = path.resolve(htmlDir, ref);
|
|
599
663
|
if (bundledFiles && bundledFiles.has(refAbs)) continue;
|
|
600
|
-
// Skip zquery lib if we're embedding it
|
|
601
664
|
if (includeLib && /zquery(?:\.min)?\.js$/i.test(ref)) continue;
|
|
602
665
|
assets.add(ref);
|
|
603
666
|
}
|
|
604
667
|
|
|
605
|
-
// Copy each referenced asset into dist
|
|
668
|
+
// Copy each referenced asset into BOTH dist dirs, preserving directory structure
|
|
606
669
|
let copiedCount = 0;
|
|
607
|
-
const copiedDirs = new Set();
|
|
608
670
|
for (const asset of assets) {
|
|
609
671
|
const srcFile = path.resolve(htmlDir, asset);
|
|
610
672
|
if (!fs.existsSync(srcFile)) continue;
|
|
611
673
|
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
674
|
+
for (const distDir of [serverDir, localDir]) {
|
|
675
|
+
const destFile = path.join(distDir, asset);
|
|
676
|
+
const destDir = path.dirname(destFile);
|
|
677
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
678
|
+
fs.copyFileSync(srcFile, destFile);
|
|
679
|
+
}
|
|
617
680
|
copiedCount++;
|
|
618
|
-
|
|
619
|
-
// If this is inside a directory that may contain sibling assets
|
|
620
|
-
// (fonts referenced by CSS, etc.), track it
|
|
621
|
-
copiedDirs.add(path.dirname(srcFile));
|
|
622
681
|
}
|
|
623
682
|
|
|
624
|
-
// Also copy any CSS-referenced assets
|
|
625
|
-
// references and copy those too
|
|
683
|
+
// Also copy any CSS-referenced assets (fonts, images in url() etc.)
|
|
626
684
|
for (const asset of assets) {
|
|
627
685
|
const srcFile = path.resolve(htmlDir, asset);
|
|
628
686
|
if (!fs.existsSync(srcFile) || !asset.endsWith('.css')) continue;
|
|
@@ -633,25 +691,27 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
|
|
|
633
691
|
while ((cm = urlRe.exec(cssContent)) !== null) {
|
|
634
692
|
const ref = cm[1];
|
|
635
693
|
if (ref.startsWith('data:') || ref.startsWith('http') || ref.startsWith('//')) continue;
|
|
636
|
-
const cssSrcDir
|
|
637
|
-
const assetSrc
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
fs.
|
|
644
|
-
|
|
694
|
+
const cssSrcDir = path.dirname(srcFile);
|
|
695
|
+
const assetSrc = path.resolve(cssSrcDir, ref);
|
|
696
|
+
if (!fs.existsSync(assetSrc)) continue;
|
|
697
|
+
|
|
698
|
+
for (const distDir of [serverDir, localDir]) {
|
|
699
|
+
const cssDestDir = path.dirname(path.join(distDir, asset));
|
|
700
|
+
const assetDest = path.resolve(cssDestDir, ref);
|
|
701
|
+
if (!fs.existsSync(assetDest)) {
|
|
702
|
+
const dir = path.dirname(assetDest);
|
|
703
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
704
|
+
fs.copyFileSync(assetSrc, assetDest);
|
|
705
|
+
}
|
|
645
706
|
}
|
|
707
|
+
copiedCount++;
|
|
646
708
|
}
|
|
647
709
|
}
|
|
648
710
|
|
|
649
|
-
// Make the bundle
|
|
650
|
-
const bundleRel = path.relative(
|
|
711
|
+
// Make the bundle filename relative (same name in both dirs)
|
|
712
|
+
const bundleRel = path.relative(serverDir, bundleFile).replace(/\\/g, '/');
|
|
651
713
|
|
|
652
|
-
// Replace <script type="module" src="..."> with the bundle (
|
|
653
|
-
// Use "defer" so the script runs after DOM is parsed — module scripts are
|
|
654
|
-
// deferred by default, but regular scripts in <head> are not.
|
|
714
|
+
// Replace <script type="module" src="..."> with the bundle (defer)
|
|
655
715
|
html = html.replace(
|
|
656
716
|
/<script\s+type\s*=\s*["']module["']\s+src\s*=\s*["'][^"']+["']\s*>\s*<\/script>/gi,
|
|
657
717
|
`<script defer src="${bundleRel}"></script>`
|
|
@@ -665,20 +725,23 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
|
|
|
665
725
|
);
|
|
666
726
|
}
|
|
667
727
|
|
|
668
|
-
//
|
|
669
|
-
// /
|
|
670
|
-
//
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
728
|
+
// ── server/index.html ──
|
|
729
|
+
// Keep <base href="/"> as-is — the preload scanner sees it, all resources
|
|
730
|
+
// resolve from root, deep-route refreshes work perfectly.
|
|
731
|
+
const serverHtml = html;
|
|
732
|
+
|
|
733
|
+
// ── local/index.html ──
|
|
734
|
+
// Remove <base href="/"> so relative paths resolve from the HTML file's
|
|
735
|
+
// directory — correct for file:// with zero console errors.
|
|
736
|
+
const localHtml = html.replace(/<base\s+href\s*=\s*["']\/["'][^>]*>\s*\n?\s*/i, '');
|
|
737
|
+
|
|
738
|
+
// Write both
|
|
739
|
+
const htmlName = path.basename(htmlRelPath);
|
|
740
|
+
fs.writeFileSync(path.join(serverDir, htmlName), serverHtml, 'utf-8');
|
|
741
|
+
fs.writeFileSync(path.join(localDir, htmlName), localHtml, 'utf-8');
|
|
742
|
+
console.log(` ✓ server/${htmlName} (with <base href="/">)`);
|
|
743
|
+
console.log(` ✓ local/${htmlName} (relative paths, file:// ready)`);
|
|
744
|
+
console.log(` ✓ Copied ${copiedCount} asset(s) into both dist dirs`);
|
|
682
745
|
}
|
|
683
746
|
|
|
684
747
|
|
|
@@ -693,31 +756,54 @@ function showHelp() {
|
|
|
693
756
|
COMMANDS
|
|
694
757
|
|
|
695
758
|
build Build the zQuery library → dist/
|
|
696
|
-
|
|
759
|
+
(must be run from the project root where src/ lives)
|
|
697
760
|
|
|
698
761
|
bundle [entry] Bundle app ES modules into a single file
|
|
699
|
-
--out, -o <path> Output directory (default: dist/)
|
|
700
|
-
--
|
|
701
|
-
--html <file> Rewrite HTML file to reference the bundle
|
|
762
|
+
--out, -o <path> Output directory (default: dist/ next to index.html)
|
|
763
|
+
--html <file> Use a specific HTML file (default: auto-detected)
|
|
702
764
|
--watch, -w Watch source files and rebuild on changes
|
|
703
765
|
|
|
766
|
+
SMART DEFAULTS
|
|
767
|
+
|
|
768
|
+
The bundler works with zero flags for typical projects:
|
|
769
|
+
• Entry is auto-detected from index.html <script type="module" src="...">
|
|
770
|
+
• zquery.min.js is always embedded (auto-built from source if not found)
|
|
771
|
+
• index.html is rewritten for both server and local (file://) use
|
|
772
|
+
• Output goes to dist/server/ and dist/local/ next to the detected index.html
|
|
773
|
+
|
|
704
774
|
OUTPUT
|
|
705
775
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
776
|
+
The bundler produces two self-contained sub-directories:
|
|
777
|
+
|
|
778
|
+
dist/server/ deploy to your web server
|
|
779
|
+
index.html has <base href="/"> for SPA deep routes
|
|
780
|
+
z-<entry>.<hash>.js readable bundle
|
|
781
|
+
z-<entry>.<hash>.min.js minified bundle
|
|
782
|
+
|
|
783
|
+
dist/local/ open from disk (file://)
|
|
784
|
+
index.html relative paths, no <base> tag
|
|
785
|
+
z-<entry>.<hash>.js same bundle
|
|
786
|
+
|
|
709
787
|
Previous hashed builds are automatically cleaned on each rebuild.
|
|
710
788
|
|
|
789
|
+
DEVELOPMENT
|
|
790
|
+
|
|
791
|
+
npm run serve start a local dev server (zero-http, SPA routing)
|
|
792
|
+
npm run dev watch mode — auto-rebuild bundle on source changes
|
|
793
|
+
|
|
711
794
|
EXAMPLES
|
|
712
795
|
|
|
713
|
-
# Build the library
|
|
796
|
+
# Build the library only
|
|
714
797
|
zquery build
|
|
715
798
|
|
|
716
|
-
# Bundle an app
|
|
799
|
+
# Bundle an app — auto-detects everything
|
|
717
800
|
cd my-app && zquery bundle
|
|
718
801
|
|
|
719
|
-
#
|
|
720
|
-
zquery bundle scripts/app.js
|
|
802
|
+
# Point to an entry from a parent directory
|
|
803
|
+
zquery bundle path/to/scripts/app.js
|
|
804
|
+
|
|
805
|
+
# Custom output directory
|
|
806
|
+
zquery bundle -o build/
|
|
721
807
|
|
|
722
808
|
# Watch mode
|
|
723
809
|
zquery bundle --watch
|
|
@@ -739,20 +825,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
739
825
|
} else if (command === 'build') {
|
|
740
826
|
console.log('\n zQuery Library Build\n');
|
|
741
827
|
buildLibrary();
|
|
742
|
-
if (flag('watch', 'w')) {
|
|
743
|
-
console.log(' Watching src/ for changes...\n');
|
|
744
|
-
const srcDir = path.join(process.cwd(), 'src');
|
|
745
|
-
let debounceTimer;
|
|
746
|
-
const rebuild = () => {
|
|
747
|
-
clearTimeout(debounceTimer);
|
|
748
|
-
debounceTimer = setTimeout(() => {
|
|
749
|
-
console.log(' Rebuilding...');
|
|
750
|
-
try { buildLibrary(); } catch (e) { console.error(` ✗ ${e.message}`); }
|
|
751
|
-
}, 200);
|
|
752
|
-
};
|
|
753
|
-
fs.watch(srcDir, { recursive: true }, rebuild);
|
|
754
|
-
fs.watch(path.join(process.cwd(), 'index.js'), rebuild);
|
|
755
|
-
}
|
|
756
828
|
} else if (command === 'bundle') {
|
|
757
829
|
bundleApp();
|
|
758
830
|
} else {
|
|
Binary file
|