wirejs-scripts 3.0.8 → 3.0.10
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/README.md +3 -0
- package/bin.js +52 -29
- package/configs/webpack.config.js +11 -213
- package/package.json +4 -3
- package/ssg.js +42 -0
package/README.md
ADDED
package/bin.js
CHANGED
|
@@ -4,11 +4,13 @@ import process from 'process';
|
|
|
4
4
|
import http from 'http';
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { Worker } from 'worker_threads';
|
|
7
8
|
|
|
8
9
|
import webpack from 'webpack';
|
|
9
10
|
import webpackConfigure from './configs/webpack.config.js';
|
|
10
11
|
import { rimraf } from 'rimraf';
|
|
11
12
|
import esbuild from 'esbuild';
|
|
13
|
+
import { contentType } from 'mime-types';
|
|
12
14
|
|
|
13
15
|
import { JSDOM } from 'jsdom';
|
|
14
16
|
import { useJSDOM } from 'wirejs-dom/v2';
|
|
@@ -115,7 +117,7 @@ async function handleApiResponse(req, res) {
|
|
|
115
117
|
const calls = JSON.parse(body);
|
|
116
118
|
logger.info('handling API request', body);
|
|
117
119
|
|
|
118
|
-
const apiPath = path.join(CWD, 'api', 'index.js');
|
|
120
|
+
const apiPath = path.join(CWD, 'api', 'dist', 'index.js');
|
|
119
121
|
const api = await import(`${apiPath}?cache-id=${new Date().getTime()}`);
|
|
120
122
|
|
|
121
123
|
const responses = [];
|
|
@@ -174,13 +176,7 @@ async function tryStaticPath(req, res) {
|
|
|
174
176
|
if (!fs.existsSync(fullPath)) return false;
|
|
175
177
|
logger.info('static found');
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
179
|
-
} else if (fullPath.endsWith(".js")) {
|
|
180
|
-
res.setHeader('Content-Type', 'text/javascript; charset=utf-8');
|
|
181
|
-
} else {
|
|
182
|
-
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
183
|
-
}
|
|
179
|
+
res.setHeader('Content-Type', contentType(path.extname(fullPath)));
|
|
184
180
|
|
|
185
181
|
try {
|
|
186
182
|
res.end(fs.readFileSync(fullPath));
|
|
@@ -284,26 +280,32 @@ async function trySSRPath(req, res) {
|
|
|
284
280
|
const module = self.exports;
|
|
285
281
|
if (typeof module.generate === 'function') {
|
|
286
282
|
const doc = await module.generate(context);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
283
|
+
if (typeof doc.outerHTML === 'undefined') {
|
|
284
|
+
res.setHeader('Content-Type', contentType(
|
|
285
|
+
context.location.pathname.split('.').pop()
|
|
286
|
+
));
|
|
287
|
+
res.end(doc);
|
|
288
|
+
} else {
|
|
289
|
+
const doctype = doc.parentNode.doctype?.name || '';
|
|
294
290
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
291
|
+
let hydrationsFound = 0;
|
|
292
|
+
while (globalThis.pendingDehydrations?.length > 0) {
|
|
293
|
+
globalThis.pendingDehydrations.shift()(doc);
|
|
294
|
+
hydrationsFound++;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (hydrationsFound) {
|
|
298
|
+
const script = doc.parentNode.createElement('script');
|
|
299
|
+
script.src = asJSPath;
|
|
300
|
+
doc.parentNode.body.appendChild(script);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
res.setHeader('Content-type', 'text/html; charset=utf-8');
|
|
304
|
+
res.end([
|
|
305
|
+
doctype ? `<!doctype ${doctype}>\n` : '',
|
|
306
|
+
doc.outerHTML
|
|
307
|
+
].join(''));
|
|
299
308
|
}
|
|
300
|
-
|
|
301
|
-
res.setHeader('Content-type', 'text/html; charset=utf-8');
|
|
302
|
-
res.end([
|
|
303
|
-
doctype ? `<!doctype ${doctype}>\n` : '',
|
|
304
|
-
doc.outerHTML
|
|
305
|
-
].join(''));
|
|
306
|
-
|
|
307
309
|
return true;
|
|
308
310
|
} else {
|
|
309
311
|
logger.info('SSR module missing generate function');
|
|
@@ -367,6 +369,25 @@ async function compile(watch = false) {
|
|
|
367
369
|
const stats = await new Promise(async (resolve, reject) => {
|
|
368
370
|
let compiler;
|
|
369
371
|
if (watch) {
|
|
372
|
+
|
|
373
|
+
const apiDir = path.join(CWD, 'api');
|
|
374
|
+
const prebuildApiWatch = await esbuild.context({
|
|
375
|
+
entryPoints: [path.join(CWD, 'api', '**', '*.ts')],
|
|
376
|
+
outdir: path.join(apiDir, 'dist'),
|
|
377
|
+
platform: 'node',
|
|
378
|
+
bundle: true,
|
|
379
|
+
external: ['./node_modules/*'],
|
|
380
|
+
format: 'esm',
|
|
381
|
+
plugins: [{
|
|
382
|
+
name: 'post-build-rebuild-api-client',
|
|
383
|
+
setup(build) {
|
|
384
|
+
build.onEnd(() => prebuildApi(apiDir))
|
|
385
|
+
}
|
|
386
|
+
}]
|
|
387
|
+
});
|
|
388
|
+
await prebuildApiWatch.rebuild();
|
|
389
|
+
prebuildApiWatch.watch();
|
|
390
|
+
|
|
370
391
|
const prebuild = await esbuild.context({
|
|
371
392
|
entryPoints: [`${CWD}/src/**/*.ts`],
|
|
372
393
|
outdir: `${CWD}/pre-dist`,
|
|
@@ -376,6 +397,7 @@ async function compile(watch = false) {
|
|
|
376
397
|
});
|
|
377
398
|
await prebuild.rebuild();
|
|
378
399
|
prebuild.watch();
|
|
400
|
+
|
|
379
401
|
webpack({
|
|
380
402
|
...getWebpackConfig(),
|
|
381
403
|
mode: 'development',
|
|
@@ -390,6 +412,7 @@ async function compile(watch = false) {
|
|
|
390
412
|
server.listen(3000).on('listening', () => {
|
|
391
413
|
console.log('Started listening on http://localhost:3000/')
|
|
392
414
|
});
|
|
415
|
+
|
|
393
416
|
} else {
|
|
394
417
|
logger.log('prebundling JS');
|
|
395
418
|
await esbuild.build({
|
|
@@ -470,13 +493,13 @@ const engine = {
|
|
|
470
493
|
async ['prebuild-api']() {
|
|
471
494
|
logger.log("prebuilding api ...");
|
|
472
495
|
await esbuild.build({
|
|
473
|
-
entryPoints: [
|
|
474
|
-
outdir: CWD,
|
|
496
|
+
entryPoints: [path.join(CWD, '**', '*.ts')],
|
|
497
|
+
outdir: path.join(CWD, 'dist'),
|
|
475
498
|
platform: 'node',
|
|
476
499
|
bundle: false,
|
|
477
500
|
format: 'esm',
|
|
478
501
|
});
|
|
479
|
-
await prebuildApi();
|
|
502
|
+
await prebuildApi(CWD);
|
|
480
503
|
logger.log("api prebuild finished");
|
|
481
504
|
},
|
|
482
505
|
};
|
|
@@ -1,28 +1,14 @@
|
|
|
1
|
-
import { useJSDOM } from 'wirejs-dom/v2';
|
|
2
|
-
import fs from 'fs';
|
|
3
1
|
import path from 'path';
|
|
4
2
|
import glob from 'glob';
|
|
5
3
|
import process from 'process';
|
|
6
4
|
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
|
7
|
-
import
|
|
8
|
-
import { JSDOM } from 'jsdom';
|
|
9
|
-
|
|
5
|
+
import { execSync } from 'child_process';
|
|
10
6
|
|
|
11
7
|
const CWD = process.cwd();
|
|
12
8
|
const SRC = 'pre-dist';
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
highlight: function (code, lang) {
|
|
17
|
-
try {
|
|
18
|
-
const highlighter = require('highlight.js');
|
|
19
|
-
const language = highlighter.getLanguage(lang) ? lang : 'plaintext';
|
|
20
|
-
return highlighter.highlight(code, { language }).value;
|
|
21
|
-
} catch (e) {
|
|
22
|
-
console.log("highlight.js not installed. Skipping syntax highlighting.");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
10
|
+
const __filename = import.meta.url.replace(/^file:/, '');
|
|
11
|
+
const SELF_DIR = path.dirname(__filename);
|
|
26
12
|
|
|
27
13
|
function distPath({ subpathOut = '', subpathIn = '', extensionOut } = {}) {
|
|
28
14
|
return function ({ context, absoluteFilename }) {
|
|
@@ -37,90 +23,24 @@ function distPath({ subpathOut = '', subpathIn = '', extensionOut } = {}) {
|
|
|
37
23
|
};
|
|
38
24
|
};
|
|
39
25
|
|
|
40
|
-
const layouts = {};
|
|
41
|
-
const CollectLayouts = {
|
|
42
|
-
transformer: (content, path) => {
|
|
43
|
-
// add one to dirname prefix to include separating slash
|
|
44
|
-
const relativePath = path.slice(CWD.length + 1);
|
|
45
|
-
layouts[relativePath] = content.toString();
|
|
46
|
-
return layouts[relativePath];
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const SSG = {
|
|
51
|
-
transformer: async (content, _path) => {
|
|
52
|
-
let _meta = {};
|
|
53
|
-
|
|
54
|
-
let body;
|
|
55
|
-
try {
|
|
56
|
-
body = _path.endsWith('.md') ? marked(content.toString()) : content.toString();
|
|
57
|
-
} catch (err) {
|
|
58
|
-
console.error(`Could not parse page ${_path}`, err);
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// apply no layout if the document has already provided the
|
|
63
|
-
// overarching html structure.
|
|
64
|
-
if (!_meta.layout && body && (
|
|
65
|
-
String(body).startsWith('<!doctype html>')
|
|
66
|
-
|| String(body).startsWith('<html'))
|
|
67
|
-
) {
|
|
68
|
-
return body;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const layoutPath = path.join(
|
|
72
|
-
SRC,
|
|
73
|
-
'layouts',
|
|
74
|
-
(_meta.layout || 'default')
|
|
75
|
-
) + '.html';
|
|
76
|
-
|
|
77
|
-
const layout = layouts[layoutPath];
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
return layout;
|
|
81
|
-
} catch (err) {
|
|
82
|
-
console.error(`Could not parse layout ${layoutPath}`, err);
|
|
83
|
-
throw err;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
26
|
const Generated = {
|
|
89
27
|
transformer: async (content, contentPath) => {
|
|
90
|
-
useJSDOM(JSDOM);
|
|
91
|
-
|
|
92
28
|
try {
|
|
93
29
|
if (contentPath.endsWith('.js')) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
while (globalThis.pendingDehydrations?.length > 0) {
|
|
101
|
-
globalThis.pendingDehydrations.shift()(doc);
|
|
102
|
-
hydrationsFound++;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (hydrationsFound) {
|
|
106
|
-
const script = doc.parentNode.createElement('script');
|
|
107
|
-
script.src = contentPath.substring((`${CWD}/${SRC}/ssg`).length);
|
|
108
|
-
doc.parentNode.body.appendChild(script);
|
|
30
|
+
// generated in a subprocess to ensure imports are clean, especially
|
|
31
|
+
// when in watch mode.
|
|
32
|
+
const generatedContent = execSync(
|
|
33
|
+
`node ${SELF_DIR}/../ssg.js ${CWD}/${SRC} ${contentPath}`,
|
|
34
|
+
{
|
|
35
|
+
stdio: [ 'pipe', 'pipe', 'pipe' ]
|
|
109
36
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
doctype ? `<!doctype ${doctype}>\n` : '',
|
|
113
|
-
doc.outerHTML
|
|
114
|
-
].join('');
|
|
115
|
-
} else {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
37
|
+
);
|
|
38
|
+
return generatedContent;
|
|
118
39
|
} else {
|
|
119
40
|
return content.toString();
|
|
120
41
|
}
|
|
121
42
|
} catch (err) {
|
|
122
43
|
console.error(`Could not generate page ${contentPath}`, err);
|
|
123
|
-
throw err;
|
|
124
44
|
}
|
|
125
45
|
}
|
|
126
46
|
};
|
|
@@ -177,25 +97,6 @@ export default (env, argv) => {
|
|
|
177
97
|
target: 'web',
|
|
178
98
|
devtool,
|
|
179
99
|
plugins: [
|
|
180
|
-
|
|
181
|
-
// TODO: does it make sense to actually handle static assets
|
|
182
|
-
// first? then layouts? then everything else?
|
|
183
|
-
|
|
184
|
-
// handle layouts first. other things depend on them.
|
|
185
|
-
new CopyWebpackPlugin({
|
|
186
|
-
patterns: [
|
|
187
|
-
{
|
|
188
|
-
from: `./${SRC}/layouts/**/*.html`,
|
|
189
|
-
to: distPath({
|
|
190
|
-
subpathIn: `${SRC}/layouts`,
|
|
191
|
-
subpathOut: 'layouts'
|
|
192
|
-
}),
|
|
193
|
-
transform: CollectLayouts,
|
|
194
|
-
noErrorOnMissing: true,
|
|
195
|
-
},
|
|
196
|
-
]
|
|
197
|
-
}),
|
|
198
|
-
|
|
199
100
|
// now pages, etc.
|
|
200
101
|
new CopyWebpackPlugin({
|
|
201
102
|
patterns: [
|
|
@@ -211,111 +112,8 @@ export default (env, argv) => {
|
|
|
211
112
|
noErrorOnMissing: true,
|
|
212
113
|
priority: 5
|
|
213
114
|
},
|
|
214
|
-
// {
|
|
215
|
-
// from: './src/routes/**/*.md',
|
|
216
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
217
|
-
// transform: SSG,
|
|
218
|
-
// noErrorOnMissing: true,
|
|
219
|
-
// priority: 3,
|
|
220
|
-
// },
|
|
221
|
-
// {
|
|
222
|
-
// from: './src/routes/**/*.html',
|
|
223
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
224
|
-
// transform: SSG,
|
|
225
|
-
// noErrorOnMissing: true,
|
|
226
|
-
// priority: 3,
|
|
227
|
-
// },
|
|
228
|
-
// {
|
|
229
|
-
// from: './src/routes/**/*.xml',
|
|
230
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
231
|
-
// transform: SSG,
|
|
232
|
-
// noErrorOnMissing: true,
|
|
233
|
-
// priority: 3,
|
|
234
|
-
// },
|
|
235
|
-
// {
|
|
236
|
-
// from: './src/routes/**/*.rss',
|
|
237
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
238
|
-
// transform: SSG,
|
|
239
|
-
// noErrorOnMissing: true,
|
|
240
|
-
// priority: 3,
|
|
241
|
-
// },
|
|
242
|
-
// {
|
|
243
|
-
// from: './src/routes/**/*.css',
|
|
244
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
245
|
-
// noErrorOnMissing: true,
|
|
246
|
-
// // trasform: ???
|
|
247
|
-
// priority: 3,
|
|
248
|
-
// },
|
|
249
|
-
// {
|
|
250
|
-
// from: './src/routes/**/*.png',
|
|
251
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
252
|
-
// noErrorOnMissing: true,
|
|
253
|
-
// priority: 3,
|
|
254
|
-
// },
|
|
255
|
-
// {
|
|
256
|
-
// from: './src/routes/**/*.jpg',
|
|
257
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
258
|
-
// noErrorOnMissing: true,
|
|
259
|
-
// priority: 3,
|
|
260
|
-
// },
|
|
261
|
-
// {
|
|
262
|
-
// from: './src/routes/**/*.json',
|
|
263
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
264
|
-
// noErrorOnMissing: true,
|
|
265
|
-
// priority: 3,
|
|
266
|
-
// },
|
|
267
|
-
// {
|
|
268
|
-
// from: './src/routes/**/*.svg',
|
|
269
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
270
|
-
// noErrorOnMissing: true,
|
|
271
|
-
// priority: 3,
|
|
272
|
-
// },
|
|
273
|
-
// {
|
|
274
|
-
// from: './src/routes/**/*.mp3',
|
|
275
|
-
// to: distPath({ subpathIn: 'src/routes' }),
|
|
276
|
-
// noErrorOnMissing: true,
|
|
277
|
-
// priority: 3,
|
|
278
|
-
// },
|
|
279
115
|
],
|
|
280
116
|
}),
|
|
281
117
|
],
|
|
282
|
-
module: {
|
|
283
|
-
rules: [
|
|
284
|
-
{
|
|
285
|
-
test: /\.css$/,
|
|
286
|
-
use: [
|
|
287
|
-
"style-loader",
|
|
288
|
-
// path.resolve(__dirname, '../node_modules/style-loader'),
|
|
289
|
-
{
|
|
290
|
-
loader: "css-loader",
|
|
291
|
-
// loader: path.resolve(__dirname, '../node_modules/css-loader'),
|
|
292
|
-
options: {
|
|
293
|
-
// don't try to require() url assets
|
|
294
|
-
url: false
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
]
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
test: /\.html$/,
|
|
301
|
-
loader: "file-loader",
|
|
302
|
-
// loader: path.resolve(__dirname, '../node_modules/file-loader'),
|
|
303
|
-
options: {
|
|
304
|
-
name: "[name].[ext]",
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
test: /\.mjs$/,
|
|
309
|
-
resolve: {
|
|
310
|
-
fullySpecified: false
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
test: /\.(md|tpl)$/,
|
|
315
|
-
use: "raw-loader",
|
|
316
|
-
// use: path.resolve(__dirname, '../node_modules/raw-loader')
|
|
317
|
-
},
|
|
318
|
-
]
|
|
319
|
-
}
|
|
320
118
|
};
|
|
321
119
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wirejs-scripts",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.10",
|
|
4
4
|
"description": "Basic build and start commands for wirejs apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,11 +28,12 @@
|
|
|
28
28
|
"glob": "^7.2.0",
|
|
29
29
|
"jsdom": "^25.0.1",
|
|
30
30
|
"marked": "^2.0.1",
|
|
31
|
+
"mime-types": "^2.1.35",
|
|
31
32
|
"raw-loader": "^4.0.2",
|
|
32
33
|
"rimraf": "^6.0.1",
|
|
33
34
|
"style-loader": "^2.0.0",
|
|
34
35
|
"webpack": "^5.97.1",
|
|
35
36
|
"wirejs-dom": "^1.0.38",
|
|
36
|
-
"wirejs-resources": "^0.1.
|
|
37
|
+
"wirejs-resources": "^0.1.12"
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
|
+
}
|
package/ssg.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import process from 'process';
|
|
2
|
+
import { JSDOM } from 'jsdom';
|
|
3
|
+
import { useJSDOM } from 'wirejs-dom/v2';
|
|
4
|
+
|
|
5
|
+
const SRC_DIR = process.argv[2];
|
|
6
|
+
|
|
7
|
+
async function build(filename) {
|
|
8
|
+
useJSDOM(JSDOM);
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const module = await import(filename);
|
|
12
|
+
|
|
13
|
+
if (typeof module.generate === 'function') {
|
|
14
|
+
const doc = await module.generate(filename);
|
|
15
|
+
const doctype = doc.parentNode.doctype?.name || '';
|
|
16
|
+
|
|
17
|
+
let hydrationsFound = 0;
|
|
18
|
+
while (globalThis.pendingDehydrations?.length > 0) {
|
|
19
|
+
globalThis.pendingDehydrations.shift()(doc);
|
|
20
|
+
hydrationsFound++;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (hydrationsFound) {
|
|
24
|
+
const script = doc.parentNode.createElement('script');
|
|
25
|
+
script.src = filename.substring((`${SRC_DIR}/ssg`).length);
|
|
26
|
+
doc.parentNode.body.appendChild(script);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return [
|
|
30
|
+
doctype ? `<!doctype ${doctype}>\n` : '',
|
|
31
|
+
doc.outerHTML
|
|
32
|
+
].join('');
|
|
33
|
+
} else {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
} catch (err) {
|
|
37
|
+
console.error(`Could not generate page ${filename}`, err);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(await build(process.argv[3]));
|