Nachdem ich GraalJS berührt habe, werde ich SSR ausprobieren. Ich hoffe, es ist hilfreich für Leute, die SSR auch in Java wollen.
GraalVM ist eine VM, auf der JVM, JavaScript, Python, Ruby usw. ausgeführt werden können. GraalJS soll die Leistung optimieren, indem es in der GraalVM-Umgebung (vom Beamten) ausgeführt wird. Da es jedoch in Java geschrieben ist, handelt es sich um eine normale JVM Aber es ist möglich zu bedienen. Dieses Mal möchte ich SSR mit GraalJS mit JVM ausprobieren.
Ich werde die Einstellungen auf der JS-Seite nicht im Detail erläutern, sondern die JS-Dateien auf der Serverseite und der Clientseite mit einem Webpack gemäß dem VueSSR-Handbuch vorbereiten.
javascript:webpack.config.js
node: {
child_process: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
},
Fügen Sie das Obige hinzu, um auf der Serverseite zu arbeiten.
Laden Sie in der Java-App den Vue-Server-Renderer und die Bundle-Datei und lassen Sie sie den HTML-Code zeichnen.
entry-server.js
import { createApp } from './app'
const { app, router, store } = createApp()
router.push(route)
router.onReady(() => {
renderVueComponentToString(app, (err, res) => {
rendered = String(res)
})
})
Ich schreibe einen Prozess, um den von renderVueComponentToString erfassten HTML-Code in die gerenderte globale Variable einzufügen.
ScriptEngine Fügen Sie eine Bibliothek hinzu, um GraalJS mit Javas ScriptEngine zu verwenden.
pom.xml
<!-- https://mvnrepository.com/artifact/org.graalvm.js/js -->
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>19.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.graalvm.js/js-scriptengine -->
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>19.2.0</version>
</dependency>
Renderer.java
public String render(String route) throws ScriptException, IOException {
ScriptEngine engine = getEngine();
ScriptContext context = getContext();
Bindings engineScope = engineSetting(engine, context);
engineScope.put("rendered", null); //Globale Variablendeklaration
engineScope.put("route", route); //Globale Variablendeklaration
engine.eval(read("static/js/server.js"), context);
return context.getAttribute("rendered").toString(); //Rendervariable auf String-Typ übertragen
}
private Bindings engineSetting(ScriptEngine engine, ScriptContext context) throws ScriptException, IOException {
context.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
Bindings engineScope = context.getBindings(ScriptContext.ENGINE_SCOPE);
engine.setContext(context);
engine.eval(
"var process = { env: { VUE_ENV: 'server', NODE_ENV: 'production' }}; this.global = { process: process };",
context);
loadFiles(engine, context); // vue-server-Renderer wird geladen
return engineScope;
}
Sie können globale Variablen mit der put-Methode der Bindings-Klasse deklarieren und die Werte mit der getAttribute-Methode der ScriptContext-Klasse abrufen.
Renderer.java
private ScriptEngine getEngine() {
return new ScriptEngineManager().getEngineByName("graal.js");
}
private ScriptContext getContext() {
return new SimpleScriptContext();
}
Um zu vermeiden, dass die JS-Seite zu einem Singleton wird, wie im VueSSR-Handbuch beschrieben, erstellt ScriptEngine jedes Mal eine neue Instanz, wenn eine Anforderung vorliegt.
Zeichnen Sie das erworbene HTML mit Thymeleaf.
index.html
<body th:utext="${rendered}">
</body>
Stellen Sie auf der Vue-Seite sicher, dass Sie die zum Zeichnen verwendete Element-ID angeben.
Die Daten zum Zeitpunkt des ersten Zeichnens werden durch Schreiben von JSON in eine HTML-Datei erfasst. Dies wird mit Thymeleaf erreicht.
index.html
<script th:inline="javascript">
/*<![CDATA[*/
window.__INITIAL_STATE__ = /*[[${word}]]*/ {};
/*]]>*/
</script>
Ich habe ein Beispielprojekt auf github veröffentlicht, daher hoffe ich, dass Sie es hilfreich finden.
Es ist einfacher, SSR mit Nuxt oder etwas anderem zu machen.
Handbuch zur serverseitigen Wiedergabe von Vue.js terwer/spring-vue-ssr
Recommended Posts