@ossy/app 0.7.16 → 0.8.1
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/cli/dev.js +75 -36
- package/cli/server.js +36 -1
- package/package.json +2 -2
package/cli/dev.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import url from 'url';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import {
|
|
4
|
+
import { watch } from 'rollup';
|
|
5
5
|
import babel from '@rollup/plugin-babel';
|
|
6
6
|
import { nodeResolve as resolveDependencies } from '@rollup/plugin-node-resolve'
|
|
7
7
|
import resolveCommonJsDependencies from '@rollup/plugin-commonjs'
|
|
@@ -14,10 +14,11 @@ import copy from 'rollup-plugin-copy';
|
|
|
14
14
|
import replace from '@rollup/plugin-replace';
|
|
15
15
|
import remove from 'rollup-plugin-delete';
|
|
16
16
|
import arg from 'arg'
|
|
17
|
+
import { spawn } from 'node:child_process'
|
|
17
18
|
// import inject from '@rollup/plugin-inject'
|
|
18
19
|
|
|
19
20
|
export const dev = async (cliArgs) => {
|
|
20
|
-
console.log('[@ossy/app][
|
|
21
|
+
console.log('[@ossy/app][dev] Starting...')
|
|
21
22
|
|
|
22
23
|
const options = arg({
|
|
23
24
|
'--source': String,
|
|
@@ -28,12 +29,12 @@ export const dev = async (cliArgs) => {
|
|
|
28
29
|
|
|
29
30
|
'--config': String,
|
|
30
31
|
'-c': '--config',
|
|
31
|
-
}, { argv: cliArgs })
|
|
32
|
+
}, { argv: cliArgs, permissive: true })
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
const appSourcePath = path.resolve(options['--source'] || 'src/App.jsx');
|
|
35
|
-
let apiSourcePath = path.resolve(options['--api-source'] || 'src/
|
|
36
|
-
let middlewareSourcePath = path.resolve(options['--middleware-source'] || 'src/
|
|
36
|
+
let apiSourcePath = path.resolve(options['--api-source'] || 'src/api.js');
|
|
37
|
+
let middlewareSourcePath = path.resolve(options['--middleware-source'] || 'src/middleware.js');
|
|
37
38
|
const configPath = path.resolve(options['--config'] || 'src/config.js');
|
|
38
39
|
const buildPath = path.resolve(options['--destination'] || 'build');
|
|
39
40
|
const publicDir = path.resolve('public')
|
|
@@ -49,11 +50,11 @@ export const dev = async (cliArgs) => {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
if (!fs.existsSync(apiSourcePath)) {
|
|
52
|
-
apiSourcePath = path.resolve(scriptDir, '
|
|
53
|
+
apiSourcePath = path.resolve(scriptDir, 'api.js')
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
if (!fs.existsSync(middlewareSourcePath)) {
|
|
56
|
-
|
|
57
|
+
middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
if (fs.existsSync(configPath)) {
|
|
@@ -78,11 +79,11 @@ export const dev = async (cliArgs) => {
|
|
|
78
79
|
replace({
|
|
79
80
|
preventAssignment: true,
|
|
80
81
|
delimiters: ['%%', '%%'],
|
|
81
|
-
'@ossy/middleware/source-file':
|
|
82
|
+
'@ossy/middleware/source-file': middlewareSourcePath,
|
|
82
83
|
}),
|
|
83
84
|
replace({
|
|
84
85
|
preventAssignment: true,
|
|
85
|
-
'process.env.NODE_ENV': JSON.stringify('
|
|
86
|
+
'process.env.NODE_ENV': JSON.stringify('development')
|
|
86
87
|
}),
|
|
87
88
|
json(),
|
|
88
89
|
// removeOwnPeerDependencies(),
|
|
@@ -105,33 +106,71 @@ export const dev = async (cliArgs) => {
|
|
|
105
106
|
],
|
|
106
107
|
};
|
|
107
108
|
|
|
108
|
-
const outputOptions =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return 'public/static/[name].js'
|
|
121
|
-
} else {
|
|
122
|
-
return 'public/static/[name].js'
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
chunkFileNames: 'public/static/[name]-[hash].js',
|
|
126
|
-
format: 'esm',
|
|
127
|
-
}
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
const bundle = await rollup.watch(inputOptions);
|
|
131
|
-
|
|
132
|
-
for (const options of outputOptions) {
|
|
133
|
-
await bundle.write(options);
|
|
109
|
+
const outputOptions = {
|
|
110
|
+
dir: 'build',
|
|
111
|
+
// preserveModules: true,
|
|
112
|
+
entryFileNames: ({ name }) => {
|
|
113
|
+
const serverFileNames = ['server', 'api', 'middleware']
|
|
114
|
+
if (serverFileNames.includes(name)) return '[name].js'
|
|
115
|
+
if (name === 'client') return 'public/static/main.js'
|
|
116
|
+
if (name === 'config') return 'public/static/[name].js'
|
|
117
|
+
return 'public/static/[name].js'
|
|
118
|
+
},
|
|
119
|
+
chunkFileNames: 'public/static/[name]-[hash].js',
|
|
120
|
+
format: 'esm',
|
|
134
121
|
}
|
|
135
122
|
|
|
136
|
-
|
|
123
|
+
let serverProcess = null
|
|
124
|
+
const startServer = () => {
|
|
125
|
+
if (serverProcess) return
|
|
126
|
+
serverProcess = spawn(process.execPath, [path.resolve(buildPath, 'server.js'), ...process.argv.slice(3)], {
|
|
127
|
+
stdio: 'inherit',
|
|
128
|
+
env: {
|
|
129
|
+
...process.env,
|
|
130
|
+
OSSY_DEV_RELOAD: '1',
|
|
131
|
+
NODE_ENV: 'development',
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
serverProcess.on('exit', () => {
|
|
135
|
+
serverProcess = null
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const restartServer = () => {
|
|
140
|
+
if (!serverProcess) return startServer()
|
|
141
|
+
serverProcess.kill('SIGTERM')
|
|
142
|
+
serverProcess = null
|
|
143
|
+
startServer()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const triggerReload = async () => {
|
|
147
|
+
const port = process.env.PORT || '3000'
|
|
148
|
+
try {
|
|
149
|
+
await fetch(`http://localhost:${port}/__ossy_reload`, { method: 'POST' })
|
|
150
|
+
} catch {
|
|
151
|
+
// server might not be up yet
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const watcher = watch({
|
|
156
|
+
...inputOptions,
|
|
157
|
+
output: outputOptions,
|
|
158
|
+
watch: { clearScreen: false },
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
watcher.on('event', async (event) => {
|
|
162
|
+
if (event.code === 'BUNDLE_START') {
|
|
163
|
+
console.log('[@ossy/app][dev] Building...')
|
|
164
|
+
}
|
|
165
|
+
if (event.code === 'ERROR') {
|
|
166
|
+
console.error('[@ossy/app][dev] Build error', event.error)
|
|
167
|
+
}
|
|
168
|
+
if (event.code === 'BUNDLE_END') {
|
|
169
|
+
console.log(`[@ossy/app][dev] Built in ${event.duration}ms`)
|
|
170
|
+
}
|
|
171
|
+
if (event.code === 'END') {
|
|
172
|
+
await triggerReload()
|
|
173
|
+
restartServer()
|
|
174
|
+
}
|
|
175
|
+
})
|
|
137
176
|
};
|
package/cli/server.js
CHANGED
|
@@ -17,6 +17,9 @@ const app = express();
|
|
|
17
17
|
const currentDir = path.dirname(url.fileURLToPath(import.meta.url))
|
|
18
18
|
const ROOT_PATH = path.resolve(currentDir, 'public')
|
|
19
19
|
|
|
20
|
+
const isDevReloadEnabled = process.env.OSSY_DEV_RELOAD === '1'
|
|
21
|
+
const reloadClients = new Set()
|
|
22
|
+
|
|
20
23
|
function parsePortFromArgv(argv) {
|
|
21
24
|
// Supports: --port 4000, --port=4000, -p 4000
|
|
22
25
|
const idx = argv.findIndex(a => a === '--port' || a === '-p')
|
|
@@ -42,6 +45,34 @@ if (Middleware !== undefined) {
|
|
|
42
45
|
console.log(`[@ossy/app][server] ${Middleware?.length || 0} custom middleware loaded`)
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
if (isDevReloadEnabled) {
|
|
49
|
+
app.get('/__ossy_reload', (req, res) => {
|
|
50
|
+
res.status(200)
|
|
51
|
+
res.setHeader('Content-Type', 'text/event-stream')
|
|
52
|
+
res.setHeader('Cache-Control', 'no-cache')
|
|
53
|
+
res.setHeader('Connection', 'keep-alive')
|
|
54
|
+
res.flushHeaders?.()
|
|
55
|
+
|
|
56
|
+
res.write('event: connected\ndata: ok\n\n')
|
|
57
|
+
reloadClients.add(res)
|
|
58
|
+
|
|
59
|
+
req.on('close', () => {
|
|
60
|
+
reloadClients.delete(res)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
app.post('/__ossy_reload', (req, res) => {
|
|
65
|
+
for (const client of reloadClients) {
|
|
66
|
+
try {
|
|
67
|
+
client.write('event: reload\ndata: now\n\n')
|
|
68
|
+
} catch {
|
|
69
|
+
// ignore broken connections
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
res.status(204).end()
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
45
76
|
const middleware = [
|
|
46
77
|
morgan('tiny'),
|
|
47
78
|
express.json({ strict: false }),
|
|
@@ -99,8 +130,12 @@ app.listen(port, () => {
|
|
|
99
130
|
|
|
100
131
|
async function renderToString(App, config) {
|
|
101
132
|
|
|
133
|
+
const devReloadScript = isDevReloadEnabled
|
|
134
|
+
? `(function(){try{var es=new EventSource('/__ossy_reload');es.addEventListener('reload',function(){location.reload();});}catch(e){}})();`
|
|
135
|
+
: ``
|
|
136
|
+
|
|
102
137
|
const { prelude } = await prerenderToNodeStream(createElement(App, config), {
|
|
103
|
-
bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__ = ${JSON.stringify(config)}
|
|
138
|
+
bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__ = ${JSON.stringify(config)};${devReloadScript}`,
|
|
104
139
|
bootstrapModules: ['/static/main.js']
|
|
105
140
|
});
|
|
106
141
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"/cli",
|
|
59
59
|
"README.md"
|
|
60
60
|
],
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "8cd0c560777ae9e2bd3f11d02fed26f5bc1e7d5f"
|
|
62
62
|
}
|