next-ssr-middleware 0.10.0-rc.2 → 0.10.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 +165 -137
- package/dist/API.d.ts +1 -1
- package/dist/API.js +4 -4
- package/dist/API.js.map +1 -1
- package/package.json +2 -2
- package/source/API.ts +2 -2
package/ReadMe.md
CHANGED
|
@@ -1,137 +1,165 @@
|
|
|
1
|
-
# Next SSR middleware
|
|
2
|
-
|
|
3
|
-
[Koa][1]-like middlewares for [Next.js][2] **Server Side Rendering**
|
|
4
|
-
|
|
5
|
-
[][3]
|
|
6
|
-
[][4]
|
|
7
|
-
|
|
8
|
-
[][5]
|
|
9
|
-
|
|
10
|
-
## Versions
|
|
11
|
-
|
|
12
|
-
| SemVer | status | Next.js | MobX | [MobX i18n][6] |
|
|
13
|
-
| :----------: | :----------: | :-------: | :---------: | :------------: |
|
|
14
|
-
| `>=0.9` | ✅developing | `>=15` | `>=6.11` | `>=0.5` |
|
|
15
|
-
| `>=0.7 <0.9` | ❌deprecated | `>=9 <15` | `>=6.11` | `>=0.5` |
|
|
16
|
-
| `<0.7` | ❌deprecated | `>=9 <15` | `>=4 <6.11` | `<0.5` |
|
|
17
|
-
|
|
18
|
-
## Middlewares
|
|
19
|
-
|
|
20
|
-
1. Router
|
|
21
|
-
2. Error logger
|
|
22
|
-
3. JWT verifier
|
|
23
|
-
4. Props cache
|
|
24
|
-
5. i18n loader
|
|
25
|
-
6. OAuth 2 signer (with common providers)
|
|
26
|
-
1. GitHub
|
|
27
|
-
|
|
28
|
-
## Usage
|
|
29
|
-
|
|
30
|
-
### Page router
|
|
31
|
-
|
|
32
|
-
#### `pages/user/[id].tsx`
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import {
|
|
36
|
-
JWTProps,
|
|
37
|
-
RouterProps,
|
|
38
|
-
jwtVerifier,
|
|
39
|
-
cache,
|
|
40
|
-
errorLogger,
|
|
41
|
-
router,
|
|
42
|
-
translator
|
|
43
|
-
} from 'next-ssr-middleware';
|
|
44
|
-
|
|
45
|
-
import i18n from '../../model/Translation';
|
|
46
|
-
import { User, UserModel } from '../../model/User';
|
|
47
|
-
|
|
48
|
-
type UserDetailPageProps = User & JWTProps & RouterProps;
|
|
49
|
-
|
|
50
|
-
export const getServerSideProps = compose<{ id: string }, UserDetailPageProps>(
|
|
51
|
-
jwtVerifier(), // set `JWT_SECRET` in `.env.local` first
|
|
52
|
-
cache(),
|
|
53
|
-
errorLogger,
|
|
54
|
-
router,
|
|
55
|
-
translator(i18n),
|
|
56
|
-
async ({ params }) => {
|
|
57
|
-
const props = await new UserModel().getOne(params!.id);
|
|
58
|
-
|
|
59
|
-
return { notFound: !props, props };
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
export default function UserDetailPage({
|
|
64
|
-
jwtPayload,
|
|
65
|
-
route,
|
|
66
|
-
name,
|
|
67
|
-
summary
|
|
68
|
-
}: UserDetailPageProps) {
|
|
69
|
-
return (
|
|
70
|
-
<>
|
|
71
|
-
<h1>
|
|
72
|
-
{name} - {route.params!.id}
|
|
73
|
-
</h1>
|
|
74
|
-
<p>{summary}</p>
|
|
75
|
-
</>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### App router
|
|
81
|
-
|
|
82
|
-
#### `middleware.ts`
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
86
|
-
import { parseHeaders } from 'next-ssr-middleware';
|
|
87
|
-
|
|
88
|
-
export const config = {
|
|
89
|
-
// Matcher ignoring `/_next/`, `/api/` & icons
|
|
90
|
-
matcher: [
|
|
91
|
-
'/((?!api|_next/static|_next/image|favicon.ico|apple-icon|icon).*)'
|
|
92
|
-
]
|
|
93
|
-
};
|
|
94
|
-
export const middleware = ({ headers }: NextRequest) =>
|
|
95
|
-
NextResponse.next({ headers: parseHeaders(headers) });
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
#### `app/page.tsx`
|
|
99
|
-
|
|
100
|
-
```tsx
|
|
101
|
-
import { compose, withMiddleware, ServerProps } from 'next-ssr-middleware';
|
|
102
|
-
|
|
103
|
-
const getServerSideProps = compose(async () => {
|
|
104
|
-
const props = await (
|
|
105
|
-
await fetch('https://api.github.com/orgs/idea2app')
|
|
106
|
-
).json();
|
|
107
|
-
|
|
108
|
-
return { props };
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
const HomePage = withMiddleware(getServerSideProps, Home);
|
|
112
|
-
|
|
113
|
-
export default HomePage;
|
|
114
|
-
|
|
115
|
-
async function Home({ params, searchParams, ...props }: ServerProps) {
|
|
116
|
-
return (
|
|
117
|
-
<>
|
|
118
|
-
<h1>Home</h1>
|
|
119
|
-
<pre>{JSON.stringify(props, null, 4)}</pre>
|
|
120
|
-
</>
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
1
|
+
# Next SSR middleware
|
|
2
|
+
|
|
3
|
+
[Koa][1]-like middlewares for [Next.js][2] **Back-end API** & **Server Side Rendering**
|
|
4
|
+
|
|
5
|
+
[][3]
|
|
6
|
+
[][4]
|
|
7
|
+
|
|
8
|
+
[][5]
|
|
9
|
+
|
|
10
|
+
## Versions
|
|
11
|
+
|
|
12
|
+
| SemVer | status | Next.js | MobX | [MobX i18n][6] |
|
|
13
|
+
| :----------: | :----------: | :-------: | :---------: | :------------: |
|
|
14
|
+
| `>=0.9` | ✅developing | `>=15` | `>=6.11` | `>=0.5` |
|
|
15
|
+
| `>=0.7 <0.9` | ❌deprecated | `>=9 <15` | `>=6.11` | `>=0.5` |
|
|
16
|
+
| `<0.7` | ❌deprecated | `>=9 <15` | `>=4 <6.11` | `<0.5` |
|
|
17
|
+
|
|
18
|
+
## Middlewares
|
|
19
|
+
|
|
20
|
+
1. Router
|
|
21
|
+
2. Error logger
|
|
22
|
+
3. JWT verifier
|
|
23
|
+
4. Props cache
|
|
24
|
+
5. i18n loader
|
|
25
|
+
6. OAuth 2 signer (with common providers)
|
|
26
|
+
1. GitHub
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Page router
|
|
31
|
+
|
|
32
|
+
#### `pages/user/[id].tsx`
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import {
|
|
36
|
+
JWTProps,
|
|
37
|
+
RouterProps,
|
|
38
|
+
jwtVerifier,
|
|
39
|
+
cache,
|
|
40
|
+
errorLogger,
|
|
41
|
+
router,
|
|
42
|
+
translator
|
|
43
|
+
} from 'next-ssr-middleware';
|
|
44
|
+
|
|
45
|
+
import i18n from '../../model/Translation';
|
|
46
|
+
import { User, UserModel } from '../../model/User';
|
|
47
|
+
|
|
48
|
+
type UserDetailPageProps = User & JWTProps & RouterProps;
|
|
49
|
+
|
|
50
|
+
export const getServerSideProps = compose<{ id: string }, UserDetailPageProps>(
|
|
51
|
+
jwtVerifier(), // set `JWT_SECRET` in `.env.local` first
|
|
52
|
+
cache(),
|
|
53
|
+
errorLogger,
|
|
54
|
+
router,
|
|
55
|
+
translator(i18n),
|
|
56
|
+
async ({ params }) => {
|
|
57
|
+
const props = await new UserModel().getOne(params!.id);
|
|
58
|
+
|
|
59
|
+
return { notFound: !props, props };
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export default function UserDetailPage({
|
|
64
|
+
jwtPayload,
|
|
65
|
+
route,
|
|
66
|
+
name,
|
|
67
|
+
summary
|
|
68
|
+
}: UserDetailPageProps) {
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<h1>
|
|
72
|
+
{name} - {route.params!.id}
|
|
73
|
+
</h1>
|
|
74
|
+
<p>{summary}</p>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### App router
|
|
81
|
+
|
|
82
|
+
#### `middleware.ts`
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
86
|
+
import { parseHeaders } from 'next-ssr-middleware';
|
|
87
|
+
|
|
88
|
+
export const config = {
|
|
89
|
+
// Matcher ignoring `/_next/`, `/api/` & icons
|
|
90
|
+
matcher: [
|
|
91
|
+
'/((?!api|_next/static|_next/image|favicon.ico|apple-icon|icon).*)'
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
export const middleware = ({ headers }: NextRequest) =>
|
|
95
|
+
NextResponse.next({ headers: parseHeaders(headers) });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### `app/page.tsx`
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { compose, withMiddleware, ServerProps } from 'next-ssr-middleware';
|
|
102
|
+
|
|
103
|
+
const getServerSideProps = compose(async () => {
|
|
104
|
+
const props = await (
|
|
105
|
+
await fetch('https://api.github.com/orgs/idea2app')
|
|
106
|
+
).json();
|
|
107
|
+
|
|
108
|
+
return { props };
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const HomePage = withMiddleware(getServerSideProps, Home);
|
|
112
|
+
|
|
113
|
+
export default HomePage;
|
|
114
|
+
|
|
115
|
+
async function Home({ params, searchParams, ...props }: ServerProps) {
|
|
116
|
+
return (
|
|
117
|
+
<>
|
|
118
|
+
<h1>Home</h1>
|
|
119
|
+
<pre>{JSON.stringify(props, null, 4)}</pre>
|
|
120
|
+
</>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### API router
|
|
126
|
+
|
|
127
|
+
Located in [`pages/api/` of a Next.js project][7] or [`api/` of a Vercel serverless project][8].
|
|
128
|
+
|
|
129
|
+
#### `pages/api/echo.ts`
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { createKoaRouter, withKoaRouter } from 'next-ssr-middleware';
|
|
133
|
+
|
|
134
|
+
export const config = { api: { bodyParser: false } };
|
|
135
|
+
|
|
136
|
+
const router = createKoaRouter(import.meta.url);
|
|
137
|
+
|
|
138
|
+
router
|
|
139
|
+
.get('/', async context => {
|
|
140
|
+
context.body = context.request.query;
|
|
141
|
+
})
|
|
142
|
+
.post('/', async context => {
|
|
143
|
+
context.status = 201;
|
|
144
|
+
context.body = Reflect.get(context.request, 'body');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
export default withKoaRouter(router);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Cases
|
|
151
|
+
|
|
152
|
+
1. https://github.com/idea2app/Next-Bootstrap-ts
|
|
153
|
+
2. https://github.com/FreeCodeCamp-Chengdu/FreeCodeCamp-Chengdu.github.io
|
|
154
|
+
3. https://github.com/kaiyuanshe/kaiyuanshe.github.io
|
|
155
|
+
4. https://github.com/kaiyuanshe/OpenHackathon-Web
|
|
156
|
+
5. https://github.com/kaiyuanshe/OSS-toolbox
|
|
157
|
+
|
|
158
|
+
[1]: https://koajs.com/
|
|
159
|
+
[2]: https://nextjs.org/
|
|
160
|
+
[3]: https://libraries.io/npm/next-ssr-middleware
|
|
161
|
+
[4]: https://github.com/idea2app/Next-SSR-middleware/actions/workflows/main.yml
|
|
162
|
+
[5]: https://nodei.co/npm/next-ssr-middleware/
|
|
163
|
+
[6]: https://github.com/idea2app/MobX-i18n
|
|
164
|
+
[7]: https://github.com/idea2app/Lark-Next-Bootstrap-ts/tree/main/pages/api
|
|
165
|
+
[8]: https://github.com/idea2app/Vercel-Node-serverless/tree/master/api
|
package/dist/API.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ export type KoaCallback = ReturnType<(typeof Koa)['prototype']['callback']>;
|
|
|
5
5
|
export declare function withKoa<S, C>(...middlewares: Middleware<S, C>[]): KoaCallback;
|
|
6
6
|
export declare function withKoa<S, C>(option: KoaOption, ...middlewares: Middleware<S, C>[]): KoaCallback;
|
|
7
7
|
export declare const pageApiRouteOf: (path: string) => string;
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const createKoaRouter: <S, C extends RouterParamContext<S>>(moduleURI: string, option?: RouterOptions) => Router<S, C>;
|
|
9
9
|
export declare function withKoaRouter<S, C extends RouterParamContext<S>>(router: Router<S, C>, ...middlewares: Middleware<S, C>[]): KoaCallback;
|
|
10
10
|
export declare function withKoaRouter<S, C extends RouterParamContext<S>>(option: KoaOption, router: Router<S, C>, ...middlewares: Middleware<S, C>[]): KoaCallback;
|
package/dist/API.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createKoaRouter = exports.pageApiRouteOf = void 0;
|
|
4
4
|
exports.withKoa = withKoa;
|
|
5
5
|
exports.withKoaRouter = withKoaRouter;
|
|
6
6
|
var tslib_1 = require("tslib");
|
|
@@ -39,12 +39,12 @@ function withKoa() {
|
|
|
39
39
|
}
|
|
40
40
|
var pageApiRouteOf = function (path) {
|
|
41
41
|
var _a, _b, _c;
|
|
42
|
-
return (_c = (_b = (_a = path
|
|
42
|
+
return (_c = (_b = (_a = decodeURI(path)
|
|
43
43
|
.match(/pages(\/api\/.+)\.(j|t)s/)) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.split('/[')[0]) === null || _c === void 0 ? void 0 : _c.replace(/\/index$/, '');
|
|
44
44
|
};
|
|
45
45
|
exports.pageApiRouteOf = pageApiRouteOf;
|
|
46
|
-
var
|
|
47
|
-
exports.
|
|
46
|
+
var createKoaRouter = function (moduleURI, option) { return new router_1.default(tslib_1.__assign(tslib_1.__assign({}, option), { prefix: (0, exports.pageApiRouteOf)(moduleURI) })); };
|
|
47
|
+
exports.createKoaRouter = createKoaRouter;
|
|
48
48
|
function withKoaRouter() {
|
|
49
49
|
var _a, _b;
|
|
50
50
|
var parameters = [];
|
package/dist/API.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"API.js","sourceRoot":"","sources":["../source/API.ts"],"names":[],"mappings":";;;AAaA,0BAcC;AAsBD,sCAiBC;;AAlED,uEAAyC;AACzC,+DAAwE;AACxE,oDAAsC;AAWtC,SAAgB,OAAO;;IAAO,oBAAoB;SAApB,UAAoB,EAApB,qBAAoB,EAApB,IAAoB;QAApB,+BAAoB;;IAC9C,IAAI,MAA6B,CAAC;IAClC,IAAI,WAAW,GAAuB,EAAE,CAAC;IAEzC,IAAI,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,GAAG,SAAS,CAAC;QACnB,WAAW,GAAG,UAAU,CAAC;IAC7B,CAAC;;QAAM,KAAA,eAA2B,UAAU,CAAA,EAApC,MAAM,QAAA,EAAK,WAAW,cAAA,CAAe;IAE7C,IAAM,GAAG,GAAG,IAAI,aAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;;QAE9C,KAAyB,IAAA,gBAAA,iBAAA,WAAW,CAAA,wCAAA;YAA/B,IAAM,UAAU,wBAAA;YAAiB,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;SAAA;;;;;;;;;IAE1D,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAEM,IAAM,cAAc,GAAG,UAAC,IAAY;;IACvC,OAAA,MAAA,MAAA,MAAA,IAAI;
|
|
1
|
+
{"version":3,"file":"API.js","sourceRoot":"","sources":["../source/API.ts"],"names":[],"mappings":";;;AAaA,0BAcC;AAsBD,sCAiBC;;AAlED,uEAAyC;AACzC,+DAAwE;AACxE,oDAAsC;AAWtC,SAAgB,OAAO;;IAAO,oBAAoB;SAApB,UAAoB,EAApB,qBAAoB,EAApB,IAAoB;QAApB,+BAAoB;;IAC9C,IAAI,MAA6B,CAAC;IAClC,IAAI,WAAW,GAAuB,EAAE,CAAC;IAEzC,IAAI,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,GAAG,SAAS,CAAC;QACnB,WAAW,GAAG,UAAU,CAAC;IAC7B,CAAC;;QAAM,KAAA,eAA2B,UAAU,CAAA,EAApC,MAAM,QAAA,EAAK,WAAW,cAAA,CAAe;IAE7C,IAAM,GAAG,GAAG,IAAI,aAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;;QAE9C,KAAyB,IAAA,gBAAA,iBAAA,WAAW,CAAA,wCAAA;YAA/B,IAAM,UAAU,wBAAA;YAAiB,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;SAAA;;;;;;;;;IAE1D,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAEM,IAAM,cAAc,GAAG,UAAC,IAAY;;IACvC,OAAA,MAAA,MAAA,MAAA,SAAS,CAAC,IAAI,CAAC;SACV,KAAK,CAAC,0BAA0B,CAAC,0CAAG,CAAC,CAAC,0CACrC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,0CACd,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;CAAA,CAAC;AAJrB,QAAA,cAAc,kBAIO;AAE3B,IAAM,eAAe,GAAG,UAC3B,SAAiB,EACjB,MAAsB,IACrB,OAAA,IAAI,gBAAM,uCAAY,MAAM,KAAE,MAAM,EAAE,IAAA,sBAAc,EAAC,SAAS,CAAC,IAAG,EAAlE,CAAkE,CAAC;AAH3D,QAAA,eAAe,mBAG4C;AAWxE,SAAgB,aAAa;;IACzB,oBAAoB;SAApB,UAAoB,EAApB,qBAAoB,EAApB,IAAoB;QAApB,+BAAoB;;IAEpB,IAAI,MAA6B,CAAC;IAClC,IAAI,MAAoB,CAAC;IACzB,IAAI,WAAW,GAAuB,EAAE,CAAC;IAEzC,IAAI,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU;QACnC,KAAA,eAA2B,UAAU,CAAA,EAApC,MAAM,QAAA,EAAK,WAAW,cAAA,CAAe;;QACrC,KAAA,eAAmC,UAAU,CAAA,EAA5C,MAAM,QAAA,EAAE,MAAM,QAAA,EAAK,WAAW,cAAA,CAAe;IAEnD,OAAO,OAAO,sCACV,MAAM;QACN,MAAM,CAAC,MAAM,EAAE;QACf,MAAM,CAAC,cAAc,EAAE,kBACpB,WAAW,WAChB;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-ssr-middleware",
|
|
3
|
-
"version": "0.10.0
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "LGPL-3.0-or-later",
|
|
5
5
|
"author": "shiy2008@gmail.com",
|
|
6
|
-
"description": "Koa-like middlewares for Next.js Server Side Rendering",
|
|
6
|
+
"description": "Koa-like middlewares for Next.js Back-end API & Server Side Rendering",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"koa",
|
|
9
9
|
"middleware",
|
package/source/API.ts
CHANGED
|
@@ -28,12 +28,12 @@ export function withKoa<S, C>(...parameters: any[]) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const pageApiRouteOf = (path: string) =>
|
|
31
|
-
path
|
|
31
|
+
decodeURI(path)
|
|
32
32
|
.match(/pages(\/api\/.+)\.(j|t)s/)?.[1]
|
|
33
33
|
?.split('/[')[0]
|
|
34
34
|
?.replace(/\/index$/, '');
|
|
35
35
|
|
|
36
|
-
export const
|
|
36
|
+
export const createKoaRouter = <S, C extends RouterParamContext<S>>(
|
|
37
37
|
moduleURI: string,
|
|
38
38
|
option?: RouterOptions
|
|
39
39
|
) => new Router<S, C>({ ...option, prefix: pageApiRouteOf(moduleURI) });
|