3

I am currently migrating a Play Framework application with a view composed entirely of Twirl templates into one with a view composed of a mix of Twirl and React. I have written a PlayRunHook to integrate Webpack with Play's build process, and the result is JavaScript bundles whose names match what I have hardcoded in the new barebones Twirl templates.

So things look like this:

@(title: String)(implicit session: Session, staticAssetResolver: StaticAssetResolver)
@main(title) {
        <input type="hidden" name="pageTitle" id="pageTitle" value="@title">

        <div id="content">
        </div>

        <script language="JavaScript" src="@staticAssetResolver.asset("dist/profile.bundle.js")"></script>
}

The React code in the bundle knows to mount at the "content" div and receives props provided in the template.

This all works well, but I would like to avoid hardcoding the bundle name so that I can benefit from asset fingerprinting. This means figuring out a way to more tightly couple Webpack with Play's build process so that Webpack's output can be incorporated into the Twirl templates.

I have researched plugins, but what would you suggest for integrating Webpack and Twirl in this way?

Vidya
  • 29,932
  • 7
  • 42
  • 70
  • I'm not familiar with `twirl` but what is the content that is going into the webpack pipe line? – felixmosh Aug 25 '19 at 20:04
  • Twirl is the templating language for serverside-rendering HTML in Play Framework--like ERB in Rails FWIW. The Webpack pipeline (among a lot of other things) transpiles TypeScript JSX/Sass into JavaScript/CSS bundles whose names I've defined to match what's in the templates. The templates hold variables whose values become props to the React code in the bundle mounted in the "content" div. – Vidya Aug 25 '19 at 20:08
  • Is those templates are separate files? something that you can provide to webpack? As I've understood, you want to inject bundle file name into the template, is that correct? – felixmosh Aug 25 '19 at 20:10
  • I basically want to do with dynamically generated Twirl templates what [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) does with static HTML files. The bundles are generated in a completely separate process Play barely knows about (because of the `PlayRunHook`) from the templates. – Vidya Aug 25 '19 at 20:15
  • OK, you can feed html-webpacl-plugin with a custom template (twirl one) and specifiy the place to inject with this method: https://github.com/jantimon/html-webpack-plugin/tree/master/examples/custom-insertion-position – felixmosh Aug 25 '19 at 20:18
  • I saw that, but Twirl templates are parameterized and generated during Play's build process, so the Handlebars/Mustache/etc. approach doesn't quite work here. However, part of the reason I asked the question is to see if anyone knows how Webpack can inject the bundles immediately after the templates are generated. This means making Webpack a first-class citizen of Play's build process. – Vidya Aug 25 '19 at 20:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/198454/discussion-between-felixmosh-and-vidya). – felixmosh Aug 25 '19 at 20:24

1 Answers1

2

This is probably not what you want to hear - I too messed around with trying to figure out how to embed interactivity in Twirl... but in the ended I concluded it was a back idea to mix javascript and twirl, ended up doing this;

https://blog.usejournal.com/react-with-play-framework-2-6-x-a6e15c0b7bd

It could be that I'm simply not familiar enough with Twirl, but after wrestling for quite a while, I found that simply "changing worlds" into react, and having it talk to the backend via

fetch(/api/myRoute)

was quite productive. In conjunction with React Router I found myself very happy with the productivity, performance and outcome. I spent little time on "custom" build work, outside of copy and paste from that blog, so was able to concentrate on what I wanted.

I would also say that I am not skilful enough, and did not have time to start writing custom "RunHooks"... so that may also be the problem!

The above link worked well for me... with the only downside being that when changing routes one gets no tool support... so it is manual and risky to change a backend route or method signature. Probably not great for a big app... but for my small set of requirements was an effective strategy.

Simon
  • 323
  • 2
  • 15
  • I saw that link and considered a React Router approach as well, but it is too heavy a lift for my app. Thanks for the suggestion. – Vidya Aug 27 '19 at 02:17