-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
157 lines (134 loc) · 4.64 KB
/
index.js
File metadata and controls
157 lines (134 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* sails-hook-shipwright
*
* Modern asset pipeline for Sails.js, powered by Rsbuild.
*
* @see https://github.com/sailshq/sails-hook-shipwright
*/
const path = require('path')
const {
detectStylesEntry,
detectJsEntry,
expandEntryPatterns,
validatePlugins
} = require('./lib/entry')
const { createTagGenerators } = require('./lib/tags')
const { createLogger, randomQuote } = require('./lib/log')
const { createDefaultRsbuildConfig } = require('./lib/rsbuild-config')
module.exports = function defineShipwrightHook(sails) {
let log
let tagGenerators
return {
defaults: {
shipwright: {
styles: {},
js: {},
build: {}
}
},
/**
* Configure hook.
* Runs after defaults merge, before initialize.
* Detects entry points and validates plugins early.
*/
configure: function () {
log = createLogger(sails.log)
const { appPath } = sails.config
const config = sails.config.shipwright
config.styles.entry = detectStylesEntry(appPath, config.styles.entry)
config.js.entry = detectJsEntry(appPath, config.js.entry)
validatePlugins({ appPath, stylesEntry: config.styles.entry, log })
// Create tag generators early so other hooks can use them
tagGenerators = createTagGenerators(appPath, {
jsInject: config.js.inject,
cssInject: config.styles.inject
})
// Register view locals
sails.config.views = sails.config.views || {}
sails.config.views.locals = {
...sails.config.views.locals,
shipwright: tagGenerators
}
},
// Expose tag generators on hook for other hooks to use
scripts: (entryName) => tagGenerators?.scripts(entryName) || '',
styles: (entryName) => tagGenerators?.styles(entryName) || '',
/**
* Initialize hook.
* Starts Rsbuild build (production) or dev server (development).
*/
initialize: async function () {
if (sails.config.dontLift) {
log.verbose('Skipping build (dontLift)')
return
}
const { appPath } = sails.config
const config = sails.config.shipwright
// Build entry object - array patterns get expanded to file list
const entry = {}
const jsFiles = expandEntryPatterns(config.js.entry, appPath)
if (jsFiles?.length) {
entry.app = jsFiles
log.verbose('Bundling %d JS files', jsFiles.length)
} else if (config.js.entry && !Array.isArray(config.js.entry)) {
entry.app = [path.resolve(appPath, config.js.entry)]
log.verbose('Bundling %s', config.js.entry)
}
if (config.styles.entry) {
const stylesPath = path.resolve(appPath, config.styles.entry)
if (entry.app) {
// Bundle CSS with the JS entry so the chunk keeps a JS module map.
// CSS-only entries produce chunks with no JS modules, which crashes
// the HMR runtime in jsonp_chunk_loading when it tries to apply
// updates. The CSS extract plugin still outputs a separate CSS file.
entry.app.unshift(stylesPath)
} else {
entry.styles = stylesPath
}
log.verbose('Compiling %s', config.styles.entry)
}
log.silly('Preparing to set sail...')
if (!Object.keys(entry).length) {
log.verbose('No entry points found, skipping')
return
}
const { defineConfig, mergeRsbuildConfig, createRsbuild } =
await import('@rsbuild/core')
const defaultConfig = defineConfig(
createDefaultRsbuildConfig({
appPath,
entry,
port: sails.config.port
})
)
const rsbuildConfig = mergeRsbuildConfig(defaultConfig, config.build)
try {
const rsbuild = await createRsbuild({ rsbuildConfig })
if (process.env.NODE_ENV === 'production') {
log.silly('Building for production...')
await rsbuild.build()
log.verbose('Build complete ⚓')
log.silly('🚢 %s', randomQuote())
} else {
const devServer = await rsbuild.createDevServer()
sails.after('hook:http:loaded', () => {
sails.hooks.http.app.use(devServer.middlewares)
devServer.connectWebSocket({ server: sails.hooks.http.server })
})
sails.on('lifted', () => {
devServer.afterListen()
log.verbose('Dev server ready ⚓')
log.silly('🚢 %s', randomQuote())
})
sails.on('lower', () => {
devServer.close()
log.silly('Dropping anchor... goodbye!')
})
}
} catch (error) {
log.error('Build failed')
log.error(error)
}
}
}
}