UNPKG

3.31 kBJavaScriptView Raw
1"use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var fsExtra=require("fs-extra"),path=require("path"),express=_interopDefault(require("express")),fs=require("fs"),fs__default=_interopDefault(fs),template=_interopDefault(require("art-template")),React=_interopDefault(require("react")),server=require("react-dom/server"),delay=_interopDefault(require("delay")),webpack=_interopDefault(require("webpack")),TerserPlugin=_interopDefault(require("terser-webpack-plugin"));const cwd=process.cwd(),isProd="production"===process.env.NODE_ENV;var configure=(e,t)=>{const r={test:/\.(js|ts)x?$/,exclude:/node_modules/,use:{loader:"babel-loader",options:{}}};if(fs.existsSync(path.resolve(cwd,".babelrc"))||fs.existsSync(path.resolve(cwd,".babelrc.js"))||fs.existsSync(path.resolve(cwd,"babel.config.js"))){const e=(()=>fs.existsSync(path.resolve(cwd,".babelrc"))?path.resolve(cwd,".babelrc"):fs.existsSync(path.resolve(cwd,".babelrc.js"))?path.resolve(cwd,".babelrc.js"):path.resolve(cwd,"babel.config.js"))();isProd||console.log("[react-ssr] Babelrc in: "+e),r.use.options={extends:e}}else r.use.options={presets:["@react-ssr/express-engine-jsx/babel"]};const s={mode:isProd?"production":"development",context:cwd,entry:{[e]:"./react-ssr-src/entry.js"},output:{path:path.resolve(cwd,t),filename:"[name].js"},resolve:{extensions:[".js",".jsx",".ts",".tsx"]},module:{rules:[r]}};return isProd&&(s.optimization={minimizer:[new TerserPlugin]}),s};const Html=e=>React.createElement("html",null,React.createElement("body",null,React.createElement("div",{id:"app"},e.children),React.createElement("script",{src:`/${e.script}`})));template.defaults.minimize=!1;const getPagePath=(e,t)=>e.split(path.sep+t.viewsDir+path.sep)[1],waitUntilBuilt=async(e,t)=>{for(;!t.existsSync(e);)await delay(30)},MemoryFileSystem=require("memory-fs"),render=async(e,t,r)=>{let s="<!DOCTYPE html>";const a=process.cwd(),i=t.distDir,l=getPagePath(e,t),c=path.resolve(a,i,l.replace(".jsx",".html"));if(fsExtra.existsSync(c))return fsExtra.readFileSync(c).toString();const n=path.basename(l).replace(".jsx",""),o=webpack(configure(n,i)),p=new MemoryFileSystem,{ufs:u}=require("unionfs");u.use(p).use(fs__default),p.mkdirpSync(path.resolve(a,"react-ssr-src")),p.writeFileSync(path.resolve(a,"react-ssr-src/entry.js"),template(path.resolve(__dirname,"page.jsx"),{props:r})),p.writeFileSync(path.resolve(a,"react-ssr-src/page.js"),template(e,r)),o.inputFileSystem=u,o.outputFileSystem=p;try{o.run(e=>{if(e)return console.error(e.stack||e),void(e.details&&console.error(e.details))});const t=path.resolve(a,i,l).replace(".jsx",".js");await waitUntilBuilt(t,p),await fsExtra.outputFileSync(t,p.readFileSync(t).toString());let c=require(e);return c=c.default||c,s+=server.renderToString(React.createElement(Html,{script:l.replace(".jsx",".js")},React.createElement(c,r)))}finally{}},register=async(e,t)=>{require("@babel/register")();const r=process.cwd(),s=t.distDir,a=t.viewsDir;"BUILD"===process.env.REACT_SSR&&await fsExtra.remove(s);e.engine("jsx",async(e,r,s)=>{try{const a=r;return delete a.settings,delete a._locals,delete a.cache,s(null,await render(e,t,a))}catch(e){return s(e)}}),e.set("views",path.resolve(r,a)),e.set("view engine","jsx"),e.use(express.static(s))};module.exports=register;