Skip to content

Commit 83ddc61

Browse files
committed
implement server-side rendering
1 parent 30ad220 commit 83ddc61

11 files changed

+139
-18
lines changed

src/main/java/daggerok/ReactSpringBootApplication.java renamed to src/main/java/daggerok/ReactServerSideRenderingSpringBootApplication.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55

66
@SpringBootApplication
7-
public class ReactSpringBootApplication {
7+
public class ReactServerSideRenderingSpringBootApplication {
88

99
public static void main(String[] args) {
10-
SpringApplication.run(ReactSpringBootApplication.class, args);
10+
SpringApplication.run(ReactServerSideRenderingSpringBootApplication.class, args);
1111
}
1212
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package daggerok.react;
2+
3+
import jdk.nashorn.api.scripting.NashornScriptEngine;
4+
import lombok.SneakyThrows;
5+
import lombok.val;
6+
import org.springframework.stereotype.Component;
7+
8+
import javax.annotation.PostConstruct;
9+
import javax.script.ScriptEngineManager;
10+
import java.io.InputStreamReader;
11+
import java.io.Reader;
12+
13+
/**
14+
* Created by mak on 9/7/16.
15+
*/
16+
@Component
17+
public class React {
18+
19+
private ThreadLocal<NashornScriptEngine> engineHolder;
20+
21+
@PostConstruct
22+
public void init() {
23+
24+
val nashornScriptEngine = (NashornScriptEngine) new ScriptEngineManager().getEngineByName("nashorn");
25+
26+
engineHolder = new ThreadLocal<NashornScriptEngine>() {
27+
@Override @SneakyThrows
28+
protected NashornScriptEngine initialValue() {
29+
nashornScriptEngine.eval(read("nashorn/polyfill.js"));
30+
nashornScriptEngine.eval(read("static/app.js"));
31+
return nashornScriptEngine;
32+
}
33+
};
34+
}
35+
36+
@SneakyThrows
37+
public String renderApp() {
38+
39+
val html = engineHolder.get().invokeFunction("renderServer");
40+
41+
return String.valueOf(html);
42+
}
43+
44+
@SneakyThrows
45+
private Reader read(String path) {
46+
47+
val resource = getClass().getClassLoader().getResourceAsStream(path);
48+
49+
return new InputStreamReader(resource);
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package daggerok.react;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.stereotype.Controller;
5+
import org.springframework.ui.Model;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
8+
/**
9+
* Created by mak on 9/7/16.
10+
*/
11+
@Controller
12+
public class ReactServerSideRenderingController {
13+
14+
@Autowired React react;
15+
16+
@GetMapping("/")
17+
public String index(Model model) {
18+
model.addAttribute("data", react.renderApp());
19+
return "index";
20+
}
21+
}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var window = this;
2+
var global = this;
3+
var console = {};
4+
5+
console.error = print;
6+
console.debug = print;
7+
console.warn = print;
8+
console.info = print;
9+
console.log = print;
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>fast-react-starter</title>
6+
<link href="/app.css" rel="stylesheet"></head>
7+
<body>
8+
<!-- 1) render data from backend server side (see daggerok.react.ReactServerSideRenderingController.index) -->
9+
<div id="app">{{{data}}}</div>
10+
<script type="text/javascript" src="/app.js"></script>
11+
<!-- 2) up and running dynamic part of site after it static initial page pf app was loader -->
12+
<script type="text/javascript">
13+
$(function() {
14+
renderClient();
15+
});
16+
</script>
17+
</body>
18+
</html>

src/test/java/daggerok/ReactSpringBootApplicationTests.java renamed to src/test/java/daggerok/ReactServerSideRenderingSpringBootApplicationTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
@SpringBootTest
99
@RunWith(SpringRunner.class)
10-
public class ReactSpringBootApplicationTests {
10+
public class ReactServerSideRenderingSpringBootApplicationTests {
1111

1212
@Test
1313
public void contextLoads() {}

ui/config/webpack.config.babel.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ const assetsInclude = [path.resolve(process.cwd(), './src/assets')];
1111
const bsInclude = [path.resolve(process.cwd(), './node_modules/bootstrap/dist')];
1212
const config = {
1313
entry: {
14-
app: ['babel-polyfill', './src/main.js']
14+
app: './src/main.js'
1515
},
1616
output: {
1717
path: '../src/main/resources/static',
18-
filename: '/[name].[hash].js',
18+
filename: '/[name].js',
1919
sourceMapFilename: 'maps/[file].map'
2020
},
2121
module: {
@@ -73,7 +73,7 @@ const config = {
7373
modulesDirectories: ['node_modules']
7474
},
7575
plugins: [
76-
new ExtractPlugin('/[name].[hash].css', { allChunks: true }),
76+
new ExtractPlugin('/[name].css', { allChunks: true }),
7777
new HtmlWebpackPlugin({ template: './src/assets/index.hbs' })
7878
],
7979
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ],

ui/config/webpack.config.production.babel.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import config from './webpack.config.babel';
55
import webpack from 'webpack';
66

7-
config.devtool = '#source-map';
7+
// config.devtool = '#source-map';
8+
config.devtool = false;
89
config.plugins = [
910
...config.plugins,
1011
new webpack.DefinePlugin({

ui/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
"webpack-dev-server": "*"
5959
},
6060
"dependencies": {
61-
"babel-polyfill": "*",
6261
"bootstrap": "*",
62+
"jquery": "*",
6363
"react": "*",
6464
"react-dom": "*",
6565
"react-router": "*"

ui/src/assets/index.hbs

+7
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,12 @@
66
</head>
77
<body>
88
<div id="app"></div>
9+
<!--
10+
<script type="text/javascript">
11+
$(function () {
12+
renderClient();
13+
});
14+
</script>
15+
-->
916
</body>
1017
</html>

ui/src/main.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,27 @@ class App extends Component {
4040
}
4141
}
4242

43-
render(
44-
<Router history={browserHistory}>
45-
<Route path="/" component={App}>
46-
<IndexRoute component={Main}/>
47-
<Route path="home" component={Main}/>
48-
<Route path="*" component={NotFound}/>
49-
</Route>
50-
</Router>,
51-
document.getElementById('app')
52-
);
43+
window.renderClient = function() {
44+
// const renderClient = (comments) => {
45+
// const data = comments || [];
46+
return render(
47+
<Router history={browserHistory}>
48+
<Route path="/" component={App}>
49+
<IndexRoute component={Main}/>
50+
<Route path="home" component={Main}/>
51+
<Route path="*" component={NotFound}/>
52+
</Route>
53+
</Router>,
54+
document.getElementById('app')
55+
);
56+
};
57+
58+
import { renderToString } from 'react-dom/server'
59+
window.renderServer = function() {
60+
// const renderServer = (comments) => {
61+
// const data = Java.from(comments);
62+
return renderToString(<App><NotFound/></App>);
63+
};
64+
65+
import $ from 'jquery';
66+
window.$ = $;

0 commit comments

Comments
 (0)