@unsetsoft/ryunix-presets 1.0.26-canary.13 → 1.0.26-canary.16
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unsetsoft/ryunix-presets",
|
|
3
3
|
"description": "Package with presets for different development environments.",
|
|
4
|
-
"version": "1.0.26-canary.
|
|
4
|
+
"version": "1.0.26-canary.16",
|
|
5
5
|
"author": "Neyunse",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": "https://github.com/UnSetSoft/Ryunixjs",
|
|
@@ -56,16 +56,25 @@ const StartServer = async (cliSettings) => {
|
|
|
56
56
|
cleanCacheDir(cacheDir)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
const clientConfig = Array.isArray(webpackConfig) ? webpackConfig.find(c => c.name === 'client') || webpackConfig[0] : webpackConfig
|
|
60
|
+
|
|
61
|
+
if (Array.isArray(webpackConfig)) {
|
|
62
|
+
webpackConfig.forEach(c => c.mode = mode ? 'production' : 'development')
|
|
63
|
+
} else {
|
|
64
|
+
webpackConfig.mode = mode ? 'production' : 'development'
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
const compiler = Webpack(webpackConfig)
|
|
61
|
-
let port =
|
|
68
|
+
let port = clientConfig.devServer?.port || 3000
|
|
62
69
|
|
|
63
70
|
// Encontrar un puerto disponible
|
|
64
71
|
port = await findAvailablePort(port)
|
|
65
72
|
|
|
66
73
|
// Modificamos el puerto en la configuración
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
if (clientConfig.devServer) {
|
|
75
|
+
clientConfig.devServer.port = port
|
|
76
|
+
}
|
|
77
|
+
const devServerOptions = { ...(clientConfig.devServer || {}), ...cliSettings }
|
|
69
78
|
const server = new WebpackDevServer(devServerOptions, compiler)
|
|
70
79
|
|
|
71
80
|
const devMode = Boolean(!mode)
|
package/webpack/bin/index.mjs
CHANGED
|
@@ -13,12 +13,7 @@
|
|
|
13
13
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
|
-
|
|
17
|
-
<div style="display: flex;justify-content: center;align-items: center;">
|
|
18
|
-
<p><b>Warning:</b> JavaScript is not enabled. Some features may not work.
|
|
19
|
-
</p>
|
|
20
|
-
</div>
|
|
21
|
-
</noscript>
|
|
16
|
+
<%= htmlWebpackPlugin.options.ssrScript %>
|
|
22
17
|
<div id="__ryunix"></div>
|
|
23
18
|
</body>
|
|
24
19
|
</html>
|
package/webpack/utils/ssg.mjs
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import { prerenderRoute } from './ssg.mjs'
|
|
3
|
+
import { resolveApp } from './index.mjs'
|
|
4
|
+
|
|
5
|
+
export async function renderDevRoute(req, res, devServer, dir, config) {
|
|
6
|
+
// We only care about GET requests for HTML documents
|
|
7
|
+
if (req.method !== 'GET' || !req.headers.accept?.includes('text/html')) {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Find client compiler to read index.html from its memory file system
|
|
12
|
+
const clientCompiler = devServer.compiler.compilers
|
|
13
|
+
? devServer.compiler.compilers.find((c) => c.name === 'client')
|
|
14
|
+
: devServer.compiler
|
|
15
|
+
|
|
16
|
+
if (!clientCompiler) return false
|
|
17
|
+
|
|
18
|
+
const outputFs = clientCompiler.outputFileSystem
|
|
19
|
+
const buildDir = config.webpack.output.buildDirectory
|
|
20
|
+
const indexPath = resolveApp(dir, `${buildDir}/static/index.html`)
|
|
21
|
+
|
|
22
|
+
let template
|
|
23
|
+
try {
|
|
24
|
+
template = outputFs.readFileSync(indexPath, 'utf-8')
|
|
25
|
+
} catch (err) {
|
|
26
|
+
// index.html not generated yet, let the dev server handle default logic
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let AppRouterApp = null
|
|
31
|
+
let ryunixRenderToString = null
|
|
32
|
+
let ryunixCreateElement = null
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const serverBundlePath = resolveApp(dir, `${buildDir}/server/app-router-server.bundle.mjs`)
|
|
36
|
+
if (fs.existsSync(serverBundlePath)) {
|
|
37
|
+
if (typeof global.window === 'undefined') {
|
|
38
|
+
global.window = { location: { pathname: req.url } }
|
|
39
|
+
}
|
|
40
|
+
if (typeof global.document === 'undefined') {
|
|
41
|
+
global.document = { querySelector: () => null, getElementById: () => null }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const serverModule = await import(`file://${serverBundlePath}?update=${Date.now()}`)
|
|
45
|
+
AppRouterApp = serverModule.default?.default || serverModule.default
|
|
46
|
+
|
|
47
|
+
const ryunixCore = await import('@unsetsoft/ryunixjs')
|
|
48
|
+
const Ryunix = ryunixCore.default || ryunixCore
|
|
49
|
+
global.Ryunix = Ryunix
|
|
50
|
+
ryunixRenderToString = Ryunix.renderToString
|
|
51
|
+
ryunixCreateElement = Ryunix.createElement
|
|
52
|
+
}
|
|
53
|
+
} catch (e) {
|
|
54
|
+
console.warn(`[Ryunix SSR Dev] Failed to load server bundle: ${e.message}`)
|
|
55
|
+
return false // fallback to SPA
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let renderedString = ''
|
|
59
|
+
if (AppRouterApp && ryunixRenderToString && ryunixCreateElement) {
|
|
60
|
+
global.window = { location: { pathname: req.url } }
|
|
61
|
+
try {
|
|
62
|
+
const element = ryunixCreateElement(AppRouterApp)
|
|
63
|
+
renderedString = ryunixRenderToString(element)
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(`[Ryunix SSR Dev] Render error:`, err)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Generic mock route for prerenderRoute (to inject metadata)
|
|
70
|
+
const mockRoute = { path: req.url, meta: {} }
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
let html = await prerenderRoute(mockRoute, template, config, renderedString)
|
|
74
|
+
|
|
75
|
+
// In dev mode with SSR, MiniCssExtractPlugin outputs CSS to the virtual filesystem.
|
|
76
|
+
// We need to inject <link> tags for them so there is no FOUC.
|
|
77
|
+
try {
|
|
78
|
+
const cssDir = resolveApp(dir, `${buildDir}/static/css`)
|
|
79
|
+
if (outputFs.existsSync(cssDir)) {
|
|
80
|
+
const cssFiles = outputFs.readdirSync(cssDir).filter(f => f.endsWith('.css'))
|
|
81
|
+
const styleLinks = cssFiles.map(f => `<link rel="stylesheet" href="/css/${f}" />`).join('\n')
|
|
82
|
+
|
|
83
|
+
if (styleLinks) {
|
|
84
|
+
html = html.replace('</head>', `${styleLinks}\n</head>`)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {
|
|
88
|
+
// Ignore errors reading CSS directory
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
|
92
|
+
res.end(html)
|
|
93
|
+
return true
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error(`[Ryunix SSR Dev] Final render error:`, err)
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -23,6 +23,7 @@ import RyunixRoutesPlugin from './utils/ssgPlugin.mjs'
|
|
|
23
23
|
import AppRouterPlugin from './utils/appRouterPlugin.mjs'
|
|
24
24
|
import ApiRouterPlugin from './utils/ApiRouterPlugin.mjs'
|
|
25
25
|
import { handleApiRequest } from './utils/apiHandler.mjs'
|
|
26
|
+
import { renderDevRoute } from './utils/ssrDevHandler.mjs'
|
|
26
27
|
import remarkGfm from 'remark-gfm'
|
|
27
28
|
import remarkFrontmatter from 'remark-frontmatter'
|
|
28
29
|
import remarkMdxFrontmatter from 'remark-mdx-frontmatter'
|
|
@@ -121,17 +122,17 @@ const sharedWebpackConfig = {
|
|
|
121
122
|
minimize: config.webpack.production === true,
|
|
122
123
|
minimizer: config.webpack.production
|
|
123
124
|
? [
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
},
|
|
125
|
+
new TerserPlugin({
|
|
126
|
+
parallel: true,
|
|
127
|
+
terserOptions: {
|
|
128
|
+
compress: {
|
|
129
|
+
dead_code: true,
|
|
130
|
+
passes: 2,
|
|
131
131
|
},
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
},
|
|
133
|
+
}),
|
|
134
|
+
new CssMinimizerPlugin(),
|
|
135
|
+
]
|
|
135
136
|
: [],
|
|
136
137
|
},
|
|
137
138
|
cache: {
|
|
@@ -279,43 +280,61 @@ const getPlugins = (isServer = false) => [
|
|
|
279
280
|
}),
|
|
280
281
|
// Only inject HTML for the client build
|
|
281
282
|
!isServer &&
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
283
|
+
new HtmlWebpackPlugin({
|
|
284
|
+
pageLang: config.static.seo.pageLang,
|
|
285
|
+
title: config.static.seo.title,
|
|
286
|
+
favicon: config.static.favicon
|
|
287
|
+
? join(dir, 'public', 'favicon.png')
|
|
288
|
+
: false,
|
|
289
|
+
meta: config.static.seo.meta,
|
|
290
|
+
template: config.static.customTemplate
|
|
291
|
+
? join(dir, 'public', 'index.html')
|
|
292
|
+
: join(__dirname, 'template', 'index.html'),
|
|
293
|
+
info: {
|
|
294
|
+
framework: 'Ryunix',
|
|
295
|
+
version,
|
|
296
|
+
mode: config.webpack.production ? 'production' : 'dev',
|
|
297
|
+
},
|
|
298
|
+
ssrScript: isServer ? `
|
|
299
|
+
<noscript
|
|
300
|
+
style="background: #f4f47f;color: black;padding: 10px;width: 100%;display: block;position: fixed;bottom: 0;z-index: 99;">
|
|
301
|
+
<div style="display: flex;justify-content: center;align-items: center;">
|
|
302
|
+
<p><b>Warning:</b> JavaScript is not enabled. Some features may not work.
|
|
303
|
+
</p>
|
|
304
|
+
</div>
|
|
305
|
+
</noscript>
|
|
306
|
+
` : `
|
|
307
|
+
<noscript
|
|
308
|
+
style="background: #f57070ff;color: black;padding: 10px;width: 100%;display: block;position: fixed;bottom: 0;z-index: 99;">
|
|
309
|
+
<div style="display: flex;justify-content: center;align-items: center;">
|
|
310
|
+
<p><b>Error:</b> JavaScript is disabled. Please enable it to use this application.
|
|
311
|
+
</p>
|
|
312
|
+
</div>
|
|
313
|
+
</noscript>
|
|
314
|
+
|
|
315
|
+
`,
|
|
316
|
+
}),
|
|
298
317
|
!isServer &&
|
|
299
|
-
|
|
318
|
+
(config.webpack.production || config.experimental.ssr) &&
|
|
300
319
|
new MiniCssExtractPlugin({
|
|
301
320
|
filename: 'css/[name].[contenthash].css',
|
|
302
321
|
}),
|
|
303
322
|
!isServer &&
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
},
|
|
312
|
-
filter: (resourcePath) => {
|
|
313
|
-
try { return !resourcePath.toLowerCase().endsWith('.html') } catch { return true }
|
|
314
|
-
},
|
|
315
|
-
noErrorOnMissing: true,
|
|
323
|
+
new CopyWebpackPlugin({
|
|
324
|
+
patterns: [
|
|
325
|
+
{
|
|
326
|
+
from: resolveApp(dir, 'public'),
|
|
327
|
+
to: resolveApp(dir, `${config.webpack.output.buildDirectory}/static`),
|
|
328
|
+
globOptions: {
|
|
329
|
+
ignore: ['**/template.html', '**/index.html', '**/*.html', '**/favicon.png'],
|
|
316
330
|
},
|
|
317
|
-
|
|
318
|
-
|
|
331
|
+
filter: (resourcePath) => {
|
|
332
|
+
try { return !resourcePath.toLowerCase().endsWith('.html') } catch { return true }
|
|
333
|
+
},
|
|
334
|
+
noErrorOnMissing: true,
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
}),
|
|
319
338
|
...(!isServer ? config.webpack.plugins : []),
|
|
320
339
|
].filter(Boolean)
|
|
321
340
|
|
|
@@ -336,6 +355,11 @@ const clientConfig = {
|
|
|
336
355
|
},
|
|
337
356
|
devServer: {
|
|
338
357
|
watchFiles: [resolveApp(dir, 'src/**/*'), resolveApp(dir, 'app/**/*')],
|
|
358
|
+
devMiddleware: {
|
|
359
|
+
writeToDisk: (filePath) => {
|
|
360
|
+
try { return filePath.includes('/server/') || filePath.includes('\\server\\') } catch { return false }
|
|
361
|
+
},
|
|
362
|
+
},
|
|
339
363
|
hot: true,
|
|
340
364
|
historyApiFallback: {
|
|
341
365
|
index: '/',
|
|
@@ -367,6 +391,18 @@ const clientConfig = {
|
|
|
367
391
|
}
|
|
368
392
|
})
|
|
369
393
|
|
|
394
|
+
devServer.app.use(async (req, res, next) => {
|
|
395
|
+
try {
|
|
396
|
+
if (config.experimental.ssr) {
|
|
397
|
+
const handled = await renderDevRoute(req, res, devServer, dir, config)
|
|
398
|
+
if (handled) return
|
|
399
|
+
}
|
|
400
|
+
} catch (err) {
|
|
401
|
+
console.error('[Ryunix Dev SSR]', err)
|
|
402
|
+
}
|
|
403
|
+
next()
|
|
404
|
+
})
|
|
405
|
+
|
|
370
406
|
return middlewares
|
|
371
407
|
},
|
|
372
408
|
},
|
|
@@ -379,7 +415,7 @@ const clientConfig = {
|
|
|
379
415
|
test: /\.s[ac]ss|css$/i,
|
|
380
416
|
exclude: /node_modules/,
|
|
381
417
|
use: [
|
|
382
|
-
config.webpack.production
|
|
418
|
+
(config.webpack.production || config.experimental.ssr)
|
|
383
419
|
? MiniCssExtractPlugin.loader
|
|
384
420
|
: ryunixRequire.resolve('style-loader'),
|
|
385
421
|
ryunixRequire.resolve('css-loader'),
|
|
@@ -487,7 +523,8 @@ const serverConfig = {
|
|
|
487
523
|
]
|
|
488
524
|
}
|
|
489
525
|
|
|
490
|
-
// Export dual compilers
|
|
491
|
-
|
|
526
|
+
// Export dual compilers if SSR is enabled, or in production if SSG prerender is enabled
|
|
527
|
+
const enableServerDualCompiler = config.experimental.ssr || (config.webpack.production && config.experimental.ssg?.prerender?.length > 0);
|
|
528
|
+
export default enableServerDualCompiler
|
|
492
529
|
? [clientConfig, serverConfig]
|
|
493
530
|
: clientConfig;
|