Sébastien Deleuze opened SPR-13508 and commented
Spring Framework 4.2.x introduced a generic support for script based templating suitable for any kind of script technology. The scope of this issue is to keep track of potential server-side javascript improvements.
Java to JSON object conversion
In the script template, the model object available on Javascript side is still a Java object. Most template engines requires to have a real JSON object instead of a Map
, and a real JSON array instead of an Iterable
. It should be useful to provide out of the box this functionality. A possible implementation is available here.
JS logging on server-side
Similarly to this Spring Boot proposed feature, it should be possible to provide a console.log()
interceptor that will forward client side logs to your Java log appender.
Load easily file content from filesystem or classpath
Very useful to make it possible to implement easily nested template support for example.
Script loader extension
Provide a JS extension for script loader like System.js/Require.js that loads lazily a Javascript dependency from the classpath (instead of an Ajax request) in order to improve maintainability of such app.
EmberJS 2/Angular 2/React support
More helpers/guidance for Angular 2, EmberJS 2 or React universal/isomorphic applications.
Spring beans accessible on Javascript
Experiment about making Spring beans accessible from Javascript. Wildfly support for similar functionality seems worth to have a look.
Issue Links: - #16871 Support JavaScript Templating
12 votes, 19 watchers
Comment From: spring-projects-issues
Sébastien Deleuze commented
May be useful for implementation: how to expose your Java objects as "script friendly" objects to nashorn scripts?
Comment From: spring-projects-issues
chanwook park commented
Hi! I'm tried pre-compile partial with simple maven plugin with Dust.js, and very nice work. (Thanks to Sébastien your suggestion)
Pre-compiled template is located specific folder, then I hope to ScriptTemplateView.setScripts(..) is support to load script in folder! For example,
/resources/static
+ templates
+ partial-compiled
+ nav.js
+ header.js
+ footer.js
+ template.html
ScriptTemplateView.setScripts("render.js", "static/templates/partial-compiled", ...)
Is that possible? thanks.
Comment From: spring-projects-issues
Titus Cheung commented
This is very exciting. Would support for Angular 2 means we can actually pre-render a normal Angular 2 app within Nashorn and send the rendered HTML/CSS to browser? Am curious how we may achieve this because Nashorn only provides JavaScript support and doesn't implement the full browser DOM, event loop, timer, etc and neither env.js nor Avatar.js appears to be going anywhere. Thanks.
Comment From: spring-projects-issues
Sébastien Deleuze commented
Initial discussion with Angular team about Nashorn support for rendering Angular 2 universal application on server-side.
Comment From: spring-projects-issues
Sébastien Deleuze commented
After more thoughts, and given the fact that JavaScript frameworks like Angular 2 and Ember now provide native support for isomorphic applications for server-side rendering, I tend to think we should focus on trying to provide a way to integrate seamlessly with for example Angular Universal and Ember FastBoot.
The JavaScript router is a key part of Universal and Fastboot, and we should maybe have an architecture where Spring MVC (and Spring Web Reactive) handles requests for REST or Websocket endpoints, but also where HTML pages requests should be just forwarded to the JavaScript router bundled in Universal and Fastboot.
Dealing with routing/mapping on Spring side like we do currently in ScriptTemplateView
is perfectly fine with JavaScript template engines as demonstrated in spring-react-isomorphic and spring-boot-sample-web-handlebars example apps, but with Angular 2 or Ember HTML page routing should be JavaScript framework responsability.
I think the best way to progress is to create a Spring Boot + Angular 2 universal support prototype as discussed in this Angular Universal Java support issue. Here is a draft decription of what this prototype could be:
- A Spring Boot web application
- Based on Spring Framework 5.0.0.BUILD-SNAPSHOT
- JSON REST endpoints implemented with Spring MVC or Spring Web Reactive
- Regular Angular 2 application in src/main/resources/static
- Experiment with the 2 possible engines:
- Nashorn (run natively on the JVM but some compatility issues with Angular 2)
- J2V8 (Java binding for NodeJS)
- Universal application support based on Angular Universal + some adaptations
- Experiment about how to delegate the HTML pages to Angular 2 :
- ScriptTemplateView
+ @RequestMapping
with ** wildcard
?
- Dedicated handler (may be required for J2V8 since it does not support JSR223 yet)?
- Define where such support should live:
- Spring Framework?
- Spring Boot?
- Side project?
- Provide some configuration via application.properties
or via a JavaScript file
- Benchmarks
- Optimize static files access by avoiding using the classpath to serve them (needed for Spring Web Reactive zero copy support)
We could use this hello-angular2-universal-j2v8 as a starting point (especially the server.ts file), adding support for MacOS X, replace Spark by Spring Boot, see if Nashorn is a viable option or not, etc. If anybody is interested to work on such prototype, any help will be appreciated and could help to progress faster.
The other part where I would like to move forward is the JS logging extension to send logs in a Spring Boot actuator endpoint. The goal is to achieve that for the early Spring Boot 2.0 milestones, see this Spring Boot issue for more details.
As usual, any feedbacks is welcome. Keep in mind this is a topic where we really need to experiment and there is not commitment yet to include such support in Spring Framework 5.
Comment From: spring-projects-issues
Patrick Grimard commented
Hi Sébastien, I've read over your latest comments and saw that you'd like to explore using J2V8 as a rendering engine. I've implemented such an example. You can find my GitHub repo here https://github.com/pgrimard/spring-j2v8. So far in my non-extensive example, performance seems to be quite good, but I haven't tried it with anything like React.
My repo contains a sample application, you'll also find a V8ScriptTemplateView implementation which uses J2V8 to render the view using the template and model, in a similar fashion to the existing ScriptTemplateView. I also have a V8ScriptTemplateViewResolver, V8ScriptTemplateConfig and V8ScriptTemplateConfigurer.
Comment From: spring-projects-issues
Sébastien Deleuze commented
Patrick Grimard Thanks a lot for this great contribution. This could allow to experiment on rendering Isomorphic application using React, EmberJS or Angular Universal since such support is natively built to run on top of NodeJS. It is not a pure Java solution, but when it comes to such complex JavaScript serverside rendering use case, such tradeoff is maybe something worth to consider, especially if at some point they provide natively a JSR 223 support. See also the platform specific dependencies.
If you have the time to create a JSV8 based branch in your sample application coming from your awesome blog post, please let me know (nice to see you used Kotlin for the backend ^^).
Comment From: spring-projects-issues
Patrick Grimard commented
I've just pushed the J2V8 branch to my other sample application https://github.com/pgrimard/spring-boot-react/tree/j2v8. I had to make some slight modifications to make it work. Most notable was in the V8ScriptTemplateView
, instead of calling executeObjectScript
against each script defined in the V8ScriptTemplateConfigurer
, now I'm merely calling executeScript
and only tracking results that are instances of V8Value to release later before releasing the V8 runtime. The reason for this is that when Webpack minifies the production bundle, the first character in the bundle is a ! which returns a boolean value, causing executeObjectScript
to throw an exception. Calling executeScript
simply returns an Object
and I can check if that object is an instance of V8Value
to determine if it needs to be released later or not.
Comment From: spring-projects-issues
Patrick Grimard commented
Hi Sébastien, following a comment on my blog post about using i18n in script templates, I've added this support to the J2V8 branch of my project. It uses a custom ResourceBundleMessageSource
implementation to allow fetching all messages of a given basename and locale, as a Java Map
. The map then gets converted to a V8Object
which is passed as a 3rd parameter to the JS render function. This could theoretically be applied to the existing ScriptTemplateView
without too much fuss if you think this merits a pull request.
As a side note, I've updated the sample application. It now uses a AcceptHeaderLocaleResolver
bean and a MappingResourceBundleMessageSource
(my custom implementation). The resulting messages are stored in the Redux store both on the server side and client side scripts.
Comment From: spring-projects-issues
Patrick Grimard commented
I have submitted a PR to add i18n support to ScriptTemplateView https://github.com/spring-projects/spring-framework/pull/1262
I had some issue rebasing after Codacy checked my code. My original PR 1261 got closed while I tried to sort out the mess I created. PR 1262 is a new one with the rebased code.
Comment From: spring-projects-issues
Sébastien Deleuze commented
Interesting community driven project for server side render with Spring Boot and Angular 4 based on the J2V8 library : https://github.com/swaechter/angularj-ssr
Comment From: sdeleuze
With no update in 5 years and Nashorn now removed from the JDK, I think it is better to close this and stay unopinionated at Spring Framework level.