egg-serlina is a Serlina binding for Egg. It brings the best SSR solution to Egg application.
$ npm i serlina egg-serlina react react-dom --save
Enable the plugin:
// {app_root}/config/plugin.js
exports.serlina = {
enable: true,
package: 'egg-serlina',
};
Add a client
folder and create the first page:
- app_root
- app
+ - client
+ - pages
+ - page1.js
// {app_root}/client/pages/page1.js
export default () => {
return <div>Hello Serlina</div>
}
// {app_root}/config/config.default.js
exports.serlina = {
map: {
'/page1': 'page1'
}
}
Then visit http://{your_host}/page1
and you will see the React page.
Please note that the egg
ctx
had been injected to your page:
// {app_root}/client/pages/page1.js
export default class Page1 extends React.Component {
static async getInitialProps({ ctx }) {
// ctx is egg `ctx`
return {
data: await ctx.service.getDate()
}
}
render () {
return (
<div>{this.props.data}</div>
)
}
}
You can also render your page manually in controller:
// app/controller/page1.js
module.exports = async ctx => {
const rendered = await ctx.app.serlina.render('/page1', { ctx })
}
Remember to inject your
ctx
if you need it ingetInitialProps
.
boolean dev mode.
default: appInfo.env === 'local'
string Serlina baseDir.
default: path.resolve(appInfo.baseDir, './client')
string Serlina output files path.
string Webpack's publicPath. Only work in prod
mode. Usually use it when you upload the Serlina output files to CDN.
default: /public/
object Using Serlina only in specific path:
exports.serlina = {
map: {
'/p/page1': 'page1' // render SSR page `page1` only when the `ctx.path` is `/p/page1`
}
}
see config/config.default.js for more detail.
Before deploy to production, please run serlina build
first (usually do it on CI):
// ${app_root}/package.json
{
"script": {
"build": "serlina build ./client --publicPath /public/"
}
}
Then you need to serve the output path:
// {app_root}/config/config.default.js
exports.static = {
dir: [
path.join(appInfo.baseDir, 'app/public'),
path.join(appInfo.baseDir, 'client/.serlina')
]
};
// ${app_root}/package.json
{
"script": {
"build": "serlina build ./client --publicPath ${YOUR_CDN_ENDPOINT}"
}
}
// {app_root}/config/config.default.js
exports.serlina = {
publicPath: '${YOUR_CND_ENDPOINT}'
};
While Egg will restart a new worker after file changing, Serlina will restart building. Maybe it will be frustrating when the client code getting bigger. PR is welcome if you know how to deal with this problem.