solidstep 0.1.4 → 0.1.6
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 +110 -18
- package/index.d.ts +9 -0
- package/index.d.ts.map +1 -1
- package/index.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ Configure your app in `app.config.ts`:
|
|
|
48
48
|
|
|
49
49
|
```tsx
|
|
50
50
|
import { defineConfig } from 'solidstep';
|
|
51
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
51
52
|
|
|
52
53
|
export default defineConfig({
|
|
53
54
|
server: {
|
|
@@ -55,13 +56,53 @@ export default defineConfig({
|
|
|
55
56
|
},
|
|
56
57
|
plugins: [
|
|
57
58
|
{
|
|
58
|
-
type: 'both'
|
|
59
|
-
plugin:
|
|
60
|
-
}
|
|
59
|
+
type: 'client', // or 'server' or 'both' - depends on where you want to use the plugin
|
|
60
|
+
plugin: tailwindcss()
|
|
61
|
+
}
|
|
61
62
|
],
|
|
62
63
|
});
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
#### Vite Configuration
|
|
67
|
+
|
|
68
|
+
You can customize Vite settings for both client and server builds.
|
|
69
|
+
|
|
70
|
+
__When trying to configure absolute path imports__
|
|
71
|
+
1. Add the path alias in tsconfig.json (for TypeScript support):
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"compilerOptions": {
|
|
75
|
+
"baseUrl": ".",
|
|
76
|
+
"paths": {
|
|
77
|
+
"@/*": ["./*"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. Then add the same alias in the Vite config inside `app.config.ts` to ensure it works during build and runtime:
|
|
84
|
+
```tsx
|
|
85
|
+
import { defineConfig } from 'solidstep';
|
|
86
|
+
import { resolve } from 'node:path';
|
|
87
|
+
import { dirname } from 'node:path';
|
|
88
|
+
import { fileURLToPath } from 'node:url';
|
|
89
|
+
|
|
90
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
91
|
+
|
|
92
|
+
export default defineConfig({
|
|
93
|
+
server: {
|
|
94
|
+
preset: 'node',
|
|
95
|
+
},
|
|
96
|
+
vite: {
|
|
97
|
+
resolve: {
|
|
98
|
+
alias: {
|
|
99
|
+
'@': resolve(__dirname, '.'),
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
65
106
|
### Project Structure
|
|
66
107
|
|
|
67
108
|
```
|
|
@@ -169,15 +210,13 @@ export default function RootLayout(props: {
|
|
|
169
210
|
slots: { graph1: any; graph2: any; };
|
|
170
211
|
}) {
|
|
171
212
|
return (
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
</main>
|
|
180
|
-
</div>
|
|
213
|
+
<main>
|
|
214
|
+
{props.children()}
|
|
215
|
+
<aside>
|
|
216
|
+
<div>{props.slots.graph1()}</div>
|
|
217
|
+
<div>{props.slots.graph2()}</div>
|
|
218
|
+
</aside>
|
|
219
|
+
</main>
|
|
181
220
|
);
|
|
182
221
|
}
|
|
183
222
|
```
|
|
@@ -323,7 +362,7 @@ Configure page-level caching:
|
|
|
323
362
|
```tsx
|
|
324
363
|
export const options = {
|
|
325
364
|
cache: {
|
|
326
|
-
ttl: 60000,
|
|
365
|
+
ttl: 60000, // Cache for 60 seconds
|
|
327
366
|
},
|
|
328
367
|
};
|
|
329
368
|
```
|
|
@@ -350,6 +389,21 @@ export async function POST(request: Request) {
|
|
|
350
389
|
}
|
|
351
390
|
```
|
|
352
391
|
|
|
392
|
+
## Server Assets
|
|
393
|
+
Serve static files from the `server-assets/` directory:
|
|
394
|
+
|
|
395
|
+
```my-app/
|
|
396
|
+
├── server-assets/
|
|
397
|
+
│ └── secret.txt
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Access via `my-app/server-assets/secret.txt` URL:
|
|
401
|
+
|
|
402
|
+
```ts
|
|
403
|
+
const TEMPLATE_PATH = join(process.cwd(), 'server-assets', 'templates', 'template.ejs');
|
|
404
|
+
const template = await fs.promises.readFile(TEMPLATE_PATH, 'utf-8');
|
|
405
|
+
```
|
|
406
|
+
|
|
353
407
|
## Utilities
|
|
354
408
|
|
|
355
409
|
### Cookies
|
|
@@ -400,7 +454,7 @@ const corsHeaders = corsMiddleware(origin, event.node.req.method === 'OPTIONS');
|
|
|
400
454
|
|
|
401
455
|
### CSP
|
|
402
456
|
```tsx
|
|
403
|
-
import { createBasePolicy, serializePolicy, withNonce } from '
|
|
457
|
+
import { createBasePolicy, serializePolicy, withNonce } from 'solidstep/utils/csp';
|
|
404
458
|
|
|
405
459
|
let cspPolicy = createBasePolicy();
|
|
406
460
|
|
|
@@ -417,7 +471,7 @@ event.response.headers.set('Content-Security-Policy', serializePolicy(cspPolicy)
|
|
|
417
471
|
|
|
418
472
|
### CSRF Protection
|
|
419
473
|
```tsx
|
|
420
|
-
import { csrf } from '
|
|
474
|
+
import { csrf } from 'solidstep/utils/csrf';
|
|
421
475
|
|
|
422
476
|
const trustedOrigins = ['https://example.com', 'https://another-example.com'];
|
|
423
477
|
|
|
@@ -539,7 +593,7 @@ export default defineConfig({
|
|
|
539
593
|
logger: {
|
|
540
594
|
level: 'info',
|
|
541
595
|
transport: {
|
|
542
|
-
target: 'pino-pretty',
|
|
596
|
+
target: 'pino-pretty', // Use pino-pretty for human-readable logs
|
|
543
597
|
options: {
|
|
544
598
|
colorize: true
|
|
545
599
|
}
|
|
@@ -653,14 +707,52 @@ If accidentally imported on the client, it will throw:
|
|
|
653
707
|
Error: This module is only available on the server side.
|
|
654
708
|
```
|
|
655
709
|
|
|
710
|
+
## Preloading/prefetching strategies
|
|
711
|
+
SolidStep supports various preloading and prefetching strategies to enhance user experience by loading data and resources ahead of time. This can significantly reduce perceived latency and improve navigation speed within your application. Solidstep does not include any preloading/prefetching by default, but you can implement your own strategies using the built-in fetch utilities and SolidJS features.
|
|
712
|
+
|
|
713
|
+
Some common strategies include:
|
|
714
|
+
- **Link Prefetching**: Use the `<link rel="prefetch">` tag to hint the browser to prefetch resources for links that users are likely to click on next.
|
|
715
|
+
- **Using Intersection Observer**: Implement lazy loading and prefetching of data when certain elements come into the viewport.
|
|
716
|
+
- **Using [instant.page](https://instant.page/)**: A small library that preloads pages on hover or touchstart events.
|
|
717
|
+
```tsx
|
|
718
|
+
export const RootLayout = (props) => {
|
|
719
|
+
return (
|
|
720
|
+
<body>
|
|
721
|
+
...
|
|
722
|
+
<NoHydration>
|
|
723
|
+
<script src="//instant.page/5.2.0" type="module" integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script>
|
|
724
|
+
</NoHydration>
|
|
725
|
+
</body>
|
|
726
|
+
);
|
|
727
|
+
};
|
|
728
|
+
```
|
|
729
|
+
- **Using [Foresight.js](https://foresightjs.com/)**: A library that preloads pages based on user behavior and patterns.
|
|
730
|
+
```tsx
|
|
731
|
+
import { ForesightManager } from "js.foresight";
|
|
732
|
+
import { onMount } from "solid-js";
|
|
733
|
+
|
|
734
|
+
export const RootLayout = (props) => {
|
|
735
|
+
onMount(() => {
|
|
736
|
+
ForesightManager.initialize({
|
|
737
|
+
// Configuration options
|
|
738
|
+
});
|
|
739
|
+
});
|
|
740
|
+
return (
|
|
741
|
+
<body>
|
|
742
|
+
...
|
|
743
|
+
</body>
|
|
744
|
+
);
|
|
745
|
+
};
|
|
746
|
+
```
|
|
747
|
+
- **Custom Preloading Logic**: Write custom logic to preload data for specific routes or components based on user behavior or application state.
|
|
748
|
+
|
|
656
749
|
## Future Plans
|
|
657
750
|
- Revalidate on demand
|
|
658
|
-
- Preloading/prefetching strategies
|
|
659
751
|
- Support for dynamic site.webmanifest, robots.txt, sitemap.xml, manifest.json, and llms.txt
|
|
660
752
|
- Support loading and error pages for parallel routes
|
|
661
753
|
- Support deferring loaders
|
|
662
754
|
- Image/font optimizations
|
|
663
|
-
- Possible
|
|
755
|
+
- Possible SSG, ISR, and PPR
|
|
664
756
|
- Advanced caching strategies
|
|
665
757
|
- WebSocket support
|
|
666
758
|
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { AppOptions } from 'vinxi';
|
|
2
2
|
import type { LoggerOptions } from 'pino';
|
|
3
|
+
import type { CustomizableConfig } from 'vinxi/dist/types/lib/vite-dev';
|
|
4
|
+
import type { InlineConfig } from 'vite';
|
|
5
|
+
type VinxiViteServerOptions = Omit<InlineConfig["server"], "port" | "strictPort" | "host" | "middlewareMode" | "open">;
|
|
6
|
+
type ViteCustomizableConfig = CustomizableConfig & {
|
|
7
|
+
server?: VinxiViteServerOptions;
|
|
8
|
+
};
|
|
3
9
|
type Config = {
|
|
4
10
|
server?: Omit<AppOptions['server'], 'experimental'>;
|
|
5
11
|
plugins?: {
|
|
@@ -7,6 +13,9 @@ type Config = {
|
|
|
7
13
|
plugin: any;
|
|
8
14
|
}[];
|
|
9
15
|
logger?: true | LoggerOptions;
|
|
16
|
+
vite?: ViteCustomizableConfig | ((options: {
|
|
17
|
+
router: 'server' | 'client';
|
|
18
|
+
}) => ViteCustomizableConfig);
|
|
10
19
|
};
|
|
11
20
|
export declare const defineConfig: (config?: Config) => import("vinxi").App;
|
|
12
21
|
export {};
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAUxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAUxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAGzC,KAAK,sBAAsB,GAAG,IAAI,CAC9B,YAAY,CAAC,QAAQ,CAAC,EACtB,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,gBAAgB,GAAG,MAAM,CAC7D,CAAC;AAEF,KAAK,sBAAsB,GAAG,kBAAkB,GAAG;IAC/C,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACnC,CAAC;AAEF,KAAK,MAAM,GAAG;IACV,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE;QACN,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;QACnC,MAAM,EAAE,GAAG,CAAC;KACf,EAAE,CAAC;IACJ,MAAM,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC;IAC9B,IAAI,CAAC,EACC,sBAAsB,GACtB,CAAC,CAAC,OAAO,EAAE;QACT,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;KAC/B,KAAK,sBAAsB,CAAC,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAQ,MAIpC,wBAsHA,CAAC"}
|
package/index.js
CHANGED
|
@@ -7,9 +7,11 @@ import { join } from 'node:path';
|
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { cpSync, mkdirSync, existsSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { normalize } from 'vinxi/lib/path';
|
|
10
|
+
import { config as viteConfigPlugin } from 'vinxi/plugins/config';
|
|
10
11
|
export const defineConfig = (config = {
|
|
11
12
|
server: {},
|
|
12
13
|
plugins: [],
|
|
14
|
+
vite: {},
|
|
13
15
|
}) => {
|
|
14
16
|
let middlewarePath = join(process.cwd(), 'app', 'middleware.ts');
|
|
15
17
|
if (!existsSync(middlewarePath)) {
|
|
@@ -20,6 +22,9 @@ export const defineConfig = (config = {
|
|
|
20
22
|
};
|
|
21
23
|
// @ts-ignore
|
|
22
24
|
globalThis.__SOLIDSTEP_CONFIG__ = sharedConfig;
|
|
25
|
+
const viteConfig = typeof config.vite === 'function'
|
|
26
|
+
? config.vite
|
|
27
|
+
: () => config.vite || {};
|
|
23
28
|
const app = createApp({
|
|
24
29
|
server: {
|
|
25
30
|
...config.server,
|
|
@@ -47,6 +52,9 @@ export const defineConfig = (config = {
|
|
|
47
52
|
runtime: normalize(fileURLToPath(new URL('./utils/server-action.client.js', import.meta.url))),
|
|
48
53
|
}),
|
|
49
54
|
solid({ ssr: true }),
|
|
55
|
+
viteConfigPlugin('app-client', {
|
|
56
|
+
...(viteConfig({ router: 'client' }) || {}),
|
|
57
|
+
}),
|
|
50
58
|
],
|
|
51
59
|
base: '/_build',
|
|
52
60
|
routes: (router, app) => {
|
|
@@ -68,6 +76,9 @@ export const defineConfig = (config = {
|
|
|
68
76
|
.map(p => p.plugin) || []),
|
|
69
77
|
serverFunctions.server(),
|
|
70
78
|
solid({ ssr: true }),
|
|
79
|
+
viteConfigPlugin('app-server', {
|
|
80
|
+
...(viteConfig({ router: 'server' }) || {}),
|
|
81
|
+
}),
|
|
71
82
|
],
|
|
72
83
|
middleware: './app/middleware.ts',
|
|
73
84
|
routes: (router, app) => {
|