@ossy/app 1.13.2 → 1.13.3
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/build.js +58 -65
- package/cli/prerender-react.task.js +45 -92
- package/cli/render-page.task.js +3 -2
- package/package.json +10 -10
package/cli/build.js
CHANGED
|
@@ -92,14 +92,8 @@ export const OSSY_SSR_DIRNAME = 'ssr'
|
|
|
92
92
|
/** Temp stub entries for SSR bundles (inside .ossy/). */
|
|
93
93
|
const OSSY_SSR_ENTRIES_DIRNAME = 'ssr-entries'
|
|
94
94
|
|
|
95
|
-
/**
|
|
96
|
-
const
|
|
97
|
-
const HYDRATE_STUB_SUFFIX = '.jsx'
|
|
98
|
-
|
|
99
|
-
/** Rollup input chunk name for a page id (safe identifier; id may contain `-`). */
|
|
100
|
-
export function hydrateEntryName (pageId) {
|
|
101
|
-
return `hydrate__${pageId}`
|
|
102
|
-
}
|
|
95
|
+
/** Single shared client hydrate entry filename under `.ossy/` */
|
|
96
|
+
const HYDRATE_ENTRY_FILENAME = 'hydrate-entry.jsx'
|
|
103
97
|
|
|
104
98
|
export function ossyGeneratedDir (buildPath) {
|
|
105
99
|
return path.join(buildPath, OSSY_GEN_DIRNAME)
|
|
@@ -709,83 +703,81 @@ export function writePageServerRollupEntry ({ pageAbsPath, stubPath }) {
|
|
|
709
703
|
}
|
|
710
704
|
|
|
711
705
|
/**
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
706
|
+
* Generates a single shared hydrate entry that dynamically imports the active page at runtime.
|
|
707
|
+
* Rollup processes this once, emitting React and shared deps as reusable chunks instead of
|
|
708
|
+
* bundling them into every page separately.
|
|
715
709
|
*/
|
|
716
|
-
export function
|
|
717
|
-
const
|
|
710
|
+
export function generateHydrateEntry ({ pageFiles, srcDir, stubAbsPath }) {
|
|
711
|
+
const seenIds = new Set()
|
|
712
|
+
const pageLines = []
|
|
713
|
+
for (const f of pageFiles) {
|
|
714
|
+
const hydrateId = clientHydrateIdForPage(f, srcDir)
|
|
715
|
+
if (seenIds.has(hydrateId)) {
|
|
716
|
+
throw new Error(
|
|
717
|
+
`[@ossy/app] Duplicate client hydrate id "${hydrateId}" (${f}). Pages need unique ids.`
|
|
718
|
+
)
|
|
719
|
+
}
|
|
720
|
+
seenIds.add(hydrateId)
|
|
721
|
+
const rel = relToGeneratedImport(stubAbsPath, f)
|
|
722
|
+
pageLines.push(` '${hydrateId}': () => import('./${rel}'),`)
|
|
723
|
+
}
|
|
724
|
+
|
|
718
725
|
return [
|
|
719
726
|
'// Generated by @ossy/app — do not edit',
|
|
720
727
|
'',
|
|
721
728
|
"import { createElement } from 'react'",
|
|
722
729
|
"import { hydrateRoot } from 'react-dom/client'",
|
|
723
730
|
"import { App } from '@ossy/connected-components'",
|
|
724
|
-
`import * as _page from './${rel}'`,
|
|
725
731
|
'',
|
|
726
|
-
'
|
|
727
|
-
'
|
|
732
|
+
'const config = window.__INITIAL_APP_CONFIG__ || {}',
|
|
733
|
+
'',
|
|
734
|
+
'const pages = {',
|
|
735
|
+
...pageLines,
|
|
736
|
+
'}',
|
|
728
737
|
'',
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
'
|
|
732
|
-
|
|
733
|
-
"
|
|
734
|
-
|
|
735
|
-
"
|
|
736
|
-
'
|
|
737
|
-
|
|
738
|
-
|
|
738
|
+
'const load = pages[config.pageId]',
|
|
739
|
+
'if (load) {',
|
|
740
|
+
' load().then((mod) => {',
|
|
741
|
+
' const Page = mod.default',
|
|
742
|
+
" const metadata = mod.metadata || {}",
|
|
743
|
+
' function PageShell (props) {',
|
|
744
|
+
" return createElement('html', { lang: props.defaultLanguage || 'en' },",
|
|
745
|
+
" createElement('head', null,",
|
|
746
|
+
" createElement('meta', { charSet: 'utf-8' }),",
|
|
747
|
+
" createElement('title', null, metadata.title || ''),",
|
|
748
|
+
' ),',
|
|
749
|
+
' createElement(App, props,',
|
|
750
|
+
' createElement(Page, props)',
|
|
751
|
+
' )',
|
|
739
752
|
' )',
|
|
740
|
-
'
|
|
741
|
-
'
|
|
742
|
-
'
|
|
753
|
+
' }',
|
|
754
|
+
' hydrateRoot(document, createElement(PageShell, config))',
|
|
755
|
+
' })',
|
|
743
756
|
'}',
|
|
744
757
|
'',
|
|
745
758
|
].join('\n')
|
|
746
759
|
}
|
|
747
760
|
|
|
748
|
-
/** Writes `hydrate
|
|
749
|
-
export function
|
|
761
|
+
/** Writes a single `hydrate-entry.jsx`; removes any stale per-page `hydrate-*.jsx` stubs first. */
|
|
762
|
+
export function writeHydrateEntry (pageFiles, srcDir, ossyDir) {
|
|
750
763
|
if (!fs.existsSync(ossyDir)) fs.mkdirSync(ossyDir, { recursive: true })
|
|
751
764
|
for (const ent of fs.readdirSync(ossyDir, { withFileTypes: true })) {
|
|
752
|
-
|
|
753
|
-
if (ent.isDirectory() && ent.name.startsWith(HYDRATE_STUB_PREFIX)) {
|
|
754
|
-
fs.rmSync(full, { recursive: true, force: true })
|
|
755
|
-
} else if (
|
|
765
|
+
if (
|
|
756
766
|
ent.isFile() &&
|
|
757
|
-
ent.name.startsWith(
|
|
758
|
-
ent.name.endsWith(
|
|
767
|
+
ent.name.startsWith('hydrate-') &&
|
|
768
|
+
ent.name.endsWith('.jsx') &&
|
|
769
|
+
ent.name !== HYDRATE_ENTRY_FILENAME
|
|
759
770
|
) {
|
|
760
|
-
fs.rmSync(
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
const seenIds = new Set()
|
|
764
|
-
for (const f of pageFiles) {
|
|
765
|
-
const hydrateId = clientHydrateIdForPage(f, srcDir)
|
|
766
|
-
if (seenIds.has(hydrateId)) {
|
|
767
|
-
throw new Error(
|
|
768
|
-
`[@ossy/app] Duplicate client hydrate id "${hydrateId}" (${f}). Per-page hydrate bundles need unique ids.`
|
|
769
|
-
)
|
|
771
|
+
fs.rmSync(path.join(ossyDir, ent.name), { force: true })
|
|
770
772
|
}
|
|
771
|
-
seenIds.add(hydrateId)
|
|
772
|
-
const stubPath = path.join(ossyDir, `${HYDRATE_STUB_PREFIX}${hydrateId}${HYDRATE_STUB_SUFFIX}`)
|
|
773
|
-
fs.mkdirSync(path.dirname(stubPath), { recursive: true })
|
|
774
|
-
fs.writeFileSync(
|
|
775
|
-
stubPath,
|
|
776
|
-
generatePageHydrateModule({ pageAbsPath: f, stubAbsPath: stubPath, srcDir })
|
|
777
|
-
)
|
|
778
773
|
}
|
|
774
|
+
const stubPath = path.join(ossyDir, HYDRATE_ENTRY_FILENAME)
|
|
775
|
+
fs.writeFileSync(stubPath, generateHydrateEntry({ pageFiles, srcDir, stubAbsPath: stubPath }))
|
|
779
776
|
}
|
|
780
777
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
const hydrateId = clientHydrateIdForPage(f, srcDir)
|
|
785
|
-
const stubPath = path.join(ossyDir, `${HYDRATE_STUB_PREFIX}${hydrateId}${HYDRATE_STUB_SUFFIX}`)
|
|
786
|
-
input[hydrateEntryName(hydrateId)] = stubPath
|
|
787
|
-
}
|
|
788
|
-
return input
|
|
778
|
+
/** Returns a single-entry input map pointing at the shared hydrate entry. */
|
|
779
|
+
export function buildClientHydrateInput (_pageFiles, _srcDir, ossyDir) {
|
|
780
|
+
return { app: path.join(ossyDir, HYDRATE_ENTRY_FILENAME) }
|
|
789
781
|
}
|
|
790
782
|
|
|
791
783
|
/** JSON manifest: route ids, default paths, and page source paths (posix, relative to `cwd`). */
|
|
@@ -936,7 +928,7 @@ export const build = async (cliArgs) => {
|
|
|
936
928
|
srcDir,
|
|
937
929
|
pagesGeneratedPath,
|
|
938
930
|
})
|
|
939
|
-
|
|
931
|
+
writeHydrateEntry(pageFiles, srcDir, ossyDir)
|
|
940
932
|
writePageSsrStubs(pageFiles, srcDir, ossyDir)
|
|
941
933
|
const clientHydrateInput = buildClientHydrateInput(pageFiles, srcDir, ossyDir)
|
|
942
934
|
|
|
@@ -955,7 +947,7 @@ export const build = async (cliArgs) => {
|
|
|
955
947
|
? configPath
|
|
956
948
|
: path.resolve(scriptDir, 'default-config.js')
|
|
957
949
|
|
|
958
|
-
const useDashboard =
|
|
950
|
+
const useDashboard = pageFiles.length > 0
|
|
959
951
|
const overviewSnap = getBuildOverviewSnapshot({
|
|
960
952
|
pagesSourcePath: pagesGeneratedPath,
|
|
961
953
|
apiOverviewFiles,
|
|
@@ -1023,8 +1015,9 @@ export const build = async (cliArgs) => {
|
|
|
1023
1015
|
try {
|
|
1024
1016
|
await prerenderReactTask.handler({
|
|
1025
1017
|
op: 'runProduction',
|
|
1026
|
-
clientHydrateInput,
|
|
1018
|
+
hydrateEntryPath: clientHydrateInput.app,
|
|
1027
1019
|
pageFilesLength: pageFiles.length,
|
|
1020
|
+
pageIds,
|
|
1028
1021
|
copyPublicFrom: publicDir,
|
|
1029
1022
|
buildPath,
|
|
1030
1023
|
nodeEnv: 'production',
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import { rollup } from 'rollup'
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
export function staticHtmlPathForRoute (routePath, publicDir) {
|
|
6
|
+
const segments = routePath === '/' ? [] : routePath.replace(/^\//, '').split('/')
|
|
7
|
+
return path.join(publicDir, ...segments, 'index.html')
|
|
8
|
+
}
|
|
5
9
|
|
|
6
10
|
function copyPublicToBuild ({ copyPublicFrom, buildPath }) {
|
|
7
11
|
if (!copyPublicFrom || !fs.existsSync(copyPublicFrom)) return
|
|
@@ -10,31 +14,22 @@ function copyPublicToBuild ({ copyPublicFrom, buildPath }) {
|
|
|
10
14
|
fs.cpSync(copyPublicFrom, dest, { recursive: true })
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
async function
|
|
14
|
-
|
|
15
|
-
stubPath,
|
|
17
|
+
async function bundleHydrateEntry ({
|
|
18
|
+
entryPath,
|
|
16
19
|
buildPath,
|
|
17
20
|
plugins,
|
|
18
21
|
minifyPlugin,
|
|
19
22
|
}) {
|
|
20
23
|
const bundle = await rollup({
|
|
21
|
-
input: {
|
|
24
|
+
input: { app: entryPath },
|
|
22
25
|
plugins,
|
|
23
26
|
})
|
|
24
27
|
try {
|
|
25
28
|
await bundle.write({
|
|
26
29
|
dir: path.join(buildPath, 'public'),
|
|
27
30
|
format: 'esm',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const n = chunkInfo.name
|
|
31
|
-
if (n.startsWith('hydrate__')) {
|
|
32
|
-
const pageId = n.slice('hydrate__'.length)
|
|
33
|
-
return `static/${pageId}.js`
|
|
34
|
-
}
|
|
35
|
-
return 'static/[name].js'
|
|
36
|
-
},
|
|
37
|
-
chunkFileNames: 'static/[name]-[hash].js',
|
|
31
|
+
entryFileNames: 'static/[name].js',
|
|
32
|
+
chunkFileNames: 'static/chunks/[name]-[hash].js',
|
|
38
33
|
plugins: minifyPlugin ? [minifyPlugin] : [],
|
|
39
34
|
})
|
|
40
35
|
} finally {
|
|
@@ -42,100 +37,58 @@ async function bundleOneHydratePage ({
|
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
clientHydrateInput,
|
|
63
|
-
buildPath,
|
|
64
|
-
copyPublicFrom,
|
|
65
|
-
nodeEnv,
|
|
66
|
-
buildPathForPlugins,
|
|
67
|
-
createClientRollupPlugins,
|
|
68
|
-
minifyBrowserStaticChunks,
|
|
69
|
-
reporter,
|
|
70
|
-
}) {
|
|
71
|
-
copyPublicToBuild({ copyPublicFrom, buildPath })
|
|
72
|
-
fs.mkdirSync(path.join(buildPath, 'public', 'static'), { recursive: true })
|
|
40
|
+
export default {
|
|
41
|
+
type: '@ossy/app/prerender-react',
|
|
42
|
+
async handler (input) {
|
|
43
|
+
const op = input?.op
|
|
44
|
+
if (op === 'runProduction') {
|
|
45
|
+
const {
|
|
46
|
+
hydrateEntryPath,
|
|
47
|
+
pageFilesLength,
|
|
48
|
+
pageIds,
|
|
49
|
+
copyPublicFrom,
|
|
50
|
+
buildPath,
|
|
51
|
+
nodeEnv,
|
|
52
|
+
buildPathForPlugins,
|
|
53
|
+
createClientRollupPlugins,
|
|
54
|
+
minifyBrowserStaticChunks,
|
|
55
|
+
reporter,
|
|
56
|
+
} = input
|
|
73
57
|
|
|
74
|
-
|
|
58
|
+
if (pageFilesLength === 0 || !hydrateEntryPath) {
|
|
59
|
+
return { bundleFailures: 0 }
|
|
60
|
+
}
|
|
75
61
|
|
|
76
|
-
|
|
62
|
+
copyPublicToBuild({ copyPublicFrom, buildPath })
|
|
63
|
+
fs.mkdirSync(path.join(buildPath, 'public', 'static'), { recursive: true })
|
|
64
|
+
fs.mkdirSync(path.join(buildPath, 'public', 'static', 'chunks'), { recursive: true })
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
entries,
|
|
80
|
-
BUNDLE_CONCURRENCY,
|
|
81
|
-
async ([entryName, stubPath]) => {
|
|
82
|
-
const pageId = pageIdFromHydrateEntryName(entryName)
|
|
66
|
+
const ids = pageIds || []
|
|
83
67
|
const t0 = Date.now()
|
|
84
|
-
reporter?.startBundle?.(
|
|
68
|
+
for (const id of ids) reporter?.startBundle?.(id)
|
|
69
|
+
|
|
85
70
|
try {
|
|
86
71
|
const plugins = createClientRollupPlugins({
|
|
87
72
|
nodeEnv,
|
|
88
73
|
copyPublicFrom: undefined,
|
|
89
|
-
buildPath: buildPathForPlugins,
|
|
74
|
+
buildPath: buildPathForPlugins ?? buildPath,
|
|
90
75
|
})
|
|
91
|
-
await
|
|
92
|
-
|
|
93
|
-
stubPath,
|
|
76
|
+
await bundleHydrateEntry({
|
|
77
|
+
entryPath: hydrateEntryPath,
|
|
94
78
|
buildPath,
|
|
95
79
|
plugins,
|
|
96
80
|
minifyPlugin: minifyBrowserStaticChunks(),
|
|
97
81
|
})
|
|
98
|
-
|
|
82
|
+
const ms = Date.now() - t0
|
|
83
|
+
for (const id of ids) reporter?.completeBundle?.(id, { ok: true, ms })
|
|
99
84
|
} catch (error) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
error,
|
|
104
|
-
})
|
|
105
|
-
console.error(`[@ossy/app][client-bundle] ${entryName} failed:`, error)
|
|
85
|
+
const ms = Date.now() - t0
|
|
86
|
+
for (const id of ids) reporter?.completeBundle?.(id, { ok: false, ms, error })
|
|
87
|
+
console.error(`[@ossy/app][client-bundle] hydrate-entry failed:`, error)
|
|
106
88
|
throw error
|
|
107
89
|
}
|
|
108
|
-
},
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
const failures = results.filter((r) => r.status === 'rejected').length
|
|
112
|
-
return { results, failures }
|
|
113
|
-
}
|
|
114
90
|
|
|
115
|
-
|
|
116
|
-
type: '@ossy/app/prerender-react',
|
|
117
|
-
async handler (input) {
|
|
118
|
-
const op = input?.op
|
|
119
|
-
if (op === 'runProduction') {
|
|
120
|
-
const { clientHydrateInput, pageFilesLength, copyPublicFrom, buildPath, nodeEnv,
|
|
121
|
-
buildPathForPlugins, createClientRollupPlugins, minifyBrowserStaticChunks, reporter } = input
|
|
122
|
-
if (pageFilesLength === 0 || Object.keys(clientHydrateInput).length === 0) {
|
|
123
|
-
return { bundleFailures: 0 }
|
|
124
|
-
}
|
|
125
|
-
const { failures: bundleFailures } = await bundleHydratePagesParallel({
|
|
126
|
-
clientHydrateInput,
|
|
127
|
-
buildPath,
|
|
128
|
-
copyPublicFrom,
|
|
129
|
-
nodeEnv,
|
|
130
|
-
buildPathForPlugins: buildPathForPlugins ?? buildPath,
|
|
131
|
-
createClientRollupPlugins,
|
|
132
|
-
minifyBrowserStaticChunks,
|
|
133
|
-
reporter,
|
|
134
|
-
})
|
|
135
|
-
if (bundleFailures > 0) {
|
|
136
|
-
console.warn(`[@ossy/app][build] Finished with ${bundleFailures} client bundle error(s)`)
|
|
137
|
-
}
|
|
138
|
-
return { bundleFailures }
|
|
91
|
+
return { bundleFailures: 0 }
|
|
139
92
|
}
|
|
140
93
|
throw new Error(
|
|
141
94
|
`[@ossy/app][prerender-react] Unknown op: ${String(op)} (expected runProduction)`
|
package/cli/render-page.task.js
CHANGED
|
@@ -36,6 +36,7 @@ export function buildPrerenderAppConfig ({
|
|
|
36
36
|
workspaceId: buildTimeConfig.workspaceId,
|
|
37
37
|
apiUrl: buildTimeConfig.apiUrl,
|
|
38
38
|
pages,
|
|
39
|
+
pageId: activeRouteId,
|
|
39
40
|
sidebarPrimaryCollapsed: false,
|
|
40
41
|
}
|
|
41
42
|
}
|
|
@@ -61,12 +62,12 @@ export function buildHydrationAppConfig (appConfig) {
|
|
|
61
62
|
|
|
62
63
|
export const BuildPage = {
|
|
63
64
|
async handle ({ route, appConfig }) {
|
|
64
|
-
const hydrationConfig = buildHydrationAppConfig(appConfig)
|
|
65
|
+
const hydrationConfig = { ...buildHydrationAppConfig(appConfig), pageId: route.id }
|
|
65
66
|
const { renderPage } = await loadSsrBundle(route)
|
|
66
67
|
|
|
67
68
|
return renderPage(hydrationConfig, {
|
|
68
69
|
bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__=${JSON.stringify(hydrationConfig)}`,
|
|
69
|
-
bootstrapModules: [
|
|
70
|
+
bootstrapModules: ['/static/app.js'],
|
|
70
71
|
})
|
|
71
72
|
},
|
|
72
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"@babel/eslint-parser": "^7.15.8",
|
|
28
28
|
"@babel/preset-react": "^7.26.3",
|
|
29
29
|
"@babel/register": "^7.25.9",
|
|
30
|
-
"@ossy/connected-components": "^1.13.
|
|
31
|
-
"@ossy/design-system": "^1.13.
|
|
32
|
-
"@ossy/pages": "^1.13.
|
|
33
|
-
"@ossy/router": "^1.13.
|
|
34
|
-
"@ossy/router-react": "^1.13.
|
|
35
|
-
"@ossy/sdk": "^1.13.
|
|
36
|
-
"@ossy/sdk-react": "^1.13.
|
|
37
|
-
"@ossy/themes": "^1.13.
|
|
30
|
+
"@ossy/connected-components": "^1.13.3",
|
|
31
|
+
"@ossy/design-system": "^1.13.3",
|
|
32
|
+
"@ossy/pages": "^1.13.3",
|
|
33
|
+
"@ossy/router": "^1.13.3",
|
|
34
|
+
"@ossy/router-react": "^1.13.3",
|
|
35
|
+
"@ossy/sdk": "^1.13.3",
|
|
36
|
+
"@ossy/sdk-react": "^1.13.3",
|
|
37
|
+
"@ossy/themes": "^1.13.3",
|
|
38
38
|
"@rollup/plugin-alias": "^6.0.0",
|
|
39
39
|
"@rollup/plugin-babel": "6.1.0",
|
|
40
40
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"README.md",
|
|
68
68
|
"tsconfig.json"
|
|
69
69
|
],
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "0d5eae5748fb9a32e5dcb147444b7e9a8113dcba"
|
|
71
71
|
}
|