-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: new ssr #12489
feat: new ssr #12489
Changes from 35 commits
a1e5cee
9d2e626
ae9dc25
c9530cf
67f7e90
a7dd292
7ccf522
09ec592
e8735e4
e0972d3
a82a386
fa7d9fa
eb9918e
b757a04
ec2be86
2076690
0b8b4f4
1f84be6
db15285
96e855c
2409a4c
cc2eb49
1987617
0b3c81d
4c6d6a6
ca9fabb
19b732f
ac64d1c
2d844a4
7d0f2f8
4bb77aa
34d6d45
a113db8
da9315b
63e13e9
9f483d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,27 @@ | ||
export default { | ||
svgr: {}, | ||
hash: true, | ||
mfsu: false, | ||
routePrefetch: {}, | ||
manifest: {}, | ||
clientLoader: {}, | ||
mako: { | ||
plugins: [ | ||
{ | ||
load: () => {}, | ||
}, | ||
], | ||
}, | ||
ssr: { | ||
serverBuildPath: './umi.server.js', | ||
builder: 'mako', | ||
}, | ||
exportStatic: {}, | ||
styles: [`body { color: red; }`], | ||
|
||
metas: [ | ||
{ | ||
name: 'test', | ||
content: 'content', | ||
}, | ||
], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"optimization": { | ||
"skipModules": true, | ||
"concatenateModules": false | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'; | ||
import { useState } from 'react'; | ||
import { Outlet, useServerInsertedHTML } from 'umi'; | ||
|
||
export default function Layout() { | ||
const [cssCache] = useState(() => createCache()); | ||
|
||
useServerInsertedHTML(() => { | ||
const style = extractStyle(cssCache, { plain: true }); | ||
return ( | ||
<style | ||
id="antd-cssinjs" | ||
dangerouslySetInnerHTML={{ __html: style }} | ||
></style> | ||
); | ||
}); | ||
|
||
return ( | ||
<StyleProvider cache={cssCache}> | ||
<Outlet /> | ||
</StyleProvider> | ||
); | ||
} | ||
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,8 +1,12 @@ | ||||||||||||
import { Input } from 'antd'; | ||||||||||||
import { useId } from 'react'; | ||||||||||||
import { | ||||||||||||
ClientLoader, | ||||||||||||
Link, | ||||||||||||
MetadataLoader, | ||||||||||||
ServerLoader, | ||||||||||||
useClientLoaderData, | ||||||||||||
useLoaderData, | ||||||||||||
useServerInsertedHTML, | ||||||||||||
useServerLoaderData, | ||||||||||||
} from 'umi'; | ||||||||||||
|
@@ -20,18 +24,29 @@ import umiLogo from './umi.png'; | |||||||||||
export default function HomePage() { | ||||||||||||
const clientLoaderData = useClientLoaderData(); | ||||||||||||
const serverLoaderData = useServerLoaderData<typeof serverLoader>(); | ||||||||||||
const loaderData = useLoaderData<typeof serverLoader>(); | ||||||||||||
|
||||||||||||
useServerInsertedHTML(() => { | ||||||||||||
return <div>inserted html</div>; | ||||||||||||
return ( | ||||||||||||
<style | ||||||||||||
dangerouslySetInnerHTML={{ | ||||||||||||
__html: `.server_inserted_style { color: #1677ff }`, | ||||||||||||
}} | ||||||||||||
Comment on lines
+32
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 避免使用 dangerouslySetInnerHTML 直接在组件内部使用 ToolsBiome
|
||||||||||||
></style> | ||||||||||||
); | ||||||||||||
}); | ||||||||||||
|
||||||||||||
const id = useId(); | ||||||||||||
|
||||||||||||
return ( | ||||||||||||
<div> | ||||||||||||
<h1 className="title">Hello~</h1> | ||||||||||||
<p className="server_inserted_style">id: {id}</p> | ||||||||||||
<p className={styles.blue}>This is index.tsx</p> | ||||||||||||
<p className={cssStyle.title}>I should be pink</p> | ||||||||||||
<p className={cssStyle.blue}>I should be cyan</p> | ||||||||||||
<Button /> | ||||||||||||
<Input placeholder="这个样式不应该闪烁" /> | ||||||||||||
<img src={bigImage} alt="" /> | ||||||||||||
<img src={umiLogo} alt="umi" /> | ||||||||||||
<Link to="/users/user">/users/user</Link> | ||||||||||||
|
@@ -43,19 +58,21 @@ export default function HomePage() { | |||||||||||
</div> | ||||||||||||
<p>client loader data: {JSON.stringify(clientLoaderData)}</p> | ||||||||||||
<p>server loader data: {JSON.stringify(serverLoaderData)}</p> | ||||||||||||
<p>merge loader data: {JSON.stringify(loaderData)}</p> | ||||||||||||
</div> | ||||||||||||
); | ||||||||||||
} | ||||||||||||
|
||||||||||||
export async function clientLoader() { | ||||||||||||
export const clientLoader: ClientLoader = async ({}) => { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 修正空对象模式 在 - export const clientLoader: ClientLoader = async ({}) => {
+ export const clientLoader: ClientLoader = async () => {
await new Promise((resolve) => setTimeout(resolve, Math.random() * 1000));
return { clientMessage: 'data from client loader of index.tsx' };
}; Committable suggestion
Suggested change
|
||||||||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 1000)); | ||||||||||||
return { message: 'data from client loader of index.tsx' }; | ||||||||||||
} | ||||||||||||
return { clientMessage: 'data from client loader of index.tsx' }; | ||||||||||||
}; | ||||||||||||
clientLoader.hydrate = true; | ||||||||||||
|
||||||||||||
export const serverLoader: ServerLoader = async (req) => { | ||||||||||||
const url = req!.request.url; | ||||||||||||
const url = req?.request?.url; | ||||||||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 1000)); | ||||||||||||
return { message: `data from server loader of index.tsx, url: ${url}` }; | ||||||||||||
return { serverMessage: `data from server loader of index.tsx, url: ${url}` }; | ||||||||||||
}; | ||||||||||||
|
||||||||||||
// SEO-设置页面的TDK | ||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,7 @@ export function resolveDefine(opts: IOpts) { | |
|
||
return { | ||
'process.env': env, | ||
'process.env.SSR_MANIFEST': 'process.env.SSR_MANIFEST', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 忘了当时的情况了,这个能实现到 ssr plugin 里吗 |
||
...define, | ||
}; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -210,4 +210,18 @@ export { MicroAppWithMemoHistory } from './MicroAppWithMemoHistory'; | |
`, | ||
}); | ||
}); | ||
|
||
api.chainWebpack((config, { ssr }) => { | ||
// 在 ssr 的场景下,把 qiankun external 到一个任意模块 | ||
// 这样就不会把 qiankun 的依赖构建进产物中 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里感觉还是得有个本质解,现在的方式只是绕过,注释里至少要包含两个问题:
以及本质解应该是满足某个前提 ssr 就不受影响,也不用 externals 来绕,可以留成 TODO |
||
if (ssr) { | ||
const originalExternals = config.get('externals'); | ||
config.externals({ | ||
...originalExternals, | ||
qiankun: 'fs', | ||
}); | ||
} | ||
|
||
return config; | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
避免使用
dangerouslySetInnerHTML
。代码中使用了
dangerouslySetInnerHTML
来设置内联样式,这可能会导致跨站脚本攻击(XSS)。建议寻找其他方法来设置样式,以提高应用的安全性。Committable suggestion
Tools
Biome