/
DevMiddleware.js
85 lines (71 loc) · 2.45 KB
/
DevMiddleware.js
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
import path from 'path';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import getFilenameFromUrl from 'webpack-dev-middleware/lib/GetFilenameFromUrl';
import webpackHotMiddleware from 'webpack-hot-middleware';
import cheerio from 'cheerio';
import webpackConfig from '../../../../shared/webpack/webpack.client';
import logger from '../../../../shared/logger';
import buildPage from './buildPage';
// TODO dllPlugin
// if (dllPlugin) {
// app.get(/\.dll\.js$/, (req, res) => {
// const filename = req.path.replace(/^\//, '');
// res.sendFile(path.join(process.cwd(), dllPlugin.path, filename));
// });
// }
export default class DevMiddleware {
constructor(app, config) {
this.app = app;
this.config = config;
this.compiler = webpack(webpackConfig);
this.middleware = webpackDevMiddleware(this.compiler, {
noInfo: true,
publicPath: config.publicPath,
silent: true,
stats: 'errors-only',
serverSideRender: true,
});
}
registerMiddlewares(renderRoute) {
const config = this.config;
const compiler = this.compiler;
const app = this.app;
if (config.prerendering) {
// Bypass serving index.html statically to enable server-side rendering.
this.app.use((req, res, next) => {
const fileName = getFilenameFromUrl(config.publicPath, compiler.outputPath, req.url);
if (!fileName) {
return next();
}
if (fileName === compiler.outputPath) {
return renderRoute(req, res, next);
}
next();
});
}
app.use(this.middleware);
app.use(webpackHotMiddleware(compiler, {
log: logger.info.bind(logger),
}));
}
serveRoute(req, res, html, appState) {
// Since webpackDevMiddleware uses memory-fs internally to store build
// artifacts, we use it instead
const fs = this.middleware.fileSystem;
fs.readFile(path.join(this.compiler.outputPath, 'index.html'), (err, file) => {
if (err) {
// TODO detech that the app is still building
return res.status(500).send('Missing file "index.html". Either the app is still building or something went wrong.');
}
// no server-side rendering
if (typeof html !== 'string') {
return res.send(file.toString());
}
// server-side rendering:
const $doc = cheerio(file.toString());
buildPage($doc, html, appState);
res.send($doc.toString());
});
}
}