Skip to content

Commit 1be78bb

Browse files
authored
Merge pull request nullstack#343 from nullstack/next
Next
2 parents 8c29696 + 96c3637 commit 1be78bb

File tree

100 files changed

+1639
-1452
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+1639
-1452
lines changed

builders/logger.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
const clocks = ['🕛', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚']
3+
4+
function logger(bundle, mode) {
5+
let cindex = 0
6+
let timer = null
7+
let stoped = false
8+
9+
function dots() {
10+
return Array((cindex % 3) + 1).fill('.').join('')
11+
}
12+
13+
function reset() {
14+
if (process.stdout.clearLine) {
15+
process.stdout.clearLine()
16+
process.stdout.cursorTo(0)
17+
}
18+
}
19+
20+
function start() {
21+
reset()
22+
if (cindex >= clocks.length) {
23+
cindex = 0
24+
}
25+
let symbol = clocks[cindex]
26+
process.stdout.write(` ${symbol} Building your ${bundle} in ${mode} mode ${dots()}`)
27+
cindex++;
28+
timer = setTimeout(start, 200)
29+
}
30+
start()
31+
32+
function stop() {
33+
if (stoped) return
34+
clearTimeout(timer)
35+
reset()
36+
process.stdout.write(` ✅ Starting your ${bundle} in ${mode} mode\n`)
37+
stoped = true
38+
}
39+
40+
return { stop }
41+
}
42+
43+
module.exports = logger

builders/spa.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module.exports = async function spa({ output, cache, environment }) {
3434
await copy('/robots.txt')
3535
console.info()
3636

37-
console.info('\x1b[36m%s\x1b[0m', ` ✅️ ${projectName} is ready at ${folder}\n`)
37+
console.info('\x1b[36m%s\x1b[0m', ` 🚀 ${projectName} is ready at ${folder}\n`)
3838

3939
if (cache) {
4040
console.info('Storing cache...')

builders/ssg.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,8 @@ module.exports = async function ssg({ output, cache, environment }) {
7979
const urls = Object.keys(pages).map((p) => {
8080
const page = pages[p]
8181
const canonical = `https://${application.project.domain}${p}`
82-
return `<url><loc>${canonical}</loc><lastmod>${timestamp}</lastmod>${
83-
page.changes ? `<changefreq>${page.changes}</changefreq>` : ''
84-
}${page.priority ? `<priority>${page.priority.toFixed(1)}</priority>` : ''}</url>`
82+
return `<url><loc>${canonical}</loc><lastmod>${timestamp}</lastmod>${page.changes ? `<changefreq>${page.changes}</changefreq>` : ''
83+
}${page.priority ? `<priority>${page.priority.toFixed(1)}</priority>` : ''}</url>`
8584
})
8685
const xml = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls.join(
8786
'',
@@ -111,7 +110,7 @@ module.exports = async function ssg({ output, cache, environment }) {
111110
await createSitemap()
112111
console.info()
113112

114-
console.info('\x1b[36m%s\x1b[0m', ` ✅️ ${projectName} is ready at ${folder}\n`)
113+
console.info('\x1b[36m%s\x1b[0m', ` 🚀 ${projectName} is ready at ${folder}\n`)
115114

116115
if (cache) {
117116
console.info('Storing cache...')

builders/ssr.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module.exports = async function ssr({ cache }) {
33
const application = require(`${dir}/.production/server`).default
44
const projectName = application.project.name || 'The Nullstack application'
55

6-
console.info('\x1b[36m%s\x1b[0m', `\n ✅️ ${projectName} is ready for production\n`)
6+
console.info('\x1b[36m%s\x1b[0m', `\n 🚀 ${projectName} is ready for production\n`)
77

88
if (cache) {
99
console.info('Storing cache...')

client/client.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ client.nextHead = []
2626
client.head = document.head
2727
client.body = document.body
2828

29-
client.update = async function update() {
29+
client.update = function update() {
3030
if (client.initialized) {
3131
clearInterval(client.renderQueue)
3232
client.renderQueue = setTimeout(async () => {
@@ -39,9 +39,13 @@ client.update = async function update() {
3939
client.nextVirtualDom = await generateTree(client.initializer(), scope)
4040
rerender()
4141
client.processLifecycleQueues()
42-
} catch (e) {
42+
} catch (error) {
4343
client.skipHotReplacement = true
44-
console.error(e)
44+
if (context.catch) {
45+
context.catch(error)
46+
} else {
47+
throw error
48+
}
4549
}
4650
}, 16)
4751
}
@@ -97,4 +101,8 @@ client.processLifecycleQueues = async function processLifecycleQueues() {
97101
router._changed = false
98102
}
99103

104+
if (module.hot) {
105+
client.klasses = {}
106+
}
107+
100108
export default client

client/index.js

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import element from '../shared/element'
2-
import fragment from '../shared/fragment'
32
import generateTree from '../shared/generateTree'
43
import { loadPlugins, useClientPlugins } from '../shared/plugins'
54
import client from './client'
65
import context, { generateContext } from './context'
76
import environment from './environment'
87
import hydrate from './hydrate'
98
import instanceProxyHandler, { instanceProxies } from './instanceProxyHandler'
10-
import invoke from './invoke'
119
import page from './page'
1210
import params, { updateParams } from './params'
1311
import project from './project'
@@ -16,7 +14,6 @@ import rerender from './rerender'
1614
import router from './router'
1715
import settings from './settings'
1816
import state from './state'
19-
import windowEvent from './windowEvent'
2017
import worker from './worker'
2118

2219
context.page = page
@@ -35,11 +32,12 @@ scope.context = context
3532

3633
client.plugins = loadPlugins(scope)
3734

35+
if (environment.development) {
36+
globalThis.$nullstack = context
37+
}
38+
3839
export default class Nullstack {
3940

40-
static element = element
41-
static invoke = invoke
42-
static fragment = fragment
4341
static use = useClientPlugins
4442
static context = generateContext({})
4543

@@ -104,48 +102,3 @@ export default class Nullstack {
104102
}
105103

106104
}
107-
108-
if (module.hot) {
109-
Nullstack.serverHashes ??= {}
110-
Nullstack.serverPings = 0
111-
Nullstack.clientPings = 0
112-
const socket = new WebSocket(`ws${router.base.slice(4)}/ws`)
113-
socket.onmessage = async function (e) {
114-
const data = JSON.parse(e.data)
115-
if (data.type === 'NULLSTACK_SERVER_STARTED') {
116-
Nullstack.serverPings++
117-
if (Nullstack.needsReload || !environment.hot) {
118-
window.location.reload()
119-
}
120-
}
121-
}
122-
Nullstack.updateInstancesPrototypes = function updateInstancesPrototypes(klass, hash, serverHash) {
123-
for (const key in context.instances) {
124-
const instance = context.instances[key]
125-
if (instance.constructor.hash === hash) {
126-
Object.setPrototypeOf(instance, klass.prototype)
127-
}
128-
}
129-
if (Nullstack.serverHashes[hash]) {
130-
if (Nullstack.serverHashes[hash] !== serverHash) {
131-
if (Nullstack.clientPings < Nullstack.serverPings) {
132-
window.location.reload()
133-
} else {
134-
Nullstack.needsReload = true
135-
}
136-
}
137-
Nullstack.clientPings++
138-
}
139-
Nullstack.serverHashes[hash] = serverHash
140-
client.update()
141-
}
142-
Nullstack.hotReload = function hotReload(klass) {
143-
if (client.skipHotReplacement) {
144-
window.location.reload()
145-
} else {
146-
Nullstack.start(klass)
147-
windowEvent('environment')
148-
}
149-
}
150-
module.hot.decline()
151-
}

client/invoke.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import deserialize from '../shared/deserialize'
22
import prefix from '../shared/prefix'
33
import page from './page'
44
import worker from './worker'
5+
import client from './client'
56

67
export default function invoke(name, hash) {
78
return async function _invoke(params = {}) {
@@ -12,8 +13,12 @@ export default function invoke(name, hash) {
1213
} else {
1314
worker.queues[name] = [...worker.queues[name], params]
1415
}
15-
const finalHash = hash === this.hash ? hash : `${hash}-${this.hash}`
16+
let finalHash = hash === this.hash ? hash : `${hash}-${this.hash}`
1617
let url = `${worker.api}/${prefix}/${finalHash}/${name}.json`
18+
if (module.hot) {
19+
const version = client.klasses[hash].__hashes[name]
20+
url = `${worker.api}/${prefix}/${version}/${finalHash}/${name}.json`
21+
}
1722
const body = JSON.stringify(params || {})
1823
const options = {
1924
headers: worker.headers,

client/lazy.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import client from './client'
2+
3+
const queue = {}
4+
let next = null
5+
6+
async function preload() {
7+
cancelIdleCallback(next)
8+
let entry = Object.entries(queue)[0]
9+
if (!entry) return
10+
let loader = entry[1]
11+
if (!loader) return
12+
await loader.load()
13+
next = requestIdleCallback(preload)
14+
}
15+
16+
window.addEventListener('blur', () => {
17+
preload()
18+
})
19+
20+
window.addEventListener('focus', () => {
21+
cancelIdleCallback(next)
22+
})
23+
24+
export default function lazy(hash, importer) {
25+
const loader = {
26+
load: async () => {
27+
const mod = await importer()
28+
loader.component = mod.default
29+
delete queue[hash]
30+
client.update()
31+
},
32+
component: null,
33+
__nullstack_lazy: true
34+
}
35+
queue[hash] = loader
36+
return loader
37+
}

client/logo.njs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from '../logo'

client/page.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ delete state.page
1111

1212
const pageProxyHandler = {
1313
set(target, name, value, receiver) {
14-
if (name === 'title') {
15-
document.title = value
16-
}
1714
const result = Reflect.set(target, name, value, receiver)
1815
if (name === 'title') {
16+
document.title = value
17+
document.querySelector('head > meta[property="og:title"]').setAttribute('content', value)
1918
windowEvent('page')
19+
} else if (name === 'description') {
20+
document.querySelector('head > meta[name="description"]').setAttribute('content', value)
21+
document.querySelector('head > meta[property="og:description"]').setAttribute('content', value)
22+
} else if (name === 'locale') {
23+
document.querySelector('html').setAttribute('lang', value)
24+
document.querySelector('head > meta[property="og:locale"]').setAttribute('content', value)
25+
} else if (name === 'image') {
26+
document.querySelector('head > meta[property="og:image"]').setAttribute('content', value)
27+
} else if (name === 'canonical') {
28+
canonical = (path.indexOf('//') === -1) ? router.base + value : value
29+
document.querySelector('head > link[rel="canonical"]').setAttribute('href', canonical)
2030
}
2131
client.update()
2232
return result

0 commit comments

Comments
 (0)