问题描述
我想实现的目标
我想使用Sapper.js构建一个可脱机工作但还具有服务器端渲染功能的Web应用程序。为此,我需要两种数据存储实现:一种在浏览器中工作,另一种在服务器上工作。
我怎么想这会起作用
我认为在client.js
和server.js
中,我可能可以导入商店的相应实现,然后将其作为道具传递给我的页面组件,类似于:
// server.js
// [some more imports here]
import DataStore from "./my/backend/datastore"
polka()
.use(
sapper.middleware({
pageProps: {DataStore}
})
)
.listen(PORT,err => {/* other stuff */});
// client.js
import * as sapper from '@sapper/app';
import DataStore from "./my/frontend/datastore"
sapper.start({
target: document.querySelector('#sapper'),pageProps: {DataStore}
})
<!-- page.svelte -->
<script>
export let DataStore;
let item;
if (!item) {
DataStore.getItem().then(i => item = i);
}
</script>
<p>{item}</p>
但是,似乎没有办法将道具从两个入口点传递到页面中。
尽管使用全局变量而不是props,但https://stackoverflow.com/a/49085459/9236140上问题#3的答案也允许做同样的事情。但是,由于我还没有设法从组件内部访问window
和global
,所以它似乎不再起作用。
我(很高兴)如何工作
// routes/server/route/exposing/get_item.js
import DataStore from "./my/backend/datastore"
export async function get(req,res,next) {
res.end(await DataStore.getItem());
}
<!-- page.svelte -->
<script context="module">
export async function preload(page,session) {
const response = await this.fetch(`/server/route/exposing/get_item`);
return {
item: await response.text()
}
}
</script>
<script>
import {onMount} from 'svelte';
export let item;
let DataStore;
onMount(async () => {
// Dynamically import DataStore so I can use it later,e.g. in on click handlers.
const module = await import("./my/frontend/datastore");
DataStore = module.default;
}
</script>
<p>{item}</p>
为什么该解决方案不能令人满意
我的问题
- 是否有一种方法可以避免这些问题中的一个或两个?
(也许参与开发的人可以回答其他两个问题:) - 不让道具从两个入口点文件传递到页面的背后是什么原因?
- 里奇·哈里斯(Rich Harris)最近宣布即将取代Sapper换人吗?
非常感谢您的阅读。所有指针表示赞赏。 :)
//编辑:
摆弄一些东西之后,我发现了一种方法,可以在preload
函数中区分服务器和客户端,并至少在前端上导航时防止AJAX调用,但是它感觉很hacky,并增加了一些样板:
// server.js
// [imports here]
polka()
.use(
sapper.middleware({
session: (req,res) => ({environment: "server"})
})
)
.listen(PORT,err => {/* other stuff */});
<!-- page.svelte -->
<script context="module">
export async function preload(page,session) {
if (session.environment === "server") {
session.environment = "client"
const response = await this.fetch(`/server/route/exposing/get_item`);
return {
item: await response.text()
}
} else {
const module = await import("./my/frontend/datastore");
return {
item: await module.default.getItem()
};
}
}
</script>
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)