minista 2.3.0 → 2.4.0

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 CHANGED
@@ -97,6 +97,20 @@ export default defineConfig({
97
97
  bundle: {
98
98
  outName: "bundle", // string
99
99
  },
100
+ partial: {
101
+ usePreact: false, // boolean
102
+ useIntersectionObserver: true, // boolean
103
+ outName: "partial", // string
104
+ rootAttrSuffix: "partial-hydration", // string
105
+ rootValuePrefix: "ph", // string
106
+ rootDOMElement: "div", // "div" | "span"
107
+ rootStyle: { display: "contents" }, // React.CSSProperties
108
+ intersectionObserverOptions: {
109
+ root: null, // Element | null
110
+ rootMargin: "0px", // string
111
+ thresholds: [1], // ReadonlyArray<number>
112
+ },
113
+ },
100
114
  images: {
101
115
  outDir: "assets/images", // string
102
116
  outName: "[name]", // string
package/client.d.ts CHANGED
@@ -16,6 +16,13 @@ declare module "*.svg" {
16
16
  export default ReactComponent
17
17
  }
18
18
 
19
+ declare module "*?ph" {
20
+ import * as React from "react"
21
+
22
+ const ReactComponent: React.FunctionComponent<React.PropsWithChildren>
23
+ export default ReactComponent
24
+ }
25
+
19
26
  declare module "*?raw" {
20
27
  const src: string
21
28
  export default src
package/dist/build.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Options as MdxOptions } from "@mdx-js/esbuild";
2
2
  import type { Config as SvgrOptions } from "@svgr/core";
3
3
  import type { InlineConfig } from "vite";
4
- import type { MinistaResolveConfig, RootStaticContent, RootJsxContent, GlobalStaticData, GetGlobalStaticData, PageJsxContent, StaticData, StaticDataItem, GetStaticData } from "./types.js";
4
+ import type { MinistaResolveConfig, RootStaticContent, RootJsxContent, GlobalStaticData, GetGlobalStaticData, PageJsxContent, StaticData, StaticDataItem, GetStaticData, PartialModules } from "./types.js";
5
5
  export declare function buildTempPages(entryPoints: string[], buildOptions: {
6
6
  outBase: string;
7
7
  outDir: string;
@@ -21,9 +21,11 @@ export declare function buildStaticPage(entryPoint: string, outFile: string, roo
21
21
  export declare function buildStaticData(getStaticData: GetStaticData): Promise<StaticData>;
22
22
  export declare function buildHtmlPage(pageJsxContent: PageJsxContent, staticDataItem: StaticDataItem, routePath: string, rootStaticContent: RootStaticContent, assetsTagStr: string, frontmatter: any, outDir: string): Promise<void>;
23
23
  export declare function buildTempAssets(viteConfig: InlineConfig, buildOptions: {
24
+ input: string;
24
25
  bundleOutName: string;
25
26
  outDir: string;
26
27
  assetDir: string;
28
+ generateJs: boolean;
27
29
  }): Promise<void>;
28
30
  export declare function buildAssetsTagStr(entryPoints: string[], buildOptions: {
29
31
  outBase: string;
@@ -35,4 +37,27 @@ export declare function buildViteImporterAssets(entry: {
35
37
  [key: string]: string;
36
38
  }): Promise<void>;
37
39
  export declare function buildViteImporterBlankAssets(): Promise<void>;
40
+ export declare function buildPartialModules(moduleFilePaths: string[], config: MinistaResolveConfig): Promise<PartialModules>;
41
+ export declare function buildPartialStringIndex(partialModules: PartialModules, buildOptions: {
42
+ outFile: string;
43
+ }): Promise<void>;
44
+ export declare function buildPartialStringBundle(entryPoint: string, buildOptions: {
45
+ outFile: string;
46
+ mdxConfig: MdxOptions;
47
+ svgrOptions: SvgrOptions;
48
+ }): Promise<void>;
49
+ export declare function buildPartialStringInitial(entryPoint: string, partialModules: PartialModules, buildOptions: {
50
+ outFile: string;
51
+ }): Promise<void>;
52
+ export declare function buildPartialHydrateIndex(partialModules: PartialModules, config: MinistaResolveConfig, buildOptions: {
53
+ outFile: string;
54
+ }): Promise<void>;
55
+ export declare function buildPartialHydrateAssets(viteConfig: InlineConfig, buildOptions: {
56
+ input: string;
57
+ bundleOutName: string;
58
+ outDir: string;
59
+ assetDir: string;
60
+ generateJs: boolean;
61
+ usePreact: boolean;
62
+ }): Promise<void>;
38
63
  export declare function buildCopyDir(targetDir: string, outDir: string, log?: "public" | "assets"): Promise<void>;
package/dist/build.js CHANGED
@@ -25,29 +25,56 @@ import pc from "picocolors";
25
25
  import { Fragment } from "react";
26
26
  import { build as esBuild } from "esbuild";
27
27
  import mdx from "@mdx-js/esbuild";
28
- import { build as viteBuild, mergeConfig as mergeViteConfig } from "vite";
28
+ import {
29
+ build as viteBuild,
30
+ defineConfig as defineViteConfig,
31
+ mergeConfig as mergeViteConfig
32
+ } from "vite";
29
33
  import { systemConfig } from "./system.js";
30
- import { resolvePlugin, svgrPlugin, rawPlugin } from "./esbuild.js";
34
+ import { getFilePath } from "./path.js";
35
+ import {
36
+ resolvePlugin,
37
+ svgrPlugin,
38
+ rawPlugin,
39
+ partialHydrationPlugin
40
+ } from "./esbuild.js";
31
41
  import { renderHtml } from "./render.js";
32
- import { slashEnd } from "./utils.js";
42
+ import { slashEnd, reactStylesToString } from "./utils.js";
33
43
  const __filename = url.fileURLToPath(import.meta.url);
34
44
  const __dirname = path.dirname(__filename);
45
+ const ministaPkgUrl = path.resolve(__dirname + "/../package.json");
46
+ const ministaPkgUrlRelative = path.relative(".", ministaPkgUrl);
47
+ const ministaPkg = JSON.parse(fs.readFileSync(ministaPkgUrlRelative, "utf8"));
48
+ const userPkgPath = path.resolve("package.json");
49
+ const userPkgFilePath = path.relative(process.cwd(), userPkgPath);
50
+ const userPkg = JSON.parse(fs.readFileSync(userPkgFilePath, "utf8"));
51
+ const esbuildExternals = [
52
+ ...Object.keys(ministaPkg.dependencies || {}),
53
+ ...Object.keys(ministaPkg.devDependencies || {}),
54
+ ...Object.keys(ministaPkg.peerDependencies || {}),
55
+ ...Object.keys(userPkg.dependencies || {}),
56
+ ...Object.keys(userPkg.devDependencies || {}),
57
+ ...Object.keys(userPkg.peerDependencies || {}),
58
+ "*.css",
59
+ "*.scss",
60
+ "*.sass"
61
+ ];
62
+ const esbuildLoaders = {
63
+ ".jpg": "file",
64
+ ".jpeg": "file",
65
+ ".png": "file",
66
+ ".gif": "file",
67
+ ".webp": "file",
68
+ ".avif": "file",
69
+ ".eot": "file",
70
+ ".woff": "file",
71
+ ".woff2": "file"
72
+ };
73
+ const userPkgHasPreact = [
74
+ ...Object.keys(userPkg.dependencies || {}),
75
+ ...Object.keys(userPkg.devDependencies || {})
76
+ ].includes("preact");
35
77
  async function buildTempPages(entryPoints, buildOptions) {
36
- const ministaPkgURL = new URL(path.resolve(__dirname + "/../package.json"), import.meta.url);
37
- const ministaPkg = JSON.parse(fs.readFileSync(ministaPkgURL, "utf8"));
38
- const userPkgURL = new URL(path.resolve("package.json"), import.meta.url);
39
- const userPkg = JSON.parse(fs.readFileSync(userPkgURL, "utf8"));
40
- const esbuildExternal = [
41
- ...Object.keys(ministaPkg.dependencies || {}),
42
- ...Object.keys(ministaPkg.devDependencies || {}),
43
- ...Object.keys(ministaPkg.peerDependencies || {}),
44
- ...Object.keys(userPkg.dependencies || {}),
45
- ...Object.keys(userPkg.devDependencies || {}),
46
- ...Object.keys(userPkg.peerDependencies || {}),
47
- "*.css",
48
- "*.scss",
49
- "*.sass"
50
- ];
51
78
  await esBuild({
52
79
  entryPoints,
53
80
  outbase: buildOptions.outBase,
@@ -60,23 +87,26 @@ async function buildTempPages(entryPoints, buildOptions) {
60
87
  path.resolve(__dirname + "/../lib/shim-react.js"),
61
88
  path.resolve(__dirname + "/../lib/shim-fetch.js")
62
89
  ],
63
- external: esbuildExternal,
90
+ external: esbuildExternals,
91
+ loader: esbuildLoaders,
64
92
  plugins: [
65
93
  mdx(buildOptions.mdxConfig),
66
94
  resolvePlugin({
67
95
  "react/jsx-runtime": "react/jsx-runtime.js"
68
96
  }),
69
97
  svgrPlugin(buildOptions.svgrOptions),
70
- rawPlugin()
98
+ rawPlugin(),
99
+ partialHydrationPlugin()
71
100
  ]
72
101
  }).catch(() => process.exit(1));
73
102
  }
74
103
  async function buildStaticPages(entryPoints, tempRootFilePath, buildOptions, assetsTagStr) {
75
104
  const rootStaticContent = await buildRootEsmContent(tempRootFilePath);
105
+ const winOutBase = buildOptions.outBase.replaceAll("/", "\\");
76
106
  await Promise.all(entryPoints.map(async (entryPoint) => {
77
107
  const extname = path.extname(entryPoint);
78
108
  const basename = path.basename(entryPoint, extname);
79
- const dirname = path.dirname(entryPoint).replace(buildOptions.outBase, buildOptions.outDir);
109
+ const dirname = path.dirname(entryPoint).replace(buildOptions.outBase, buildOptions.outDir).replace(winOutBase, buildOptions.outDir);
80
110
  const filename = path.join(dirname, basename + ".html");
81
111
  await buildStaticPage(entryPoint, filename, rootStaticContent, assetsTagStr, buildOptions.outDir);
82
112
  }));
@@ -89,7 +119,8 @@ async function buildRootEsmContent(tempRootFilePath) {
89
119
  if (!tempRootFilePath) {
90
120
  return defaultRootEsmContent;
91
121
  } else {
92
- const rootEsmContent = await import(tempRootFilePath);
122
+ const targetFilePath = url.pathToFileURL(tempRootFilePath).href;
123
+ const rootEsmContent = await import(targetFilePath);
93
124
  const rootJsxContent = rootEsmContent.default ? rootEsmContent.default : Fragment;
94
125
  const staticData = rootEsmContent.getStaticData ? await buildGlobalStaticData(rootEsmContent.getStaticData) : { props: {} };
95
126
  return { component: rootJsxContent, staticData };
@@ -100,7 +131,8 @@ async function buildGlobalStaticData(getGlobalStaticData) {
100
131
  return response;
101
132
  }
102
133
  async function buildStaticPage(entryPoint, outFile, rootStaticContent, assetsTagStr, outDir) {
103
- const pageEsmContent = await import(path.resolve(entryPoint));
134
+ const targetFilePath = url.pathToFileURL(entryPoint).href;
135
+ const pageEsmContent = await import(targetFilePath);
104
136
  const pageJsxContent = pageEsmContent.default;
105
137
  const frontmatter = pageEsmContent.frontmatter ? pageEsmContent.frontmatter : void 0;
106
138
  const defaultStaticDataItem = { props: {}, paths: {} };
@@ -179,8 +211,21 @@ async function buildHtmlPage(pageJsxContent, staticDataItem, routePath, rootStat
179
211
  })());
180
212
  }
181
213
  };
182
- const html = await renderHtml(/* @__PURE__ */ React.createElement(RenderComponent, null), assetsTagStr);
183
- const replacedHtml = html.replace(/<div class="minista-comment" hidden="">(.+?)<\/div>/g, "\n<!-- $1 -->");
214
+ const renderdHtml = await renderHtml(/* @__PURE__ */ React.createElement(RenderComponent, null), assetsTagStr);
215
+ const html = [renderdHtml];
216
+ const stringInitial = getFilePath(systemConfig.temp.partialHydration.outDir, "string-initial", "json");
217
+ if (stringInitial) {
218
+ const targetRelative = path.relative(".", stringInitial);
219
+ const targetJson = JSON.parse(fs.readFileSync(targetRelative, "utf8"));
220
+ const items = targetJson.items;
221
+ items.map((item) => {
222
+ const dummy = `<div data-partial-hydration="${item.id}"></div>`;
223
+ const reg = new RegExp(`${dummy}`, "g");
224
+ html[0] = html[0].replace(reg, item.html);
225
+ return;
226
+ });
227
+ }
228
+ const replacedHtml = html[0].replace(/<div class="minista-comment" hidden="">(.+?)<\/div>/g, "\n<!-- $1 -->");
184
229
  await fs.outputFile(routePath, replacedHtml).then(() => {
185
230
  console.log(`${pc.bold(pc.green("BUILD"))} ${pc.bold(routePath)}`);
186
231
  }).catch((err) => {
@@ -188,16 +233,16 @@ async function buildHtmlPage(pageJsxContent, staticDataItem, routePath, rootStat
188
233
  });
189
234
  }
190
235
  async function buildTempAssets(viteConfig, buildOptions) {
191
- const customConfig = {
236
+ const customConfig = defineViteConfig({
192
237
  build: {
193
238
  write: false,
194
239
  rollupOptions: {
195
240
  input: {
196
- __minista_bundle_assets: path.resolve(__dirname + "/../dist/bundle.js")
241
+ __minista_bundle_assets: buildOptions.input
197
242
  }
198
243
  }
199
244
  }
200
- };
245
+ });
201
246
  const mergedConfig = mergeViteConfig(viteConfig, customConfig);
202
247
  const result = await viteBuild(mergedConfig);
203
248
  const items = result.output;
@@ -207,6 +252,10 @@ async function buildTempAssets(viteConfig, buildOptions) {
207
252
  const customFileName = slashEnd(buildOptions.outDir) + buildOptions.bundleOutName + ".css";
208
253
  return (item == null ? void 0 : item.source) && fs.outputFile(customFileName, item == null ? void 0 : item.source);
209
254
  } else if (item.fileName.match(/__minista_bundle_assets\.js/)) {
255
+ if (buildOptions.generateJs) {
256
+ const customFileName = slashEnd(buildOptions.outDir) + buildOptions.bundleOutName + ".js";
257
+ return (item == null ? void 0 : item.code) && fs.outputFile(customFileName, item == null ? void 0 : item.code);
258
+ }
210
259
  return;
211
260
  } else {
212
261
  const customFileName = buildOptions.outDir + item.fileName.replace(buildOptions.assetDir, "");
@@ -217,8 +266,9 @@ async function buildTempAssets(viteConfig, buildOptions) {
217
266
  }
218
267
  }
219
268
  async function buildAssetsTagStr(entryPoints, buildOptions) {
269
+ const winOutBase = buildOptions.outBase.replaceAll("/", "\\");
220
270
  const assetsTags = entryPoints.map((entryPoint) => {
221
- const assetPath = entryPoint.replace(buildOptions.outBase, buildOptions.outDir);
271
+ const assetPath = entryPoint.replace(buildOptions.outBase, buildOptions.outDir).replace(winOutBase, buildOptions.outDir).replaceAll("\\", "/");
222
272
  if (assetPath.endsWith(".css")) {
223
273
  return `<link rel="stylesheet" href="${assetPath}">`;
224
274
  } else if (assetPath.endsWith(".js")) {
@@ -311,6 +361,199 @@ async function buildViteImporterBlankAssets() {
311
361
  console.error(err);
312
362
  });
313
363
  }
364
+ async function buildPartialModules(moduleFilePaths, config) {
365
+ const moduleData = [];
366
+ await Promise.all(moduleFilePaths.map(async (entryPoint) => {
367
+ const entryPointRelative = path.relative(".", entryPoint);
368
+ const underUniqueId = path.parse(entryPoint).name;
369
+ const importer = await fs.readFile(entryPointRelative, "utf8");
370
+ moduleData.push({ id: underUniqueId, importer });
371
+ return;
372
+ }));
373
+ const sortedModuleData = moduleData.sort((a, b) => {
374
+ const nameA = a.importer.toUpperCase();
375
+ const nameB = b.importer.toUpperCase();
376
+ if (nameA < nameB) {
377
+ return -1;
378
+ }
379
+ if (nameA > nameB) {
380
+ return 1;
381
+ }
382
+ return 0;
383
+ });
384
+ const rootStyle = config.assets.partial.rootStyle;
385
+ const hasRootStyle = Object.entries(rootStyle).length !== 0;
386
+ const partialModules = sortedModuleData.map((item, index) => {
387
+ return {
388
+ id: item.id,
389
+ phId: `PH_${index + 1}`,
390
+ phDomId: `${config.assets.partial.rootValuePrefix}-${index + 1}`,
391
+ htmlId: `html_${index + 1}`,
392
+ targetsId: `targets_${index + 1}`,
393
+ importer: item.importer,
394
+ rootAttr: `data-${config.assets.partial.rootAttrSuffix}`,
395
+ rootDOMElement: config.assets.partial.rootDOMElement,
396
+ rootStyleStr: hasRootStyle ? reactStylesToString(rootStyle) : ""
397
+ };
398
+ });
399
+ return partialModules;
400
+ }
401
+ async function buildPartialStringIndex(partialModules, buildOptions) {
402
+ const tmpImporters = partialModules.map((module) => {
403
+ return `import ${module.phId} from "${module.importer}"`;
404
+ });
405
+ const tmpRenders = partialModules.map((module) => {
406
+ return `// ${module.phId}
407
+ const ${module.htmlId} = renderToString(React.createElement(${module.phId}))`;
408
+ });
409
+ const tmpExports = partialModules.map((module) => module.htmlId);
410
+ const tmpImporterStr = tmpImporters.join("\n");
411
+ const tmpRendersStr = tmpRenders.join("\n");
412
+ const tmpExportsStr = tmpExports.join(", ");
413
+ const outFile = buildOptions.outFile;
414
+ const template = `import { renderToString } from "react-dom/server.js"
415
+ ${tmpImporterStr}
416
+
417
+ ${tmpRendersStr}
418
+
419
+ export { ${tmpExportsStr} }`;
420
+ await fs.outputFile(outFile, template).catch((err) => {
421
+ console.error(err);
422
+ });
423
+ }
424
+ async function buildPartialStringBundle(entryPoint, buildOptions) {
425
+ await esBuild({
426
+ entryPoints: [entryPoint],
427
+ outfile: buildOptions.outFile,
428
+ bundle: true,
429
+ format: "esm",
430
+ platform: "node",
431
+ inject: [
432
+ path.resolve(__dirname + "/../lib/shim-react.js")
433
+ ],
434
+ external: esbuildExternals,
435
+ loader: esbuildLoaders,
436
+ plugins: [
437
+ mdx(buildOptions.mdxConfig),
438
+ resolvePlugin({
439
+ "react/jsx-runtime": "react/jsx-runtime.js"
440
+ }),
441
+ svgrPlugin(buildOptions.svgrOptions),
442
+ rawPlugin()
443
+ ]
444
+ }).catch(() => process.exit(1));
445
+ }
446
+ async function buildPartialStringInitial(entryPoint, partialModules, buildOptions) {
447
+ const outFile = buildOptions.outFile;
448
+ const targetFilePath = url.pathToFileURL(entryPoint).href;
449
+ const partialString = await import(targetFilePath);
450
+ const items = partialModules.map((module) => {
451
+ const html = partialString[module.htmlId];
452
+ const dom = module.rootDOMElement;
453
+ const dataId = `${module.rootAttr}="${module.phDomId}"`;
454
+ const style = module.rootStyleStr ? ` style="${module.rootStyleStr}"` : "";
455
+ const replacedHtml = `<${dom} ${dataId}${style}>${html}</${dom}>`;
456
+ return {
457
+ id: module.id,
458
+ html: replacedHtml
459
+ };
460
+ });
461
+ const template = JSON.stringify({ items });
462
+ await fs.outputFile(outFile, template).catch((err) => {
463
+ console.error(err);
464
+ });
465
+ }
466
+ async function buildPartialHydrateIndex(partialModules, config, buildOptions) {
467
+ const tmpImporters = partialModules.map((module) => {
468
+ return `import ${module.phId} from "${module.importer}"`;
469
+ });
470
+ const tempFunctionIntersectionObserver = `const options = {
471
+ root: ${config.assets.partial.intersectionObserverOptions.root},
472
+ rootMargin: "${config.assets.partial.intersectionObserverOptions.rootMargin}",
473
+ thresholds: ${config.assets.partial.intersectionObserverOptions.thresholds},
474
+ }
475
+ const observer = new IntersectionObserver(hydrate, options)
476
+ observer.observe(target)
477
+
478
+ function hydrate() {
479
+ ReactDOM.hydrate(App, target)
480
+ observer.unobserve(target)
481
+ }`;
482
+ const tempFunctionImmediateExecution = `ReactDOM.hydrate(App, target)`;
483
+ const tempFunction = config.assets.partial.useIntersectionObserver ? tempFunctionIntersectionObserver : tempFunctionImmediateExecution;
484
+ const tmpRenders = partialModules.map((module) => {
485
+ return `
486
+ // ${module.phId}
487
+ const ${module.targetsId} = document.querySelectorAll('[${module.rootAttr}="${module.phDomId}"]')
488
+ if (${module.targetsId}) {
489
+ ${module.targetsId}.forEach(target => {
490
+ const App = React.createElement(${module.phId})
491
+ ${tempFunction}
492
+ })
493
+ }`;
494
+ });
495
+ const tmpImporterStr = tmpImporters.join("\n");
496
+ const tmpRendersStr = tmpRenders.join("\n");
497
+ const outFile = buildOptions.outFile;
498
+ const template = `import React from "react"
499
+ import ReactDOM from "react-dom"
500
+ ${tmpImporterStr}
501
+ ${tmpRendersStr}`;
502
+ await fs.outputFile(outFile, template).catch((err) => {
503
+ console.error(err);
504
+ });
505
+ }
506
+ async function buildPartialHydrateAssets(viteConfig, buildOptions) {
507
+ var _a;
508
+ const activePreact = buildOptions.usePreact && userPkgHasPreact;
509
+ const resolveAliasPreact = {
510
+ react: "preact/compat",
511
+ "react-dom": "preact/compat"
512
+ };
513
+ const customConfig = defineViteConfig({
514
+ base: viteConfig.base,
515
+ build: {
516
+ write: false,
517
+ assetsInlineLimit: 0,
518
+ minify: (_a = viteConfig.build) == null ? void 0 : _a.minify,
519
+ rollupOptions: {
520
+ input: {
521
+ __minista_bundle_assets: buildOptions.input
522
+ },
523
+ output: {
524
+ manualChunks: void 0
525
+ }
526
+ }
527
+ },
528
+ esbuild: viteConfig.esbuild,
529
+ plugins: viteConfig.plugins,
530
+ resolve: {
531
+ alias: activePreact ? resolveAliasPreact : {}
532
+ },
533
+ customLogger: viteConfig.customLogger
534
+ });
535
+ const mergedConfig = mergeViteConfig({}, customConfig);
536
+ const result = await viteBuild(mergedConfig);
537
+ const items = result.output;
538
+ if (Array.isArray(items) && items.length > 0) {
539
+ items.map((item) => {
540
+ if (item.fileName.match(/\.css/)) {
541
+ const customFileName = slashEnd(buildOptions.outDir) + buildOptions.bundleOutName + ".css";
542
+ return (item == null ? void 0 : item.source) && fs.outputFile(customFileName, item == null ? void 0 : item.source);
543
+ } else if (item.fileName.match(/\.js/)) {
544
+ if (buildOptions.generateJs) {
545
+ const customFileName = slashEnd(buildOptions.outDir) + buildOptions.bundleOutName + ".js";
546
+ return (item == null ? void 0 : item.code) && fs.outputFile(customFileName, item == null ? void 0 : item.code);
547
+ }
548
+ return;
549
+ } else {
550
+ const customFileName = buildOptions.outDir + item.fileName.replace(buildOptions.assetDir, "");
551
+ const customCode = (item == null ? void 0 : item.source) ? item == null ? void 0 : item.source : (item == null ? void 0 : item.code) ? item == null ? void 0 : item.code : "";
552
+ return customCode && fs.outputFile(customFileName, customCode);
553
+ }
554
+ });
555
+ }
556
+ }
314
557
  async function buildCopyDir(targetDir, outDir, log) {
315
558
  const checkTargetDir = await fs.pathExists(targetDir);
316
559
  if (checkTargetDir) {
@@ -333,6 +576,12 @@ export {
333
576
  buildCopyDir,
334
577
  buildGlobalStaticData,
335
578
  buildHtmlPage,
579
+ buildPartialHydrateAssets,
580
+ buildPartialHydrateIndex,
581
+ buildPartialModules,
582
+ buildPartialStringBundle,
583
+ buildPartialStringIndex,
584
+ buildPartialStringInitial,
336
585
  buildRootEsmContent,
337
586
  buildStaticData,
338
587
  buildStaticPage,
package/dist/cli.js CHANGED
@@ -29,9 +29,11 @@ import {
29
29
  generateViteImporters,
30
30
  generateTempRoot,
31
31
  generateTempPages,
32
- generateAssets,
32
+ generateTempAssets,
33
+ generatePartialHydration,
33
34
  generateNoStyleTemp,
34
35
  generateHtmlPages,
36
+ generateAssets,
35
37
  generatePublic,
36
38
  generateDownload,
37
39
  generateBeautify
@@ -77,16 +79,25 @@ cli.command("build [root]", "build for production").action(async () => {
77
79
  emptyResolveDir(systemConfig.temp.assets.outDir),
78
80
  emptyResolveDir(systemConfig.temp.pages.outDir),
79
81
  emptyResolveDir(systemConfig.temp.viteImporter.outDir),
82
+ emptyResolveDir(systemConfig.temp.partialHydration.outDir),
80
83
  emptyResolveDir(config.out)
81
84
  ]);
82
85
  await Promise.all([generateViteImporters(config, viteConfig)]);
83
86
  await Promise.all([
84
87
  generateTempRoot(config, mdxConfig),
85
88
  generateTempPages(config, mdxConfig),
86
- generateAssets(config, viteConfig)
89
+ generateTempAssets(config, viteConfig)
90
+ ]);
91
+ await Promise.all([
92
+ generateNoStyleTemp(systemConfig.temp.root.outDir),
93
+ generateNoStyleTemp(systemConfig.temp.pages.outDir),
94
+ generatePartialHydration(config, mdxConfig, viteConfig)
95
+ ]);
96
+ await Promise.all([
97
+ generateHtmlPages(config),
98
+ generateAssets(config),
99
+ generatePublic(config)
87
100
  ]);
88
- await Promise.all([generateNoStyleTemp()]);
89
- await Promise.all([generateHtmlPages(config), generatePublic(config)]);
90
101
  await Promise.all([generateDownload(config)]);
91
102
  await Promise.all([
92
103
  generateBeautify(config, "html"),
package/dist/config.js CHANGED
@@ -41,6 +41,20 @@ const defaultConfig = {
41
41
  bundle: {
42
42
  outName: "bundle"
43
43
  },
44
+ partial: {
45
+ usePreact: false,
46
+ useIntersectionObserver: true,
47
+ outName: "partial",
48
+ rootAttrSuffix: "partial-hydration",
49
+ rootValuePrefix: "ph",
50
+ rootDOMElement: "div",
51
+ rootStyle: { display: "contents" },
52
+ intersectionObserverOptions: {
53
+ root: null,
54
+ rootMargin: "0px",
55
+ thresholds: [1]
56
+ }
57
+ },
44
58
  images: {
45
59
  outDir: "assets/images",
46
60
  outName: "[name]"
package/dist/esbuild.d.ts CHANGED
@@ -8,3 +8,4 @@ export declare function resolvePlugin(options: {
8
8
  export declare function svgrPlugin(options: SvgrOptions): Plugin;
9
9
  /*! Fork: esbuild-plugin-resolve | https://github.com/hannoeru/esbuild-plugin-raw */
10
10
  export declare function rawPlugin(): Plugin;
11
+ export declare function partialHydrationPlugin(): Plugin;
package/dist/esbuild.js CHANGED
@@ -17,8 +17,33 @@ var __spreadValues = (a, b) => {
17
17
  import React from "react";
18
18
  import fs from "fs-extra";
19
19
  import path from "path";
20
+ import { v4 as uuidv4 } from "uuid";
21
+ import { systemConfig } from "./system.js";
20
22
  /*! Fork: esbuild-plugin-resolve | https://github.com/markwylde/esbuild-plugin-resolve */
21
23
  function resolvePlugin(options) {
24
+ function resolvePluginIntercept(build, moduleName, moduleTarget) {
25
+ const filter = new RegExp("^" + moduleName + "(?:\\/.*)?$");
26
+ build.onResolve({ filter }, async (args) => {
27
+ if (args.resolveDir === "") {
28
+ return;
29
+ }
30
+ return {
31
+ path: args.path,
32
+ namespace: "esbuild-resolve",
33
+ pluginData: {
34
+ resolveDir: args.resolveDir,
35
+ moduleName
36
+ }
37
+ };
38
+ });
39
+ build.onLoad({ filter, namespace: "esbuild-resolve" }, async (args) => {
40
+ const importerCode = `
41
+ export * from '${args.path.replace(args.pluginData.moduleName, moduleTarget)}';
42
+ export { default } from '${args.path.replace(args.pluginData.moduleName, moduleTarget)}';
43
+ `;
44
+ return { contents: importerCode, resolveDir: args.pluginData.resolveDir };
45
+ });
46
+ }
22
47
  return {
23
48
  name: "esbuild-resolve",
24
49
  setup: (build) => {
@@ -28,29 +53,6 @@ function resolvePlugin(options) {
28
53
  }
29
54
  };
30
55
  }
31
- function resolvePluginIntercept(build, moduleName, moduleTarget) {
32
- const filter = new RegExp("^" + moduleName + "(?:\\/.*)?$");
33
- build.onResolve({ filter }, async (args) => {
34
- if (args.resolveDir === "") {
35
- return;
36
- }
37
- return {
38
- path: args.path,
39
- namespace: "esbuild-resolve",
40
- pluginData: {
41
- resolveDir: args.resolveDir,
42
- moduleName
43
- }
44
- };
45
- });
46
- build.onLoad({ filter, namespace: "esbuild-resolve" }, async (args) => {
47
- const importerCode = `
48
- export * from '${args.path.replace(args.pluginData.moduleName, moduleTarget)}';
49
- export { default } from '${args.path.replace(args.pluginData.moduleName, moduleTarget)}';
50
- `;
51
- return { contents: importerCode, resolveDir: args.pluginData.resolveDir };
52
- });
53
- }
54
56
  /*! Fork: esbuild-plugin-svgr | https://github.com/kazijawad/esbuild-plugin-svgr */
55
57
  function svgrPlugin(options) {
56
58
  return {
@@ -58,7 +60,7 @@ function svgrPlugin(options) {
58
60
  setup(build) {
59
61
  build.onLoad({ filter: /\.svg$/ }, async (args) => {
60
62
  const { transform: transformSvgr } = await import("@svgr/core");
61
- const svg = await fs.promises.readFile(args.path, "utf8");
63
+ const svg = await fs.readFile(args.path, "utf8");
62
64
  const contents = await transformSvgr(svg, __spreadValues({}, options), { filePath: args.path });
63
65
  return {
64
66
  contents,
@@ -81,14 +83,44 @@ function rawPlugin() {
81
83
  });
82
84
  build.onLoad({ filter: /\?raw$/, namespace: "raw-loader" }, async (args) => {
83
85
  return {
84
- contents: await fs.promises.readFile(args.path.replace(/\?raw$/, "")),
86
+ contents: await fs.readFile(args.path.replace(/\?raw$/, "")),
85
87
  loader: "text"
86
88
  };
87
89
  });
88
90
  }
89
91
  };
90
92
  }
93
+ function partialHydrationPlugin() {
94
+ return {
95
+ name: "esbuild-partial-hydration",
96
+ setup(build) {
97
+ build.onResolve({ filter: /\?ph$/ }, (args) => {
98
+ return {
99
+ path: path.isAbsolute(args.path) ? args.path : path.join(args.resolveDir, args.path),
100
+ namespace: "partial-hydration-loader"
101
+ };
102
+ });
103
+ build.onLoad({ filter: /\?ph$/, namespace: "partial-hydration-loader" }, async (args) => {
104
+ const jsPath = args.path.replace(/\?ph$/, "");
105
+ const uniqueId = uuidv4();
106
+ const underUniqueId = uniqueId.replace(/-/g, "_");
107
+ const outDir = systemConfig.temp.partialHydration.outDir;
108
+ const outFile = `${outDir}/modules/${underUniqueId}.txt`;
109
+ const template = `${jsPath}`;
110
+ await fs.outputFile(outFile, template).catch((err) => {
111
+ console.error(err);
112
+ });
113
+ const dummy = `export default () => <div data-partial-hydration="${underUniqueId}"></div>`;
114
+ return {
115
+ contents: dummy,
116
+ loader: "tsx"
117
+ };
118
+ });
119
+ }
120
+ };
121
+ }
91
122
  export {
123
+ partialHydrationPlugin,
92
124
  rawPlugin,
93
125
  resolvePlugin,
94
126
  svgrPlugin
@@ -4,9 +4,11 @@ import type { MinistaResolveConfig } from "./types.js";
4
4
  export declare function generateViteImporters(config: MinistaResolveConfig, viteConfig: ViteConfig): Promise<void>;
5
5
  export declare function generateTempRoot(config: MinistaResolveConfig, mdxConfig: MdxOptions): Promise<void>;
6
6
  export declare function generateTempPages(config: MinistaResolveConfig, mdxConfig: MdxOptions): Promise<void>;
7
- export declare function generateAssets(config: MinistaResolveConfig, viteConfig: InlineConfig): Promise<void>;
8
- export declare function generateNoStyleTemp(): Promise<void>;
7
+ export declare function generateTempAssets(config: MinistaResolveConfig, viteConfig: InlineConfig): Promise<void>;
8
+ export declare function generatePartialHydration(config: MinistaResolveConfig, mdxConfig: MdxOptions, viteConfig: InlineConfig): Promise<void>;
9
+ export declare function generateNoStyleTemp(targetDir: string): Promise<void>;
9
10
  export declare function generateHtmlPages(config: MinistaResolveConfig): Promise<void>;
11
+ export declare function generateAssets(config: MinistaResolveConfig): Promise<void>;
10
12
  export declare function generatePublic(config: MinistaResolveConfig): Promise<void>;
11
13
  export declare function generateDownload(config: MinistaResolveConfig): Promise<void>;
12
14
  export declare function generateBeautify(config: MinistaResolveConfig, target: "html" | "css" | "js"): Promise<void>;
package/dist/generate.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import React from "react";
2
+ import path from "path";
3
+ import url from "url";
2
4
  import { systemConfig } from "./system.js";
3
5
  import { getFilePath, getFilePaths, getSameFilePaths } from "./path.js";
4
6
  import { slashEnd, noSlashEnd } from "./utils.js";
@@ -11,11 +13,19 @@ import {
11
13
  buildViteImporterRoots,
12
14
  buildViteImporterRoutes,
13
15
  buildViteImporterAssets,
14
- buildViteImporterBlankAssets
16
+ buildViteImporterBlankAssets,
17
+ buildPartialModules,
18
+ buildPartialStringIndex,
19
+ buildPartialStringBundle,
20
+ buildPartialStringInitial,
21
+ buildPartialHydrateIndex,
22
+ buildPartialHydrateAssets
15
23
  } from "./build.js";
16
24
  import { optimizeCommentOutStyleImport } from "./optimize.js";
17
25
  import { downloadFiles } from "./download.js";
18
26
  import { beautifyFiles } from "./beautify.js";
27
+ const __filename = url.fileURLToPath(import.meta.url);
28
+ const __dirname = path.dirname(__filename);
19
29
  async function generateViteImporters(config, viteConfig) {
20
30
  var _a, _b;
21
31
  const viteEntry = ((_b = (_a = viteConfig.build) == null ? void 0 : _a.rollupOptions) == null ? void 0 : _b.input) || {};
@@ -49,21 +59,55 @@ async function generateTempPages(config, mdxConfig) {
49
59
  svgrOptions: config.assets.svgr.svgrOptions
50
60
  });
51
61
  }
52
- async function generateAssets(config, viteConfig) {
62
+ async function generateTempAssets(config, viteConfig) {
53
63
  await buildTempAssets(viteConfig, {
64
+ input: path.resolve(__dirname + "/../dist/bundle.js"),
54
65
  bundleOutName: config.assets.bundle.outName,
55
66
  outDir: systemConfig.temp.assets.outDir,
56
- assetDir: config.assets.outDir
67
+ assetDir: config.assets.outDir,
68
+ generateJs: false
57
69
  });
58
70
  await buildCopyDir(systemConfig.temp.assets.outDir, slashEnd(config.out) + noSlashEnd(config.assets.outDir), "assets");
59
71
  }
60
- async function generateNoStyleTemp() {
61
- const tempRootOutDir = systemConfig.temp.root.outDir;
62
- const tempPagesOutDir = systemConfig.temp.pages.outDir;
63
- const tempRootFiles = await getFilePaths(tempRootOutDir, "mjs");
64
- const tempPagesFiles = await getFilePaths(tempPagesOutDir, "mjs");
65
- await optimizeCommentOutStyleImport(tempRootFiles);
66
- await optimizeCommentOutStyleImport(tempPagesFiles);
72
+ async function generatePartialHydration(config, mdxConfig, viteConfig) {
73
+ const moduleDir = systemConfig.temp.partialHydration.outDir + "/modules";
74
+ const moduleFilePaths = await getFilePaths(moduleDir, "txt");
75
+ if (moduleFilePaths.length === 0) {
76
+ return;
77
+ }
78
+ const partialModules = await buildPartialModules(moduleFilePaths, config);
79
+ const outDir = systemConfig.temp.partialHydration.outDir;
80
+ const stringIndex = `${outDir}/string-index.mjs`;
81
+ const stringBundle = `${outDir}/string-bundle.mjs`;
82
+ const stringInitial = `${outDir}/string-initial.json`;
83
+ const hydrateIndex = `${outDir}/hydrate-index.mjs`;
84
+ await buildPartialStringIndex(partialModules, { outFile: stringIndex });
85
+ await buildPartialStringBundle(stringIndex, {
86
+ outFile: stringBundle,
87
+ mdxConfig,
88
+ svgrOptions: config.assets.svgr.svgrOptions
89
+ });
90
+ await optimizeCommentOutStyleImport([stringBundle]);
91
+ await buildPartialStringInitial(stringBundle, partialModules, {
92
+ outFile: stringInitial
93
+ });
94
+ await buildPartialHydrateIndex(partialModules, config, {
95
+ outFile: hydrateIndex
96
+ });
97
+ await buildPartialHydrateAssets(viteConfig, {
98
+ input: hydrateIndex,
99
+ bundleOutName: config.assets.partial.outName,
100
+ outDir: systemConfig.temp.assets.outDir,
101
+ assetDir: config.assets.outDir,
102
+ generateJs: true,
103
+ usePreact: config.assets.partial.usePreact
104
+ });
105
+ }
106
+ async function generateNoStyleTemp(targetDir) {
107
+ const targetFiles = await getFilePaths(targetDir, "mjs");
108
+ if (targetFiles.length !== 0) {
109
+ await optimizeCommentOutStyleImport(targetFiles);
110
+ }
67
111
  }
68
112
  async function generateHtmlPages(config) {
69
113
  const tempRootName = config.root.srcName;
@@ -85,6 +129,9 @@ async function generateHtmlPages(config) {
85
129
  outDir: config.pagesOutDir
86
130
  }, assetsTagStr);
87
131
  }
132
+ async function generateAssets(config) {
133
+ await buildCopyDir(systemConfig.temp.assets.outDir, slashEnd(config.out) + noSlashEnd(config.assets.outDir), "assets");
134
+ }
88
135
  async function generatePublic(config) {
89
136
  await buildCopyDir(config.public, config.publicOutDir, "public");
90
137
  }
@@ -128,7 +175,9 @@ export {
128
175
  generateDownload,
129
176
  generateHtmlPages,
130
177
  generateNoStyleTemp,
178
+ generatePartialHydration,
131
179
  generatePublic,
180
+ generateTempAssets,
132
181
  generateTempPages,
133
182
  generateTempRoot,
134
183
  generateViteImporters
package/dist/system.js CHANGED
@@ -8,6 +8,9 @@ const systemConfig = {
8
8
  viteImporter: {
9
9
  outDir: "node_modules/.minista/vite-importer"
10
10
  },
11
+ partialHydration: {
12
+ outDir: "node_modules/.minista/partial-hydration"
13
+ },
11
14
  root: {
12
15
  outDir: "node_modules/.minista/bundled-react-root"
13
16
  },
package/dist/types.d.ts CHANGED
@@ -26,6 +26,20 @@ export declare type MinistaConfig = {
26
26
  bundle: {
27
27
  outName: string;
28
28
  };
29
+ partial: {
30
+ usePreact: boolean;
31
+ useIntersectionObserver: boolean;
32
+ outName: string;
33
+ rootAttrSuffix: string;
34
+ rootValuePrefix: string;
35
+ rootDOMElement: "div" | "span";
36
+ rootStyle: React.CSSProperties;
37
+ intersectionObserverOptions: {
38
+ root: Element | null;
39
+ rootMargin: string;
40
+ thresholds: ReadonlyArray<number>;
41
+ };
42
+ };
29
43
  images: {
30
44
  outDir: string;
31
45
  outName: string;
@@ -87,6 +101,20 @@ export declare type MinistaUserConfig = {
87
101
  bundle?: {
88
102
  outName?: string;
89
103
  };
104
+ partial?: {
105
+ usePreact?: boolean;
106
+ useIntersectionObserver?: boolean;
107
+ outName?: string;
108
+ rootAttrSuffix?: string;
109
+ rootValuePrefix?: string;
110
+ rootDOMElement?: "div" | "span";
111
+ rootStyle?: React.CSSProperties;
112
+ intersectionObserverOptions?: {
113
+ root?: Element | null;
114
+ rootMargin?: string;
115
+ thresholds?: ReadonlyArray<number>;
116
+ };
117
+ };
90
118
  images?: {
91
119
  outDir?: string;
92
120
  outName?: string;
@@ -163,6 +191,9 @@ export declare type MinistaSystemConfig = {
163
191
  viteImporter: {
164
192
  outDir: string;
165
193
  };
194
+ partialHydration: {
195
+ outDir: string;
196
+ };
166
197
  root: {
167
198
  outDir: string;
168
199
  };
@@ -226,3 +257,17 @@ export declare type StaticDataCache = {
226
257
  key: [StaticDataList];
227
258
  } | {};
228
259
  export declare type GetStaticData = () => Promise<StaticData>;
260
+ export declare type PartialModules = {
261
+ id: string;
262
+ phId: string;
263
+ phDomId: string;
264
+ htmlId: string;
265
+ targetsId: string;
266
+ importer: string;
267
+ rootAttr: string;
268
+ rootDOMElement: string;
269
+ rootStyleStr: string;
270
+ }[];
271
+ export declare type PartialString = {
272
+ [key: string]: string;
273
+ };
package/dist/user.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import path from "path";
3
+ import url from "url";
3
4
  import { build as esBuild } from "esbuild";
4
5
  import { systemConfig } from "./system.js";
5
6
  import { getSameFilePaths } from "./path.js";
@@ -22,7 +23,9 @@ async function getUserConfig(cofigPath = ".") {
22
23
  format: "esm",
23
24
  platform: "node"
24
25
  }).catch(() => process.exit(1));
25
- const { default: userConfig } = await import(path.resolve(`${systemConfig.temp.config.outDir}/minista.config.mjs`));
26
+ const userConfigPath = path.resolve(`${systemConfig.temp.config.outDir}/minista.config.mjs`);
27
+ const userConfigFilePath = url.pathToFileURL(userConfigPath).href;
28
+ const { default: userConfig } = await import(userConfigFilePath);
26
29
  return userConfig || {};
27
30
  } else {
28
31
  return {};
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ /// <reference types="react" />
1
2
  export declare function slashEnd(dir: string): string;
2
3
  export declare function noSlashEnd(dir: string): string;
3
4
  export declare function getFilename(fullPath: string): string;
4
5
  export declare function getFilenameObject(fullPaths: string[]): any;
5
6
  export declare function valueToStringObject(obj: {} | any | undefined): any;
6
7
  export declare function sortObject(obj: {} | undefined): [string, unknown][] | undefined;
8
+ export declare function reactStylesToString(styles: React.CSSProperties): string;
package/dist/utils.js CHANGED
@@ -54,10 +54,20 @@ function sortObject(obj) {
54
54
  }
55
55
  return sorted;
56
56
  }
57
+ function reactStylesToString(styles) {
58
+ const result = Object.entries(styles).map(([key, value]) => {
59
+ const reg = new RegExp(/[A-Z]/g);
60
+ const cssKey = key.replace(reg, (v) => `-${v.toLowerCase()}`);
61
+ const cssValue = value;
62
+ return `${cssKey}:${cssValue};`;
63
+ }).join("");
64
+ return result;
65
+ }
57
66
  export {
58
67
  getFilename,
59
68
  getFilenameObject,
60
69
  noSlashEnd,
70
+ reactStylesToString,
61
71
  slashEnd,
62
72
  sortObject,
63
73
  valueToStringObject
package/dist/vite.js CHANGED
@@ -153,8 +153,9 @@ function vitePluginMinistaVirtualHtml() {
153
153
  configureServer(server) {
154
154
  return () => {
155
155
  var _a, _b;
156
- const ministaHtmlURL = new URL(path.resolve(__dirname + "/../lib/index.html"), import.meta.url);
157
- const ministaHtml = fs.readFileSync(ministaHtmlURL, "utf8");
156
+ const ministaHtmlUrl = path.resolve(__dirname + "/../lib/index.html");
157
+ const ministaHtmlUrlRelative = path.relative(".", ministaHtmlUrl);
158
+ const ministaHtml = fs.readFileSync(ministaHtmlUrlRelative, "utf8");
158
159
  const assetTagStr = getAssetsTagStr((_b = (_a = server.config.inlineConfig.build) == null ? void 0 : _a.rollupOptions) == null ? void 0 : _b.input);
159
160
  const ministaReplacedHtml = ministaHtml.replace("<!-- VIRTUAL_HTML_ASSETS_TAG -->", assetTagStr);
160
161
  server.middlewares.use((req, res, next) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "minista",
3
3
  "description": "Next.js Like Development with 100% Static Generate",
4
- "version": "2.3.0",
4
+ "version": "2.4.0",
5
5
  "bin": {
6
6
  "minista": "./bin/minista.js"
7
7
  },
@@ -72,17 +72,16 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@mdx-js/esbuild": "^2.1.1",
75
- "@mdx-js/react": "^2.1.1",
76
75
  "@mdx-js/rollup": "^2.1.1",
77
76
  "@svgr/core": "^6.2.1",
78
- "@vitejs/plugin-react": "^1.3.0",
77
+ "@vitejs/plugin-react": "^1.3.2",
79
78
  "cac": "^6.7.12",
80
- "deepmerge-ts": "^4.0.2",
81
- "esbuild": "^0.14.29",
82
- "fs-extra": "^10.0.1",
83
- "js-beautify": "^1.14.2",
79
+ "deepmerge-ts": "^4.0.3",
80
+ "esbuild": "^0.14.38",
81
+ "fs-extra": "^10.1.0",
82
+ "js-beautify": "^1.14.3",
84
83
  "mime-types": "^2.1.35",
85
- "node-fetch": "^3.2.3",
84
+ "node-fetch": "^3.2.4",
86
85
  "node-html-parser": "^5.3.3",
87
86
  "picocolors": "^1.0.0",
88
87
  "react-helmet": "^6.1.0",
@@ -94,20 +93,22 @@
94
93
  "srcset": "^5.0.0",
95
94
  "svgstore": "^3.0.1",
96
95
  "tiny-glob": "^0.2.9",
97
- "vite": "^2.9.1"
96
+ "uuid": "^8.3.2",
97
+ "vite": "^2.9.8"
98
98
  },
99
99
  "devDependencies": {
100
100
  "@types/fs-extra": "^9.0.13",
101
101
  "@types/js-beautify": "^1.13.3",
102
102
  "@types/mime-types": "^2.1.1",
103
- "@types/node": "^17.0.23",
103
+ "@types/node": "^17.0.31",
104
104
  "@types/react": "^17.0.43",
105
105
  "@types/react-dom": "^17.0.14",
106
106
  "@types/react-helmet": "^6.1.5",
107
+ "@types/uuid": "^8.3.4",
107
108
  "react": "^17.0.2",
108
109
  "react-dom": "^17.0.2",
109
- "tsup": "^5.12.2",
110
- "typescript": "^4.6.3",
111
- "vitest": "^0.8.1"
110
+ "tsup": "^5.12.7",
111
+ "typescript": "^4.6.4",
112
+ "vitest": "^0.12.0"
112
113
  }
113
114
  }