Merge pull request #1134 from nonameShijian/PR-Branch

将serviceWorker改为使用esm,加载时判断是否可以使用ts,sfc改为使用esm
This commit is contained in:
Spmario233 2024-03-27 17:32:29 +08:00 committed by GitHub
commit f1c75042df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 48297 additions and 48274 deletions

4
game/canUse.ts Normal file
View File

@ -0,0 +1,4 @@
// apk每次安装后第一次启动加载Service Worker会失败
// 所以每次导入这个ts判断是否会成功失败的话重启一次
export const text: string = 'ts文件导入成功';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@ import { userAgent } from "../noname/util/index.js";
const coreAndVersion = get.coreInfo();
const core = coreAndVersion[0], version = coreAndVersion[1];
//@todo: 77 -> 80
if (core === 'chrome' && !isNaN(version) && version < 77) {
const tip = '检测到您的浏览器内核版本小于77请及时升级浏览器或手机webview内核';
console.warn(tip);

View File

@ -166,6 +166,7 @@ new Promise(resolve => {
// 使用ts compiler对ts文件进行编译
const result = ts.transpile(code, {
module: ts.ModuleKind.CommonJS,
//@todo: ES2019 -> ES2020
target: ts.ScriptTarget.ES2019,
inlineSourceMap: true,
resolveJsonModule: true,
@ -203,15 +204,23 @@ new Promise(resolve => {
});
try {
const registration_1 = await navigator.serviceWorker.register(`${scope}service-worker.js`, {
type: 'module',
updateViaCache: "all",
scope,
});
// 初次加载worker需要重新启动一次
if (!findServiceWorker) location.reload();
// 接收消息,暂时没用到
navigator.serviceWorker.addEventListener('message', e => {
console.log(e);
});
registration_1.update().catch(console.error);
registration_1.update().catch(e => console.error('worker update失败', e));
if (!sessionStorage.getItem('canUseTs')) {
await import('./canUse.ts').then(({ text }) => console.log(text)).catch(() => {
sessionStorage.setItem('canUseTs', '1');
location.reload();
});
}
} catch (e_1) {
console.log('serviceWorker加载失败: ', e_1);
}

View File

@ -172280,3 +172280,6 @@ ${e.message}`;
if (typeof module !== "undefined" && module.exports) {
module.exports = ts;
}
if (typeof globalThis !== "undefined") {
globalThis.ts = ts;
}

View File

@ -1,39 +1,39 @@
/**
* @type { ServiceWorkerGlobalScope } 提供ServiceWorker的代码提示
*/
// @ts-ignore
var self = globalThis;
// 以副作用导入typescript以保证require也可以同步使用
import './game/typescript.js';
/**
* @type { import('typescript') }
*/
var ts;
importScripts('./game/typescript.js');
/**
* @type { import('./game/compiler-sfc.browser.js') }
*/
var sfc;
importScripts('./game/compiler-sfc.browser.js');
// @ts-ignore
var ts = globalThis.ts;
// sfc以正常的esmodule使用
import * as sfc from './game/compiler-sfc.esm-browser.js';
if (typeof ts != 'undefined') {
console.log(`ts loaded`);
console.log(`ts loaded`, ts.version);
} else {
console.log(`ts undefined`);
console.error(`ts undefined`);
}
// @ts-ignore
if (typeof sfc != 'undefined') {
console.log(`sfc loaded`);
console.log(`sfc loaded`, sfc.version);
sfc.registerTS(() => ts);
} else {
console.log(`sfc undefined`);
console.error(`sfc undefined`);
}
console.log('serviceWorker version 2.3');
self.addEventListener("install", (event) => {
// The promise that skipWaiting() returns can be safely ignored.
// @ts-ignore
self.skipWaiting();
});
self.addEventListener("activate", (event) => {
// 当一个 service worker 被初始注册时,页面在下次加载之前不会使用它。 claim() 方法会立即控制这些页面
// @ts-ignore
event.waitUntil(clients.claim());
event.waitUntil(self.clients.claim());
});
self.addEventListener('message', event => {
@ -46,7 +46,6 @@ self.addEventListener('message', event => {
const vueFileMap = new Map();
self.addEventListener('fetch', event => {
// @ts-ignore
const request = event.request;
if (typeof request.url != 'string') return console.log(request);
if (vueFileMap.has(request.url)) {
@ -63,10 +62,9 @@ self.addEventListener('fetch', event => {
if (!['.ts', '.json', '.vue', 'css'].some(ext => request.url.endsWith(ext))) return;
if (request.url.endsWith('.d.ts')) return;
if (request.url.endsWith('.json') || request.url.endsWith('css')) {
// @ts-ignore
if (!event.request.headers.get('origin')) return;
}
// 请求ts文件
// 请求文件
const res = fetch(request.url, {
method: request.method,
mode: "no-cors",
@ -74,18 +72,19 @@ self.addEventListener('fetch', event => {
"Content-Type": "text/plain"
}),
});
// @ts-ignore
// 修改请求结果
event.respondWith(
res.then(res => {
if (res.status != 200) return res;
console.log('正在编译', request.url);
return res.text().then(text => {
let js;
let js = '';
if (request.url.endsWith('.json')) {
js = `export default ${ text }`;
} else if (request.url.endsWith('.ts')) {
js = ts.transpile(text, {
module: ts.ModuleKind.ES2015,
//@todo: ES2019 -> ES2020
target: ts.ScriptTarget.ES2019,
inlineSourceMap: true,
resolveJsonModule: true,
@ -97,7 +96,7 @@ self.addEventListener('fetch', event => {
// 后续处理sourceMap合并
const { descriptor } = sfc.parse(text, { filename: request.url, sourceMap: true });
// console.log({ descriptor });
const hasScoped = descriptor.styles.some((s) => s.scoped);
const hasScoped = descriptor.styles.some(s => s.scoped);
// 编译 script因为可能有 script setup还要进行 css 变量注入
const script = sfc.compileScript(descriptor, {
id: scopeId,
@ -111,27 +110,38 @@ self.addEventListener('fetch', event => {
});
// 用于存放代码,最后 join('\n') 合并成一份完整代码
const codeList = [];
// 保存url并且拼接参数
const url = new URL(request.url);
const scriptSearchParams = new URLSearchParams(url.search.slice(1));
scriptSearchParams.append('type', 'script');
const templateSearchParams = new URLSearchParams(url.search.slice(1));
templateSearchParams.append('type', 'template');
vueFileMap.set(
request.url + '?type=script',
url.origin + url.pathname + '?' + scriptSearchParams.toString(),
// 重写 default
sfc.rewriteDefault(script.attrs && script.attrs.lang == 'ts' ? ts.transpile(script.content, {
module: ts.ModuleKind.ES2015,
//@todo: ES2019 -> ES2020
target: ts.ScriptTarget.ES2019,
inlineSourceMap: true,
resolveJsonModule: true,
esModuleInterop: true,
}, request.url + '?type=script') : script.content, "__sfc_main__")
}, url.origin + url.pathname + '?' + scriptSearchParams.toString()) : script.content, "__sfc_main__")
.replace(`const __sfc_main__`, `export const __sfc_main__`)
// import vue重新指向
.replaceAll(`from "vue"`, `from "/game/vue.esm-browser.js"`)
.replaceAll(`from 'vue'`, `from '/game/vue.esm-browser.js'`)
);
codeList.push(`import { __sfc_main__ } from '${ request.url }?type=script'`);
codeList.push(`import { __sfc_main__ } from '${ url.origin + url.pathname + '?' + scriptSearchParams.toString() }'`);
codeList.push(`__sfc_main__.__scopeId = '${ scopeId }'`);
// 编译模板,转换成 render 函数
const template = sfc.compileTemplate({
source: descriptor.template.content,
source: descriptor.template ? descriptor.template.content : '',
filename: request.url, // 用于错误提示
id: scopeId,
scoped: hasScoped,
@ -140,13 +150,15 @@ self.addEventListener('fetch', event => {
}
});
vueFileMap.set(request.url + '?type=template', template.code
vueFileMap.set(
url.origin + url.pathname + '?' + templateSearchParams.toString(),
template.code
// .replace(`function render(_ctx, _cache) {`, str => str + 'console.log(_ctx);')
.replaceAll(`from "vue"`, `from "/game/vue.esm-browser.js"`)
.replaceAll(`from 'vue'`, `from '/game/vue.esm-browser.js'`)
);
codeList.push(`import { render } from '${ request.url }?type=template'`);
codeList.push(`import { render } from '${ url.origin + url.pathname + '?' + templateSearchParams.toString() }'`);
codeList.push(`__sfc_main__.render = render;`);
codeList.push(`export default __sfc_main__;`);
// 一个 Vue 文件,可能有多个 style 标签
@ -180,11 +192,12 @@ self.addEventListener('fetch', event => {
"Content-Type": "text/javascript"
}),
});
console.log(request.url, '编译成功');
return rep;
})
})
.catch(e => {
console.log(e);
console.error(request.url, '编译失败: ', e);
throw e;
})
);