Skip to content

Commit

Permalink
feat(packages/sui-ssr): add ssr dev mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrés Alvarez authored and Andrés Alvarez committed Dec 13, 2023
1 parent 99e46ad commit bb2db70
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 3 deletions.
155 changes: 155 additions & 0 deletions packages/sui-ssr/bin/sui-ssr-dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env node
/* eslint-disable no-console */

const {WEBPACK_PORT = 8080} = process.env
process.env.CDN = `http://localhost:${WEBPACK_PORT}/`

const program = require('commander')
const {exec} = require('child_process')
const path = require('path')
const fs = require('fs')
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const nodemon = require('nodemon')
const clientConfig = require('@s-ui/bundler/webpack.config.server.dev.js')
const linkLoaderConfigBuilder = require('@s-ui/bundler/loaders/linkLoaderConfigBuilder.js')

const serverConfigFactory = require('../compiler/server.js')

const SERVER_OUTPUT_PATH = path.join(process.cwd(), '.sui/server')
const STATICS_OUTPUT_PATH = path.join(process.cwd(), '.sui/statics')
const STATICS_PATH = path.join(process.cwd(), './statics')

program
.option('-L, --link-all [monorepo]', 'Link all packages inside of monorepo multipackage')
.option(
'-l, --link-package [package]',
'Replace each occurrence of this package with an absolute path to this folder',
(v, m) => {
m.push(v)
return m
},
[]
)
.parse(process.argv)

const compile = (name, compiler) => {
return new Promise((resolve, reject) => {
compiler.hooks.compile.tap(name, () => {
console.time(`[${name}] Compiling`)
})
compiler.hooks.done.tap(name, stats => {
console.timeEnd(`[${name}] Compiling`)
if (!stats.hasErrors()) {
return resolve()
}
return reject(new Error(`Failed to compile ${name}`))
})
})
}

const linkStatics = () => {
return new Promise((resolve, reject) =>
fs.symlink(STATICS_PATH, STATICS_OUTPUT_PATH, 'dir', err => {
if (err) {
if (err.code === 'EEXIST') {
return resolve()
}

return reject(err)
}

resolve()
})
)
}

const initMSW = () => {
return exec(`npx msw init ${STATICS_PATH}`)
}

const start = ({packagesToLink, linkAll}) => {
const app = express()
const clientCompiler = webpack(
linkLoaderConfigBuilder({
config: require('@s-ui/bundler/webpack.config.server.dev.js'),
linkAll,
packagesToLink
})
)
const serverCompiler = webpack(
linkLoaderConfigBuilder({
config: serverConfigFactory({outputPath: SERVER_OUTPUT_PATH}),
linkAll,
packagesToLink
})
)
const watchOptions = {
ignored: /node_modules/,
stats: clientConfig.stats
}

app.use((_req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
return next()
})

app.use(
webpackDevMiddleware(clientCompiler, {
publicPath: clientConfig.output.publicPath,
stats: clientConfig.stats,
writeToDisk: true
})
)
app.use(webpackHotMiddleware(clientCompiler))

app.listen(WEBPACK_PORT)

serverCompiler.watch(watchOptions, (error, stats) => {
if (!error && !stats.hasErrors()) {
return
}

if (error) {
console.log(error, 'error')
}

if (stats.hasErrors()) {
const info = stats.toJson()
const errors = info.errors

console.log(errors)
}
})

Promise.all([linkStatics(), initMSW(), compile('client', clientCompiler), compile('server', serverCompiler)])
.then(() => {
const script = nodemon({
script: `${SERVER_OUTPUT_PATH}/index.js`,
watch: [SERVER_OUTPUT_PATH],
delay: 200
})

script.on('restart', () => {
console.log('Server side app has been restarted.', 'warning')
})

script.on('quit', () => {
console.log('Process ended')
process.exit()
})

script.on('error', () => {
console.log('An error occured. Exiting', 'error')
process.exit(1)
})
})
.catch(error => {
console.log('error', error)
})
}
const opts = program.opts()

start({packagesToLink: opts.linkPackage, linkAll: opts.linkAll})
5 changes: 4 additions & 1 deletion packages/sui-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"mime": "1.6.0",
"noop-console": "0.8.0",
"parse5": "6.0.1",
"ua-parser-js": "0.7.33"
"ua-parser-js": "0.7.33",
"webpack-dev-middleware": "6.1.1",
"webpack-hot-middleware": "2.25.4",
"nodemon": "3.0.1"
}
}
5 changes: 3 additions & 2 deletions packages/sui-ssr/server/utils/factory.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const IS_PRODUCTION = process.env.NODE_ENV === 'production'
const DEFAULT_SITE_HEADER = 'X-Serve-Site'
const DEFAULT_PUBLIC_FOLDER = 'public'
const DEFAULT_PUBLIC_FOLDER = IS_PRODUCTION ? 'public' : '.sui/public'
const DEFAULT_MULTI_SITE_KEY = 'default'
const EXPRESS_STATIC_CONFIG = {index: false}

Expand Down Expand Up @@ -29,7 +30,7 @@ export default ({path, fs, config: ssrConf = {}, assetsManifest}) => {

const publicFolder = req => {
const site = siteByHost(req)
if (!site) return DEFAULT_PUBLIC_FOLDER
if (!site || !IS_PRODUCTION) return DEFAULT_PUBLIC_FOLDER

return multiSitePublicFolder(site)
}
Expand Down

0 comments on commit bb2db70

Please sign in to comment.