create-spark-html-app 0.3.2 → 0.3.4
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/bin/index.js +31 -1
- package/package.json +1 -1
- package/template/README.md +17 -2
- package/template/package.json +2 -1
- package/template/vite.config.js +10 -1
package/bin/index.js
CHANGED
|
@@ -63,6 +63,29 @@ function isEmptyDir(dir) {
|
|
|
63
63
|
return entries.length === 0;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// Resolve the newest published version of a package from the npm registry,
|
|
67
|
+
// so a freshly scaffolded app always starts on the latest spark-html.
|
|
68
|
+
// Returns a caret range (e.g. "^0.13.2"), or null if the lookup fails
|
|
69
|
+
// (offline, registry down) — callers fall back to the template default.
|
|
70
|
+
async function latestRange(pkgName) {
|
|
71
|
+
try {
|
|
72
|
+
const ctrl = new AbortController();
|
|
73
|
+
const timer = setTimeout(() => ctrl.abort(), 4000);
|
|
74
|
+
const registry = (process.env.npm_config_registry || 'https://registry.npmjs.org')
|
|
75
|
+
.replace(/\/+$/, '');
|
|
76
|
+
const res = await fetch(`${registry}/${pkgName}/latest`, {
|
|
77
|
+
signal: ctrl.signal,
|
|
78
|
+
headers: { accept: 'application/json' },
|
|
79
|
+
});
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
if (!res.ok) return null;
|
|
82
|
+
const { version } = await res.json();
|
|
83
|
+
return version ? `^${version}` : null;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
66
89
|
async function prompt(question, fallback) {
|
|
67
90
|
const rl = createInterface({ input: stdin, output: stdout });
|
|
68
91
|
try {
|
|
@@ -115,10 +138,17 @@ async function main() {
|
|
|
115
138
|
if (existsSync(src)) renameSync(src, join(targetDir, to));
|
|
116
139
|
}
|
|
117
140
|
|
|
118
|
-
// 4 ─ stamp the project name
|
|
141
|
+
// 4 ─ stamp the project name + pin the latest spark-html ─────────────
|
|
119
142
|
const pkgPath = join(targetDir, 'package.json');
|
|
120
143
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
121
144
|
pkg.name = projectName;
|
|
145
|
+
// Always start on the newest published spark-html. If the registry can't
|
|
146
|
+
// be reached, the template's "latest" default still resolves on install.
|
|
147
|
+
const range = await latestRange('spark-html');
|
|
148
|
+
if (range && pkg.dependencies && pkg.dependencies['spark-html']) {
|
|
149
|
+
pkg.dependencies['spark-html'] = range;
|
|
150
|
+
stdout.write(`${c.dim(` using spark-html ${range}`)}\n`);
|
|
151
|
+
}
|
|
122
152
|
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
123
153
|
|
|
124
154
|
// 5 ─ celebrate + print next steps ───────────────────────────────────
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -13,13 +13,28 @@ npm run dev
|
|
|
13
13
|
Open the dev server and edit `public/components/welcome.html`. Save, and the
|
|
14
14
|
page reloads instantly.
|
|
15
15
|
|
|
16
|
-
## Build
|
|
16
|
+
## Build (SEO-ready)
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
npm run build # static output → dist/, serve anywhere
|
|
20
20
|
npm run preview # preview the production build locally
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
`npm run build` is **SEO-friendly out of the box**: the `spark-prerender`
|
|
24
|
+
Vite plugin runs your app at build time and writes fully-rendered HTML into
|
|
25
|
+
`dist/` — so crawlers and AI tools read real content (headings, text, links),
|
|
26
|
+
not empty placeholders. The browser still hydrates over it for full
|
|
27
|
+
interactivity. Set page metadata as plain component state:
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script>
|
|
31
|
+
let pageTitle = 'My App — does a thing';
|
|
32
|
+
let pageDescription = 'A short, crawlable description of the page.';
|
|
33
|
+
</script>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Don't need SEO? Remove the `prerender(...)` plugin from `vite.config.js`.
|
|
37
|
+
|
|
23
38
|
## How it's wired
|
|
24
39
|
|
|
25
40
|
```
|
|
@@ -29,7 +44,7 @@ npm run preview # preview the production build locally
|
|
|
29
44
|
├── public/components/ ← your components (plain .html files)
|
|
30
45
|
│ ├── app.html ← theme + shell
|
|
31
46
|
│ └── welcome.html ← the live reactive welcome screen
|
|
32
|
-
└── vite.config.js ← spark-html/vite
|
|
47
|
+
└── vite.config.js ← spark-html/vite + spark-prerender/vite (SEO)
|
|
33
48
|
```
|
|
34
49
|
|
|
35
50
|
A component is a `.html` file with optional `<script>` and `<style>`. Top-level
|
package/template/package.json
CHANGED
package/template/vite.config.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import spark from 'spark-html/vite';
|
|
3
|
+
import prerender from 'spark-prerender/vite';
|
|
3
4
|
|
|
4
5
|
// Spark needs no build step — Vite is just a convenient dev server and
|
|
5
6
|
// bundler. The plugin serves component fragments raw and full-reloads
|
|
6
7
|
// when one changes. Components live in public/ so they ship verbatim to
|
|
7
8
|
// the production build too.
|
|
9
|
+
//
|
|
10
|
+
// `prerender()` makes `npm run build` SEO-friendly: it runs your app at
|
|
11
|
+
// build time and writes fully-rendered HTML into dist/ (crawlers and AI
|
|
12
|
+
// tools read real content; the browser still hydrates over it). Remove it
|
|
13
|
+
// if you don't need SEO. List every page you ship in `pages`.
|
|
8
14
|
export default defineConfig({
|
|
9
|
-
plugins: [
|
|
15
|
+
plugins: [
|
|
16
|
+
spark(),
|
|
17
|
+
prerender({ pages: ['index.html'] }),
|
|
18
|
+
],
|
|
10
19
|
});
|