共计 2426 个字符,预计需要花费 7 分钟才能阅读完成。
敌人的网站有个需要:要从 A 域名迁徙到 B 域名。所有内容不变,只是更改域名。这个需要不简单,实践上改下配置而后 301 即可。但这个网站是纯动态网站,用户数据都存在 localStorage
里,所以他心愿可能主动帮用户把数据也迁徙到新域名。
咱们晓得,localStorage
是依照域名存储的,B 网站无法访问 A 网站的 localStorage
。所以咱们就须要一些非凡的伎俩来实现需求。通过一些调研,咱们筹备应用 postMessage()
来实现这个需要。
大体的计划如下:
首先,减少 migrate.html 页面。 这个页面不须要其它具体性能,只有侦听 message
事件,并且把 localStorage
传出即可。
<!-- migrate.html -->
<script>
window.addEventListener('message', function (message) {const { origin, source} = message;
// 验证起源,只承受咱们本人的域名发来的申请
if (origin !== 'https://wordleunlimited.me') return;
const local = localStorage.getItem('wordle');
// `source` 是浏览器主动填充的,即调用 `postMessage` 的起源。作为跨域 iframe 里的页面,拿不到外层 window,只能通过这种形式往回传递数据。source.postMessage({
type: 'migrate',
stored: local,
}, 'https://wordleunlimited.me');
});
</script>
而后,在利用里减少 <iframe>
,因为我用 Vue3,所以这里也用 Vue 组件的形式解决。
<!-- App.vue -->
<template lang="pug">
migrate-domain(v-if="needMigrate")
</template>
<script setup>
// 我会把迁徙的状态长久化,免得重复提醒打搅用户
const needMigrate = location.hostname === 'wordleunlimited.me' && !store.state.migrated19;
</script>
<!-- migrate-domain.vue -->
<script lang="ts" setup>
import {ref} from "vue";
// 我的项目启动得早,还在用 vuex
import {useStore} from "vuex";
import {key} from "@/store";
const store = useStore(key);
const migrateIFrame = ref<HTMLIFrameElement>();
// migrate.html 接到申请后,验证起源,而后会把 localStorage 的数据发回。咱们用这个函数接管。window.addEventListener('message', message => {const { origin, data} = message;
// 同样验证起源
if (origin !== 'https://mywordle.org' && origin !== 'https://mywordgame.com') return;
const {type, stored} = data;
if (type !== 'migrate') return;
if (stored) {
// 迁徙数据时,需退出非凡标记,用来标记“已迁徙”状态
localStorage.setItem('wordle', stored.replace(/}$/, ',"migrated19": true}'));
// 很奇怪,间接 reload 可能会迁徙失败,所以这里略微等一下
setTimeout(() => {if (confirm('Data migrated, reload the page?')) {location.reload();
}
}, 100);
}
});
// iframe 加载完即执行这段 JS,向 iframe 内的页面传递迁徙申请
function onLoad() {
const contentWindow = migrateIFrame.value?.contentWindow;
if (contentWindow) {contentWindow.postMessage('migrate', 'https://mywordle.org');
} else {console.warn('no content window');
}
}
</script>
<template lang="pug">
iframe(
ref="migrateIFrame"
src="https://mywordle.org/migrate.html"
frameborder="no"
width="0"
height="0"
@load="onLoad"
)
</template>
<style scoped>
iframe {
width: 0;
height: 0;
}
</style>
至此,性能实现。
如此一来,老用户关上网站后,会被跳转到新域名。而后利用 JS 会查看 localStorage
里存储的数据,如果没有迁徙过,就会应用 <iframe>
加载老域名下的 migrate.html
。期待指标页面加载实现之后,调用 postMessage()
发送迁徙申请。接下里,migrate.html
接到申请后,返回之前存储的数据。新域名贮存之后,提醒刷新。
次要的坑在于 <iframe>
里的页面无奈间接跟跨域页面通信,所以须要父页面先找到子页面,发动申请;而后子页面再把数据回传给父页面。其它方面应该就是个别的 API 调用,以及体验性问题。
心愿本文对大家有帮忙。如果各位对 postMessage() 或者其它相干技术有问题的话,欢送留言交换。
本文参加了 SegmentFault 思否写作挑战赛,欢送正在浏览的你也退出。