vite-react-ssg 0.0.3 → 0.1.1

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Riri
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Riri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,239 +1,308 @@
1
- # Vite React SSG
2
-
3
- Static-site generation for React on Vite.
4
-
5
- [![NPM version](https://img.shields.io/npm/v/vite-react-ssg?color=a1b858&label=)](https://www.npmjs.com/package/vite-react-ssg)
6
-
7
- ## Install
8
-
9
- > **This library requires Node.js version >= 17**
10
- > or `Request` is available
11
- <pre>
12
- <b>npm i -D vite-react-ssg</b> <em>react-router-dom</em>
13
- </pre>
14
-
15
- ```diff
16
- // package.json
17
- {
18
- "scripts": {
19
- "dev": "vite",
20
- - "build": "vite build"
21
- + "build": "vite-react-ssg build"
22
-
23
- // OR if you want to use another vite config file
24
- + "build": "vite-react-ssg build -c another-vite.config.ts"
25
- }
26
- }
27
- ```
28
-
29
- ```ts
30
- // src/main.ts
31
- import { ViteReactSSG } from 'vite-react-ssg'
32
- import routes from './App.tsx'
33
-
34
- export const createRoot = ViteReactSSG(
35
- // react-router-dom data routes
36
- { routes },
37
- // function to have custom setups
38
- ({ router, routes, isClient, initialState }) => {
39
- // do something.
40
- },
41
- )
42
- ```
43
-
44
- ```tsx
45
- // src/App.tsx
46
- import React from 'react'
47
- import type { RouteRecord } from 'vite-react-ssg'
48
- import './App.css'
49
-
50
- const pages = import.meta.glob<any>('./pages/**/*.tsx')
51
-
52
- const children: RouteRecord[] = Object.entries(pages).map(([filepath, component]) => {
53
- let path = filepath.split('/pages')[1]
54
- path = path.split('.')[0].replace('index', '')
55
- const entry = `src${filepath.slice(1)}`
56
-
57
- if (path.endsWith('/')) {
58
- return {
59
- index: true,
60
- Component: React.lazy(component),
61
- entry,
62
- }
63
- }
64
- return {
65
- path,
66
- Component: React.lazy(component),
67
- // Used to obtain static resources through manifest
68
- entry,
69
- }
70
- })
71
-
72
- const Layout = React.lazy(() => import('./Layout'))
73
- export const routes: RouteRecord[] = [
74
- {
75
- path: '/',
76
- element: <Layout />,
77
- children,
78
- // Used to obtain static resources through manifest
79
- entry: 'src/Layout.tsx',
80
- },
81
- ]
82
- ```
83
-
84
- ## Document head
85
-
86
- You can use `<Head/>` to manage all of your changes to the document head. It takes plain HTML tags and outputs plain HTML tags. It is a wrapper around [React Helmet](https://github.com/nfl/react-helmet).
87
-
88
- ```tsx
89
- import { Head } from 'vite-react-ssg'
90
-
91
- const MyHead = () => (
92
- <Head>
93
- <meta property="og:description" content="My custom description" />
94
- <meta charSet="utf-8" />
95
- <title>My Title</title>
96
- <link rel="canonical" href="http://mysite.com/example" />
97
- </Head>
98
- )
99
- ```
100
-
101
- Nested or latter components will override duplicate usages:
102
-
103
- ```tsx
104
- import { Head } from 'vite-react-ssg'
105
-
106
- const MyHead = () => (
107
- <parent>
108
- <Head>
109
- <title>My Title</title>
110
- <meta name="description" content="Helmet application" />
111
- </Head>
112
- <child>
113
- <Head>
114
- <title>Nested Title</title>
115
- <meta name="description" content="Nested component" />
116
- </Head>
117
- </child>
118
- </parent>
119
- )
120
- ```
121
-
122
- Outputs:
123
- ```html
124
- <head>
125
- <title>Nested Title</title>
126
- <meta name="description" content="Nested component" />
127
- </head>
128
- ```
129
-
130
- ### Reactive head
131
-
132
- ```tsx
133
- import { useState } from 'react'
134
- import { Head } from 'vite-react-ssg'
135
-
136
- export default function MyHead() {
137
- const [state, setState] = useState(false)
138
-
139
- return (
140
- <Head>
141
- <meta charSet="UTF-8" />
142
- <link rel="icon" type="image/svg+xml" href="/vite.svg" />
143
- <title>head test {state ? 'A' : 'B'}</title>
144
- {/* You can also set the 'body' attributes here */}
145
- <body className={`body-class-in-head-${state ? 'a' : 'b'}`} />
146
- </Head>
147
- )
148
- }
149
- ```
150
-
151
- ## Critical CSS
152
-
153
- Vite SSG has built-in support for generating [Critical CSS](https://web.dev/extract-critical-css/) inlined in the HTML via the [`critters`](https://github.com/GoogleChromeLabs/critters) package.
154
- Install it with:
155
-
156
- ```bash
157
- npm i -D critters
158
- ```
159
-
160
- Critical CSS generation will automatically be enabled for you.
161
-
162
- To configure `critters`, pass [its options](https://github.com/GoogleChromeLabs/critters#usage) into `ssgOptions.crittersOptions` in `vite.config.ts`:
163
-
164
- ```ts
165
- // vite.config.ts
166
- export default defineConfig({
167
- ssgOptions: {
168
- crittersOptions: {
169
- // E.g., change the preload strategy
170
- preload: 'media',
171
- // Other options: https://github.com/GoogleChromeLabs/critters#usage
172
- },
173
- },
174
- })
175
- ```
176
-
177
- ## Configuration
178
-
179
- You can pass options to Vite SSG in the `ssgOptions` field of your `vite.config.js`
180
-
181
- ```js
182
- // vite.config.js
183
-
184
- export default {
185
- plugins: [],
186
- ssgOptions: {
187
- script: 'async',
188
- },
189
- }
190
- ```
191
-
192
- See [src/types.ts](./src/types.ts). for more options available.
193
-
194
- ### Custom Routes to Render
195
-
196
- You can use the `includedRoutes` hook to include or exclude route paths to render, or even provide some completely custom ones.
197
-
198
- ```js
199
- // vite.config.js
200
-
201
- export default {
202
- plugins: [],
203
- ssgOptions: {
204
- includedRoutes(paths, routes) {
205
- // exclude all the route paths that contains 'foo'
206
- return paths.filter(i => !i.includes('foo'))
207
- },
208
- },
209
- }
210
- ```
211
- ```js
212
- // vite.config.js
213
-
214
- export default {
215
- plugins: [],
216
- ssgOptions: {
217
- includedRoutes(paths, routes) {
218
- // use original route records
219
- return routes.flatMap((route) => {
220
- return route.name === 'Blog'
221
- ? myBlogSlugs.map(slug => `/blog/${slug}`)
222
- : route.path
223
- })
224
- },
225
- },
226
- }
227
- ```
228
-
229
- ## Roadmap
230
-
231
- - [x] Preload assets
232
- - [x] Document head
233
- - [ ] SSR under dev
234
- - [ ] Initial State
235
- - [ ] More Client components, such as `<ClientOnly />`
236
-
237
- ## License
238
-
1
+ # Vite React SSG
2
+
3
+ Static-site generation for React on Vite.
4
+
5
+ [![NPM version](https://img.shields.io/npm/v/vite-react-ssg?color=a1b858&label=)](https://www.npmjs.com/package/vite-react-ssg)
6
+
7
+ ## Install
8
+
9
+ > **This library requires Node.js version >= 17**
10
+ > or `Request` is available
11
+ <pre>
12
+ <b>npm i -D vite-react-ssg</b> <em>react-router-dom</em>
13
+ </pre>
14
+
15
+ ```diff
16
+ // package.json
17
+ {
18
+ "scripts": {
19
+ - "dev": "vite",
20
+ - "build": "vite build"
21
+ + "dev": "vite-react-ssg dev",
22
+ + "build": "vite-react-ssg build"
23
+
24
+ // OR if you want to use another vite config file
25
+ + "build": "vite-react-ssg build -c another-vite.config.ts"
26
+ }
27
+ }
28
+ ```
29
+
30
+ ```ts
31
+ // src/main.ts
32
+ import { ViteReactSSG } from 'vite-react-ssg'
33
+ import routes from './App.tsx'
34
+
35
+ export const createRoot = ViteReactSSG(
36
+ // react-router-dom data routes
37
+ { routes },
38
+ // function to have custom setups
39
+ ({ router, routes, isClient, initialState }) => {
40
+ // do something.
41
+ },
42
+ )
43
+ ```
44
+
45
+ ```tsx
46
+ // src/App.tsx
47
+ import React from 'react'
48
+ import type { RouteRecord } from 'vite-react-ssg'
49
+ import './App.css'
50
+
51
+ const pages = import.meta.glob<any>('./pages/**/*.tsx')
52
+
53
+ const children: RouteRecord[] = Object.entries(pages).map(([filepath, component]) => {
54
+ let path = filepath.split('/pages')[1]
55
+ path = path.split('.')[0].replace('index', '')
56
+ const entry = `src${filepath.slice(1)}`
57
+
58
+ if (path.endsWith('/')) {
59
+ return {
60
+ index: true,
61
+ Component: React.lazy(component),
62
+ entry,
63
+ }
64
+ }
65
+ return {
66
+ path,
67
+ Component: React.lazy(component),
68
+ // Used to obtain static resources through manifest
69
+ entry,
70
+ }
71
+ })
72
+
73
+ const Layout = React.lazy(() => import('./Layout'))
74
+ export const routes: RouteRecord[] = [
75
+ {
76
+ path: '/',
77
+ element: <Layout />,
78
+ children,
79
+ // Used to obtain static resources through manifest
80
+ entry: 'src/Layout.tsx',
81
+ },
82
+ ]
83
+ ```
84
+
85
+ ## `<ClientOnly/>`
86
+
87
+ If you need to render some component in browser only, you can wrap your component with `<ClientOnly>`.
88
+
89
+ ```tsx
90
+ import { ClientOnly } from 'vite-react-ssg'
91
+
92
+ function MyComponent() {
93
+ return (
94
+ <ClientOnly>
95
+ {() => {
96
+ return <div>{window.location.href}</div>
97
+ }}
98
+ </ClientOnly>
99
+ )
100
+ }
101
+ ```
102
+
103
+ > It's important that the children of `<ClientOnly>` is not a JSX element, but a function that returns an element.
104
+ > Because React will try to render children, and may use the client's API on the server.
105
+
106
+ ## Document head
107
+
108
+ You can use `<Head/>` to manage all of your changes to the document head. It takes plain HTML tags and outputs plain HTML tags. It is a wrapper around [React Helmet](https://github.com/nfl/react-helmet).
109
+
110
+ ```tsx
111
+ import { Head } from 'vite-react-ssg'
112
+
113
+ const MyHead = () => (
114
+ <Head>
115
+ <meta property="og:description" content="My custom description" />
116
+ <meta charSet="utf-8" />
117
+ <title>My Title</title>
118
+ <link rel="canonical" href="http://mysite.com/example" />
119
+ </Head>
120
+ )
121
+ ```
122
+
123
+ Nested or latter components will override duplicate usages:
124
+
125
+ ```tsx
126
+ import { Head } from 'vite-react-ssg'
127
+
128
+ const MyHead = () => (
129
+ <parent>
130
+ <Head>
131
+ <title>My Title</title>
132
+ <meta name="description" content="Helmet application" />
133
+ </Head>
134
+ <child>
135
+ <Head>
136
+ <title>Nested Title</title>
137
+ <meta name="description" content="Nested component" />
138
+ </Head>
139
+ </child>
140
+ </parent>
141
+ )
142
+ ```
143
+
144
+ Outputs:
145
+ ```html
146
+ <head>
147
+ <title>Nested Title</title>
148
+ <meta name="description" content="Nested component" />
149
+ </head>
150
+ ```
151
+
152
+ ### Reactive head
153
+
154
+ ```tsx
155
+ import { useState } from 'react'
156
+ import { Head } from 'vite-react-ssg'
157
+
158
+ export default function MyHead() {
159
+ const [state, setState] = useState(false)
160
+
161
+ return (
162
+ <Head>
163
+ <meta charSet="UTF-8" />
164
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
165
+ <title>head test {state ? 'A' : 'B'}</title>
166
+ {/* You can also set the 'body' attributes here */}
167
+ <body className={`body-class-in-head-${state ? 'a' : 'b'}`} />
168
+ </Head>
169
+ )
170
+ }
171
+ ```
172
+
173
+ ## CSS in JS
174
+
175
+ Use the `getStyleCollector` option to specify an SSR/SSG style collector. Currently only supports `styled-components`.
176
+
177
+ ```tsx
178
+ import { ViteReactSSG } from 'vite-react-ssg'
179
+ import { getStyledComponentsCollector } from 'vite-react-ssg/style-collectors'
180
+ import { routes } from './App.js'
181
+ import './index.css'
182
+
183
+ export const createRoot = ViteReactSSG({ routes }, () => {}, { getStyleCollector: getStyledComponentsCollector })
184
+ ```
185
+
186
+ You can provide your own by looking at the [implementation](./src/style-collectors/) of any of the existing collectors.
187
+
188
+ ## Critical CSS
189
+
190
+ Vite SSG has built-in support for generating [Critical CSS](https://web.dev/extract-critical-css/) inlined in the HTML via the [`critters`](https://github.com/GoogleChromeLabs/critters) package.
191
+ Install it with:
192
+
193
+ ```bash
194
+ npm i -D critters
195
+ ```
196
+
197
+ Critical CSS generation will automatically be enabled for you.
198
+
199
+ To configure `critters`, pass [its options](https://github.com/GoogleChromeLabs/critters#usage) into `ssgOptions.crittersOptions` in `vite.config.ts`:
200
+
201
+ ```ts
202
+ // vite.config.ts
203
+ export default defineConfig({
204
+ ssgOptions: {
205
+ crittersOptions: {
206
+ // E.g., change the preload strategy
207
+ preload: 'media',
208
+ // Other options: https://github.com/GoogleChromeLabs/critters#usage
209
+ },
210
+ },
211
+ })
212
+ ```
213
+
214
+ ## Configuration
215
+
216
+ You can pass options to Vite SSG in the `ssgOptions` field of your `vite.config.js`
217
+
218
+ ```js
219
+ // vite.config.js
220
+
221
+ export default {
222
+ plugins: [],
223
+ ssgOptions: {
224
+ script: 'async',
225
+ },
226
+ }
227
+ ```
228
+
229
+ See [src/types.ts](./src/types.ts). for more options available.
230
+
231
+ ### Custom Routes to Render
232
+
233
+ You can use the `includedRoutes` hook to include or exclude route paths to render, or even provide some completely custom ones.
234
+
235
+ ```js
236
+ // vite.config.js
237
+
238
+ export default {
239
+ plugins: [],
240
+ ssgOptions: {
241
+ includedRoutes(paths, routes) {
242
+ // exclude all the route paths that contains 'foo'
243
+ return paths.filter(i => !i.includes('foo'))
244
+ },
245
+ },
246
+ }
247
+ ```
248
+ ```js
249
+ // vite.config.js
250
+
251
+ export default {
252
+ plugins: [],
253
+ ssgOptions: {
254
+ includedRoutes(paths, routes) {
255
+ // use original route records
256
+ return routes.flatMap((route) => {
257
+ return route.name === 'Blog'
258
+ ? myBlogSlugs.map(slug => `/blog/${slug}`)
259
+ : route.path
260
+ })
261
+ },
262
+ },
263
+ }
264
+ ```
265
+
266
+ ## Use CSR in development environment
267
+
268
+ If you want to use CSR during development, just:
269
+ ```ts
270
+ // src/main.ts
271
+ import { ViteReactSSG } from 'vite-react-ssg'
272
+ import routes from './App.tsx'
273
+
274
+ export const createRoot = ViteReactSSG(
275
+ { routes },
276
+ ({ router, routes, isClient, initialState }) => {
277
+ // do something.
278
+ },
279
+ {
280
+ // Default value is `true`
281
+ ssrWhenDev: false
282
+ }
283
+ )
284
+ ```
285
+
286
+ ```diff
287
+ // package.json
288
+ {
289
+ "scripts": {
290
+ - "dev": "vite-react-ssg dev",
291
+ + "dev": "vite",
292
+ "build": "vite-react-ssg build"
293
+ }
294
+ }
295
+ ```
296
+ Then, you can start the application with CSR in the development environment.
297
+
298
+ ## Roadmap
299
+
300
+ - [x] Preload assets
301
+ - [x] Document head
302
+ - [x] SSR in dev environment
303
+ - [ ] Initial State
304
+ - [ ] More Client components, such as `<ClientOnly />`
305
+
306
+ ## License
307
+
239
308
  [MIT](./LICENSE) License © 2023 [Riri](https://github.com/Daydreamer-riri)
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env node
2
- 'use strict'
3
- import('../dist/node/cli.mjs')
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+ import('../dist/node/cli.mjs')