敌人的网站有个需要:要从 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";// 我的项目启动得早,还在用 vueximport {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 思否写作挑战赛,欢送正在浏览的你也退出。