vaderjs 1.4.4 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +100 -61
- package/main.js +97 -24
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
1
2
|
let isClassComponent = function(element) {
|
|
2
3
|
return element.toString().startsWith("class");
|
|
3
4
|
};
|
|
4
5
|
|
|
6
|
+
const memoizes = new Map();
|
|
7
|
+
//@ts-ignore
|
|
8
|
+
|
|
5
9
|
declare global {
|
|
6
10
|
interface Window {
|
|
7
11
|
onbeforeunload: any;
|
|
8
12
|
localStorage: any;
|
|
9
13
|
sessionStorage: any;
|
|
14
|
+
state: any;
|
|
10
15
|
}
|
|
11
16
|
const genKey: any;
|
|
12
17
|
let isServer: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* @description - The params object is used to store the query parameters of the current URL
|
|
20
|
+
* @example
|
|
21
|
+
* // URL: https://example.com?name=John
|
|
22
|
+
* console.log(params.name) // John
|
|
23
|
+
* @example
|
|
24
|
+
* // URL: https://example.com/:name/:age
|
|
25
|
+
* // GO: https://example.com/John/20
|
|
26
|
+
* console.log(params.name) // John
|
|
27
|
+
* console.log(params.age) // 20
|
|
28
|
+
*/
|
|
29
|
+
let params: { [key: string]: string };
|
|
13
30
|
}
|
|
14
31
|
//@ts-ignore
|
|
15
32
|
globalThis.isServer = typeof window === "undefined";
|
|
33
|
+
//@ts-ignore
|
|
34
|
+
globalThis.params = {
|
|
35
|
+
[Symbol.iterator]: function* () {
|
|
36
|
+
for (const key in this) {
|
|
37
|
+
yield [key, this[key]];
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
16
41
|
|
|
17
42
|
|
|
18
43
|
/**
|
|
@@ -41,6 +66,17 @@ export const useEffect = (callback:any, dependencies: any[]) => {
|
|
|
41
66
|
}
|
|
42
67
|
}
|
|
43
68
|
|
|
69
|
+
function memoizeComponent(Component: any) {
|
|
70
|
+
let key = Component.toString();
|
|
71
|
+
if (memoizes.has(key)) {
|
|
72
|
+
return memoizes.get(key);
|
|
73
|
+
}
|
|
74
|
+
let instance = new Component();
|
|
75
|
+
memoizes.set(key, instance);
|
|
76
|
+
return instance;
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
44
80
|
/**
|
|
45
81
|
* @description - Create a new element
|
|
46
82
|
* @param element
|
|
@@ -63,20 +99,16 @@ export const e = (element: any, props: any, ...children: any[]) => {
|
|
|
63
99
|
* @param initialState
|
|
64
100
|
* @returns {state, (newState: any, Element: string) => void, key}
|
|
65
101
|
*/
|
|
66
|
-
export const useState = (
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
instance.setState({ [key]: newState }, Element);
|
|
76
|
-
}, key];
|
|
102
|
+
export const useState = <T>(initialState: T) => {
|
|
103
|
+
const setState = (newState: T, Element: string) => {
|
|
104
|
+
initialState = newState;
|
|
105
|
+
}
|
|
106
|
+
return [initialState, setState];
|
|
107
|
+
}
|
|
108
|
+
//@ts-ignore
|
|
109
|
+
if(!isServer){
|
|
110
|
+
window.state = {};
|
|
77
111
|
}
|
|
78
|
-
//@ts-ignore
|
|
79
|
-
let state = {};
|
|
80
112
|
export class Component {
|
|
81
113
|
props: any;
|
|
82
114
|
state: any;
|
|
@@ -88,21 +120,24 @@ export class Component {
|
|
|
88
120
|
constructor() {
|
|
89
121
|
this.key = Math.random().toString(36).substring(7);
|
|
90
122
|
this.props = {};
|
|
91
|
-
//@ts-ignore
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
//@ts-ignore
|
|
124
|
+
if(!isServer){
|
|
125
|
+
window.state[this.key] = {};
|
|
126
|
+
this.state = window.state[this.key];
|
|
127
|
+
}else{
|
|
128
|
+
this.state = {};
|
|
129
|
+
}
|
|
94
130
|
this.effect = [];
|
|
95
131
|
this.Mounted = false;
|
|
96
132
|
this.element = null;
|
|
97
133
|
}
|
|
98
134
|
setState(newState: any, Element: string) {
|
|
99
|
-
state[this.key] = { ...this.state, ...newState };
|
|
100
|
-
console.log(state[this.key]);
|
|
135
|
+
globalThis.window.state[this.key] = { ...this.state, ...newState };
|
|
101
136
|
this.forceUpdate(Element);
|
|
102
137
|
}
|
|
103
138
|
|
|
104
139
|
useEffect(callback: any, dependencies: any[]) {
|
|
105
|
-
if (dependencies.length === 0 && this.Mounted && this.effect.length === 0) {
|
|
140
|
+
if (dependencies.length === 0 && this.Mounted && this.effect.length === 0) {
|
|
106
141
|
callback();
|
|
107
142
|
this.effect.push(callback);
|
|
108
143
|
}else{
|
|
@@ -114,34 +149,26 @@ export class Component {
|
|
|
114
149
|
}
|
|
115
150
|
}
|
|
116
151
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.state[key] = initialState;
|
|
121
|
-
}
|
|
152
|
+
useState <T> (key: string, defaultValue: T) {
|
|
153
|
+
let value = sessionStorage.getItem("state_" + key) || defaultValue;
|
|
154
|
+
typeof value === "string" ? value = JSON.parse(value) : value;
|
|
122
155
|
|
|
123
|
-
window.onbeforeunload = ()
|
|
124
|
-
sessionStorage.
|
|
156
|
+
window.onbeforeunload = function() {
|
|
157
|
+
sessionStorage.removeItem("state_" + key);
|
|
158
|
+
}
|
|
159
|
+
const setValue = (newValue: T ,element: string) => {
|
|
160
|
+
value = newValue;
|
|
161
|
+
sessionStorage.setItem("state_" + key, JSON.stringify(value));
|
|
162
|
+
this.state[key] = value;
|
|
163
|
+
this.forceUpdate(element)
|
|
125
164
|
}
|
|
126
|
-
|
|
127
|
-
*
|
|
128
|
-
* @param {*} newState
|
|
129
|
-
* @param {*} Element - The element affected by the state change
|
|
130
|
-
*/
|
|
131
|
-
const setState = (newState, Element) => {
|
|
132
|
-
this.prevState = { ...this.state };
|
|
133
|
-
this.state[key] = newState;
|
|
134
|
-
state[this.key] = { ...this.state };
|
|
135
|
-
this.forceUpdate(Element);
|
|
136
|
-
};
|
|
137
|
-
const returnKey = key;
|
|
138
|
-
return [this.state[key], setState, returnKey];
|
|
165
|
+
return [value, setValue];
|
|
139
166
|
}
|
|
167
|
+
|
|
168
|
+
|
|
140
169
|
|
|
141
170
|
useFetch(url, options) {
|
|
142
|
-
const { key } = options;
|
|
143
|
-
|
|
144
|
-
console.log(key);
|
|
171
|
+
const { key } = options;
|
|
145
172
|
if (!key) {
|
|
146
173
|
throw new Error(`You must supply a key for the affected element in the options object`);
|
|
147
174
|
}
|
|
@@ -151,23 +178,23 @@ export class Component {
|
|
|
151
178
|
const dataKey = "_data" + url;
|
|
152
179
|
|
|
153
180
|
// Initialize loading to false if loadingKey doesn't exist in state
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
181
|
+
let [loading, setLoading] = this.useState(loadingKey, false);
|
|
182
|
+
let [error, setError] = this.useState(errorKey, null);
|
|
183
|
+
let [data, setData] = this.useState(dataKey, null);
|
|
157
184
|
|
|
158
185
|
if (loading && !error && !data) {
|
|
159
|
-
state[this.key][loadingKey] = true;
|
|
186
|
+
this.state[this.key][loadingKey] = true;
|
|
160
187
|
|
|
161
188
|
fetch(url, options)
|
|
162
189
|
.then((res) => res.json())
|
|
163
190
|
.then((data) => {
|
|
164
|
-
|
|
165
|
-
|
|
191
|
+
//@ts-ignore
|
|
192
|
+
setLoading(false, options.key);
|
|
193
|
+
setData(data, options.key);
|
|
166
194
|
this.forceUpdate(key);
|
|
167
195
|
})
|
|
168
196
|
.catch((err) => {
|
|
169
|
-
|
|
170
|
-
state[this.key][loadingKey] = false;
|
|
197
|
+
setError(err, options.key);
|
|
171
198
|
this.forceUpdate(key);
|
|
172
199
|
});
|
|
173
200
|
}
|
|
@@ -179,7 +206,7 @@ export class Component {
|
|
|
179
206
|
forceUpdate(key) {
|
|
180
207
|
//@ts-ignore
|
|
181
208
|
let el = Array.from(document.querySelectorAll("*")).filter((el2: any) =>{ return el2.key === key})[0];
|
|
182
|
-
let newl = this.parseToElement(this.render());
|
|
209
|
+
let newl = this.parseToElement(this.render());
|
|
183
210
|
if(newl.key !== key){
|
|
184
211
|
//@ts-ignore
|
|
185
212
|
newl = Array.from(newl.children).filter((el2) => el2.key === key)[0];
|
|
@@ -239,8 +266,7 @@ export class Component {
|
|
|
239
266
|
continue;
|
|
240
267
|
}
|
|
241
268
|
//@ts-ignore
|
|
242
|
-
if (key.startsWith("on")) {
|
|
243
|
-
console.log(key.substring(2).toLowerCase());
|
|
269
|
+
if (key.startsWith("on")) {
|
|
244
270
|
el.addEventListener(key.substring(2).toLowerCase(), attributes[key]);
|
|
245
271
|
continue;
|
|
246
272
|
}
|
|
@@ -281,8 +307,21 @@ export class Component {
|
|
|
281
307
|
render() {
|
|
282
308
|
return "";
|
|
283
309
|
}
|
|
310
|
+
|
|
311
|
+
|
|
284
312
|
}
|
|
285
313
|
|
|
314
|
+
function memoizeClassComponent(Component: any) {
|
|
315
|
+
let key = Component.toString();
|
|
316
|
+
if (memoizes.has(key)) {
|
|
317
|
+
return memoizes.get(key);
|
|
318
|
+
}
|
|
319
|
+
let instance = new Component();
|
|
320
|
+
memoizes.set(key, instance);
|
|
321
|
+
return instance;
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
|
|
286
325
|
export function render(element: any, container) {
|
|
287
326
|
if (isClassComponent(element)) {
|
|
288
327
|
const instance = new element();
|
|
@@ -292,14 +331,14 @@ export function render(element: any, container) {
|
|
|
292
331
|
container.innerHTML = "";
|
|
293
332
|
container.replaceWith(el);
|
|
294
333
|
} else {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
334
|
+
// memoizeComponent(element);
|
|
335
|
+
let memoizedInstance = memoizeClassComponent(Component);
|
|
336
|
+
memoizedInstance.Mounted = true;
|
|
337
|
+
memoizedInstance.render = element.bind(memoizedInstance);
|
|
338
|
+
let el = memoizedInstance.toElement();
|
|
339
|
+
container.innerHTML = "";
|
|
340
|
+
container.replaceWith(el);
|
|
341
|
+
|
|
303
342
|
}
|
|
304
343
|
}
|
|
305
344
|
|
package/main.js
CHANGED
|
@@ -12,19 +12,19 @@ if (!fs.existsSync(process.cwd() + '/app')) {
|
|
|
12
12
|
if (!fs.existsSync(process.cwd() + '/public')) {
|
|
13
13
|
fs.mkdirSync(process.cwd() + '/public')
|
|
14
14
|
}
|
|
15
|
-
const mode = args.includes('dev') ? 'development' : args.includes('prod') ? 'production' : null
|
|
15
|
+
const mode = args.includes('dev') ? 'development' : args.includes('prod') || args.includes('build') ? 'production' : null
|
|
16
16
|
if(!mode){
|
|
17
17
|
console.log(`
|
|
18
18
|
Usage:
|
|
19
19
|
bun vaderjs dev - Start development server output in dist/
|
|
20
|
-
bun vaderjs prod - Build for production
|
|
20
|
+
bun vaderjs prod - Build for production output in dist/
|
|
21
21
|
`)
|
|
22
22
|
process.exit(1)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
let start = Date.now()
|
|
26
26
|
console.log(`Starting build at ${new Date().toLocaleTimeString()}`)
|
|
27
|
-
let { port, host, } = require(process.cwd() + '/config').default
|
|
27
|
+
let { port, host, host_provider } = require(process.cwd() + '/config').default
|
|
28
28
|
|
|
29
29
|
if (!fs.existsSync(process.cwd() + '/jsconfig.json')) {
|
|
30
30
|
let json = {
|
|
@@ -96,21 +96,36 @@ const handleReplacements = (code, file) => {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
async function generateApp() {
|
|
99
|
+
async function generateApp() {
|
|
100
|
+
// remove files from dist
|
|
101
|
+
if(mode === 'development'){
|
|
102
|
+
fs.rmdirSync(process.cwd() + '/dist', { recursive: true })
|
|
103
|
+
}else{
|
|
104
|
+
fs.mkdirSync(process.cwd() + '/dist', { recursive: true })
|
|
105
|
+
}
|
|
100
106
|
return new Promise(async (resolve, reject) => {
|
|
101
107
|
let routes = new Bun.FileSystemRouter({
|
|
102
108
|
dir: process.cwd() + '/app',
|
|
103
109
|
style: 'nextjs'
|
|
104
110
|
})
|
|
105
|
-
|
|
111
|
+
routes.reload()
|
|
112
|
+
globalThis.routes = routes.routes
|
|
106
113
|
Object.keys(routes.routes).forEach(async (route) => {
|
|
107
114
|
let r = routes.routes[route]
|
|
108
115
|
let code = await Bun.file(r).text()
|
|
109
116
|
code = handleReplacements(code)
|
|
110
117
|
r = r.replace(process.cwd().replace(/\\/g, '/') + '/app', '')
|
|
111
|
-
r = r.replace('.jsx', '.js')
|
|
112
|
-
fs.mkdirSync(path.dirname(process.cwd() + '/dist/' + r), { recursive: true })
|
|
113
|
-
fs.writeFileSync(process.cwd() + '/dist/' + r,
|
|
118
|
+
r = r.replace('.jsx', '.js')
|
|
119
|
+
fs.mkdirSync(path.dirname(process.cwd() + '/dist/' + r), { recursive: true })
|
|
120
|
+
fs.writeFileSync(process.cwd() + '/dist/' + path.dirname(r) + '/' + path.basename(r), `
|
|
121
|
+
let route = window.location.pathname.split('/').filter(v => v !== '')
|
|
122
|
+
let params = {
|
|
123
|
+
${Object.keys(routes.match(route).params || {}).length > 0 ? Object.keys(routes.match(route).params || {}) .map(p => {
|
|
124
|
+
return `${p}: route[${Object.keys(routes.match(route).params).indexOf(p) + 1}]`
|
|
125
|
+
}).join(',') : ""}
|
|
126
|
+
}
|
|
127
|
+
\n${code}
|
|
128
|
+
`)
|
|
114
129
|
fs.mkdirSync(process.cwd() + '/dev', { recursive: true })
|
|
115
130
|
fs.writeFileSync(path.join(process.cwd() + '/dev/bundler.js'), `
|
|
116
131
|
import { Component, e, useState, useEffect, useFetch, useAsyncState } from 'vaderjs'
|
|
@@ -134,14 +149,16 @@ async function generateApp() {
|
|
|
134
149
|
getElementById: (id) => {},
|
|
135
150
|
}
|
|
136
151
|
await Bun.build({
|
|
137
|
-
entrypoints: [process.
|
|
138
|
-
minify:true,
|
|
139
|
-
root:
|
|
140
|
-
outdir: process.cwd() + '/dist',
|
|
141
|
-
|
|
152
|
+
entrypoints: [process.env.ENTRYPOINT],
|
|
153
|
+
minify:true,
|
|
154
|
+
root: process.cwd() + '/dist/',
|
|
155
|
+
outdir: process.cwd() + '/dist/',
|
|
156
|
+
format: 'esm',
|
|
157
|
+
...(process.env.DEV ? { sourcemap: 'inline' } : {})
|
|
158
|
+
})
|
|
142
159
|
let isClass = function(element) {
|
|
143
160
|
return element.toString().startsWith('class');
|
|
144
|
-
};
|
|
161
|
+
};
|
|
145
162
|
const generatePage = async (data = {path: process.env.INPUT, route: process.env.OUT}) => {
|
|
146
163
|
const { path, route } = data
|
|
147
164
|
if(path.includes('root.js')) return
|
|
@@ -168,10 +185,10 @@ async function generateApp() {
|
|
|
168
185
|
let headHtml = ''
|
|
169
186
|
if(head){
|
|
170
187
|
headHtml = document(head())
|
|
171
|
-
}
|
|
188
|
+
}
|
|
172
189
|
Bun.write(process.cwd() + '/dist/' + route + '/index.html', \`<!DOCTYPE html><head>\${headHtml}</head>\${h}
|
|
173
190
|
<script type="module">
|
|
174
|
-
import c from '\${
|
|
191
|
+
import c from '\${process.env.filePath}'
|
|
175
192
|
import {render} from '/src/vader/index.js'
|
|
176
193
|
render(c, document.body.firstChild)
|
|
177
194
|
</script>
|
|
@@ -183,15 +200,19 @@ async function generateApp() {
|
|
|
183
200
|
fs.mkdirSync(process.cwd() + '/dist/src/vader', { recursive: true })
|
|
184
201
|
fs.writeFileSync(process.cwd() + '/dist/src/vader/index.js', await new Bun.Transpiler({
|
|
185
202
|
loader: 'ts',
|
|
186
|
-
}).transformSync(await Bun.file(require.resolve('vaderjs')).text()))
|
|
203
|
+
}).transformSync(await Bun.file(require.resolve('vaderjs')).text()))
|
|
204
|
+
|
|
187
205
|
const spawn = Bun.spawn({
|
|
188
206
|
cmd: ['bun', 'run', './dev/bundler.js'],
|
|
189
207
|
cwd: process.cwd(),
|
|
190
208
|
stdout: 'inherit',
|
|
191
209
|
env: {
|
|
192
|
-
ENTRYPOINT: r,
|
|
210
|
+
ENTRYPOINT: path.join(process.cwd() + '/dist/' + path.dirname(r) + '/' + path.basename(r)),
|
|
193
211
|
ROOT: process.cwd() + '/app/',
|
|
194
|
-
OUT:
|
|
212
|
+
OUT: path.dirname(r),
|
|
213
|
+
file: process.cwd() + '/dist/' + path.dirname(r) + '/index.js',
|
|
214
|
+
DEV: mode === 'development',
|
|
215
|
+
filePath: r,
|
|
195
216
|
INPUT: `../app/${r.replace('.js', '.jsx')}`,
|
|
196
217
|
},
|
|
197
218
|
onExit({exitCode: code}) {
|
|
@@ -205,12 +226,50 @@ async function generateApp() {
|
|
|
205
226
|
})
|
|
206
227
|
|
|
207
228
|
})
|
|
229
|
+
|
|
230
|
+
switch(host_provider){
|
|
231
|
+
case 'vercel':
|
|
232
|
+
|
|
233
|
+
let vercelData = {
|
|
234
|
+
rewrites: []
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
for(let route in routes.routes){
|
|
238
|
+
let {filePath, kind, name, params, pathname,query} = routes.match(route)
|
|
239
|
+
let exists = vercelData.rewrites.find(v => v.source === `/${route}`)
|
|
240
|
+
let paramString = ''
|
|
241
|
+
if(pathname === '/'){
|
|
242
|
+
continue
|
|
243
|
+
}
|
|
244
|
+
if(params){
|
|
245
|
+
paramString = Object.keys(params).map(p => `:${p}`).join('/')
|
|
246
|
+
}
|
|
247
|
+
// replace double slashes
|
|
248
|
+
paramString = paramString.replace(/\/\//g, '/')
|
|
249
|
+
let base = path.dirname(route)
|
|
250
|
+
if(base.includes('[')){
|
|
251
|
+
base = base.split('[')[0].split('/').filter(v => v !== '').join('/')
|
|
252
|
+
}else{
|
|
253
|
+
base = base.split('/').filter(v => v !== '').join('/')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if(!exists){
|
|
257
|
+
vercelData.rewrites.push({
|
|
258
|
+
source: `/${base}/${paramString}`,
|
|
259
|
+
destination: `${path.dirname(routes.routes[route]).replace(process.cwd().replace(/\\/g, '/') + '/app', '')}/index.html`
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
fs.writeFileSync(process.cwd() + '/vercel.json', JSON.stringify(vercelData, null, 4))
|
|
264
|
+
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
208
267
|
|
|
209
268
|
})
|
|
210
269
|
|
|
211
270
|
}
|
|
212
271
|
|
|
213
|
-
generateApp()
|
|
272
|
+
await generateApp()
|
|
214
273
|
function handleFiles(){
|
|
215
274
|
return new Promise(async (resolve, reject) => {
|
|
216
275
|
try {
|
|
@@ -226,7 +285,7 @@ function handleFiles(){
|
|
|
226
285
|
}
|
|
227
286
|
})
|
|
228
287
|
}
|
|
229
|
-
handleFiles()
|
|
288
|
+
await handleFiles()
|
|
230
289
|
let isBuilding = false;
|
|
231
290
|
let timeout = null
|
|
232
291
|
if(mode === 'development'){
|
|
@@ -245,6 +304,8 @@ if(mode === 'development'){
|
|
|
245
304
|
watcher.on('change', async (event, filename) => {
|
|
246
305
|
try {
|
|
247
306
|
await generateApp()
|
|
307
|
+
|
|
308
|
+
handleFiles()
|
|
248
309
|
clients.forEach(c => {
|
|
249
310
|
c.send('reload')
|
|
250
311
|
})
|
|
@@ -289,14 +350,26 @@ if(mode === 'development'){
|
|
|
289
350
|
}
|
|
290
351
|
})
|
|
291
352
|
}
|
|
292
|
-
|
|
353
|
+
let router = new Bun.FileSystemRouter({
|
|
354
|
+
dir: process.cwd() + '/app',
|
|
355
|
+
style: 'nextjs'
|
|
356
|
+
})
|
|
357
|
+
router.reload()
|
|
358
|
+
let route = router.match(url.pathname)
|
|
359
|
+
if(!route){
|
|
360
|
+
return new Response('Not found', { status: 404 })
|
|
361
|
+
}
|
|
362
|
+
let p = route.pathname;
|
|
363
|
+
let base = path.dirname(route.filePath)
|
|
364
|
+
base = base.replace(path.join(process.cwd() + '/app'), '')
|
|
365
|
+
base = base.replace(/\\/g, '/').replace('/app', '/dist')
|
|
366
|
+
return new Response(await Bun.file(path.join(base, 'index.html')).text() + `
|
|
293
367
|
<script>
|
|
294
368
|
let ws = new WebSocket('ws://localhost:${server.port}')
|
|
295
369
|
ws.onmessage = (e) => {
|
|
296
370
|
if(e.data === 'reload'){
|
|
297
371
|
window.location.reload()
|
|
298
|
-
}
|
|
299
|
-
console.log(e.data)
|
|
372
|
+
}
|
|
300
373
|
}
|
|
301
374
|
</script>
|
|
302
375
|
`, {
|