Using React with Grails

Using React with Grails

By Zachary Klein, OCI Software Engineer

June 2016


Introduction

React, the JavaScript library from Facebook, has become a popular view technology for building dynamic, testable and performant user interfaces. While not a full-fledged framework like Angular or Ember, React’s focus on functional component-based views with no (or minimal) internal state makes it a great choice when building single-page applications (SPAs) or even dynamic subcomponents within a page-based application.

Because it doesn’t make assumptions about data flow or controller logic outside of rendering the view, React relies on the developer to either provide these features directly in JavaScript or use another framework as a backend to support the React-based UI.

It is this flexibility, in part, that makes React an appealing choice as a modern JavaScript view layer for Grails applications. The Grails framework provides a robust backend built upon Spring Boot, GORM, and the Apache Groovy programming language, as well as excellent support for generating restful endpoints that may be consumed by the React application. Since Grails 3 is also based upon Gradle, you can leverage Gradle’s Node plugin to unify your build and testing pipeline for both the Grails framework and React, without needing to complicate your deployment processes.

Finally, JSX (React’s XML-like syntax for defining components and page markup) is a powerful and flexible way to create dynamic views. In the author’s opinion, creating components in JSX is quite analogous to defining custom GSP tags in a Grails taglib: a function that receives state via props (GSP attrs) and typically (but not always) renders markup based on that state.

In React’s case, these components are re-rendered upon every change to the app’s state, rather than being limited to page-load. This stateless component model should be understandable to Grails developers who have written custom GSP tags, and JSX takes this to the next level.

This article demonstrates how to integrate React into a Grails 3 application, using some of the Grails framework's restful features to get up and running quickly. You’ll spend a bit of time getting the project set up and get to know some of the players in a React codebase.

There are plenty of resources available to teach you React and restful API design, so this article focuses primarily on the “missing pieces” of combining React with a Grails application1. A list of resources follows this article, to help in furthering your understanding of React; you’ll be able to take this foundation and follow along with the same documentation, tutorials and other resources available to React developers.

Building our Foundation

Let’s start with a brand new Grails 3.1.6 application, using the default web profile:

grails create-app com.ociweb.TodoList

Having run the create-app command, you already have a fully functioning backend application and server ready to go, and you can start up your app using the run-app command.

View your new Grails application at http://localhost:8080.

Let’s create your data model.

  1. grails create-domain-class com.ociweb.Todo
  2. grails create-domain-class com.ociweb.TodoList
  3. grails-app/domain/com/ociweb/Todo.groovy
  4.  
  5. package com.ociweb
  6.  
  7. class Todo {
  8.  
  9. String name
  10.  
  11. static belongsTo = [todoList: TodoList]
  12. }
  13. grails-app/domain/com/ociweb/TodoList.groovy
  14.  
  15. package com.ociweb
  16.  
  17. class TodoList {
  18.  
  19. String name
  20.  
  21. static hasMany = [ todos: Todo ]
  22.  
  23. static constraints = {
  24. todos nullable: true
  25. }
  26. }

Now, you have the domain model ready to go.

By default, Grails provides an H2 database (in memory for development and test environments, as a file in production). Of course, Grails supports all the major databases, including MySQL, Postgres, Oracle, and even NoSQL data stores like Mongo. Thanks to the flexibility of GORM, changing datasources is as simple as adding a couple dependencies or lines of configuration.

Let’s switch to Mongo for this demonstration (this step is optional).

Specify the mongo plugin in your build.gradle file:

  1. build.gradle
  2.  
  3. buildscript {
  4. //…
  5. dependencies {
  6. //…
  7. classpath "org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT"
  8.  
  9. dependencies {
  10. //…
  11. compile "org.grails.plugins:mongodb:5.0.0.BUILD-SNAPSHOT"
  12. compile "org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT"

Now, in your domain classes, add this static property to store the domain object in Mongo:

static mapWith=“mongo”

The plugin assumes you have mongodb installed and that mongod is running at port 27017; you can configure these to match your environment (see the plugin documentation for details).

Defining our API

Finally, you need to define a restful API for your React application.

API design is a broad subject and not within the scope of this article. However, Grails gives us a jump start to getting our API off the ground, providing endpoints for standard CRUD operations with minimal configuration. This is done by declaring your domain classes as resources, either by marking with the @Resource annotation, or by specifying the resource class within our URLMappings.

Let’s use the @Resource annotation for this example.

  1. grails-app/domain/com/ociweb/Todo.groovy
  2.  
  3. import grails.rest.Resource
  4.  
  5. @Resource(uri='/api/todos', formats=['json'])
  6. class Todo {
  7. //...
  8. grails-app/domain/com/ociweb/TodoList.groovy
  9.  
  10. @Resource(uri='/api/todoList', formats=['json'])
  11. class TodoList {
  12. //...

Note that you specify the content-type you wish to expose – you’ll use JSON.

Finally, let’s add some initial data in Bootstrap.groovy:

  1. grails-app/init/BootStrap.groovy
  2.  
  3. import com.ociweb.*
  4.  
  5. class BootStrap {
  6.  
  7. def init = { servletContext ->
  8.  
  9. if(!Todo.list()) {
  10. log.info "Creating todos..."
  11. def todoList = new TodoList(name: "Bob's List").save()
  12.  
  13. [[name: "Task 1", todoList: todoList],
  14. [name: "Task 2", todoList: todoList],
  15. [name: "Task 3", todoList: todoList]].each { props ->
  16. def todo = new Todo()
  17. todo.properties = props
  18. todo.save(flush: true)
  19. }
  20.  
  21. }
  22. }
  23. def destroy = {
  24. }
  25. }

Restart the application to load the new data. Now, using a rest client application or a program like cUrl, you can test drive your new API.

  1. curl -i -H "Accept: application/json" localhost:8080/api/todos
  2.  
  3. HTTP/1.1 200 OK
  4. Server: Apache-Coyote/1.1
  5. X-Application-Context: application:development
  6. Content-Type: application/json;charset=UTF-8
  7. Transfer-Encoding: chunked
  8. Date: Sun, 15 May 2016 06:03:56 GMT
  9.  
  10. [{"id":1,"list":{"id":1},"name":"Task 1"},{"id":2,"list":{"id":1},"name":"Task 2"},{"id":3,"list":{"id":1},"name":"Task 3"}]
  11. curl -i -H "Accept: application/json" localhost:8080/api/todoList/1
  12.  
  13. HTTP/1.1 200 OK
  14. Server: Apache-Coyote/1.1
  15. X-Application-Context: application:development
  16. Content-Type: application/json;charset=UTF-8
  17. Transfer-Encoding: chunked
  18. Date: Sun, 15 May 2016 06:06:00 GMT
  19.  
  20. {"id":1,"name":"Bob's List","todos":[{"id":3},{"id":1},{"id":2}]
  21. }

There you go! You have a fully functioning restful API backed by Mongo, and your coffee isn’t even cold yet!

Now that the backend is largely ready to go, you’re ready to set up React.

Why Do This?

Why not use separate backend and front-end apps? In a microservice architecture, the work you’ve already done might be sufficient; you could now build a separate React/Node-based frontend application independent of your Grails backend. This is a great strategy, and Grails 3.1 ships with a profile tailored to this use case (web-api).

Another option is to take advantage of Gradle multi-project builds, with separate projects for the backend and frontend. Both of these options require another server to run the React app.

This article, however, considers the use of React as the “view” (the V in MVC) in a standard Grails application. Although you’re sharing a project directory, the React code and Grails artifacts are independent and will communicate at runtime via your restful API, just as if they were separate apps. The only thing tying these two apps together is the same Gradle build, which gives you the benefits described earlier in the article (in fact, it would be quite easy to split out the React app in the future by simply moving the src/main/js and src/test/js directories into their own project, configuring up a new server).

There are many situations where a team may want to bring React into a Grails application, and it may be done in a way that allows for full developer productivity for both Grails and Node/React developers. Read on to see how!

Upgrading our Build

React is most commonly used in combination with Node.js, and even if you don't intend to use Node in particular, it still makes sense to have it installed if you intend to do any serious work with a JavaScript library like React.

The reason? You will use npm (which most surely does not stand for Node Package Manager) to download and install React and any other libraries you choose to use alongside it. npm may also be used to run scripts to build and test your React code, and it is the “handle” that will allow you to integrate your React code with your Gradle-based deployment.

Once your React application is set up, it will not be necessary for all developers to run Node on their machines; you’ll take care of making that happen seamlessly as part of the Gradle build. However, any developer who is set up with Node will be able to use npm and other Node tools just as if they were working within a “plain” Node application. This gives you the best of both worlds: backend Grails developers may do their work without relying upon Node and npm, while frontend developers may use Node and their preferred development tools. The only requirement for all team members will be a Gradle installation to run the Grails project.

In addition to installing Node in your development environment, you will need to install the gradle-node plugin in your Grails application. This plugin will be the key to managing your npm tasks without relying upon local installations of Node.

Install the plugin by adding the plugin in build.gradle:

  1. build.gradle
  2.  
  3. plugins {
  4. id "com.moowork.node" version "0.12"
  5. }
  6.  
  7. node {
  8. version = '5.10.1'
  9. npmVersion = '3.8.3'
  10. distBaseUrl = 'https://nodejs.org/dist'
  11. download = true
  12. }

Setting up our React environment

For the next few steps, we’ll use a local installation of npm. If you don’t have it installed yet, nvm is highly recommended to simplify installation and managing of Node versions (if you’ve used gvm/sdkman for managing Grails/Groovy/Gradle versions, you’ll like nvm).

The latest version of Node 5.x (5.10.1, as of the time of writing) is used for this article. Please refer to the Readme in the Github repository for the versions of all Node packages that are used. For a simple example like this, newer versions of any of the packages shouldn't cause a problem.

Assuming you’ve installed npm, let’s initialize your project. Run this command from your Grails project directory. You can accept the defaults for now; it’s easy to fill in the details later:

npm init

Now you’re ready to install React and other dependencies.

npm install react react-dom --save
 
npm install babel-core babel-preset-es2015 babel-preset-react babel-loader webpack --save-dev

There are plenty of options when setting up a React application, but these are the basics.

Of course you need React and ReactDOM to render your app in the browser (React may also be used natively on mobile platforms like iOS, using ReactNative instead of ReactDOM).

In addition, because you’ll be using JSX to write your components, you’ll need to use a transpiler to convert your React code into “plain vanilla” Javascript. Modern Javascript frameworks are moving much faster than web browsers, and many of the Javascript APIs commonly used in React projects are not yet standard in browsers. Babel is a popular transpiler with many “presets” supporting different versions of Javascript syntax.

To enable these presets, create a .babelrc file in the project root directory, with this content:

  1. {
  2. "presets": [
  3. "react",
  4. "es2015"
  5. ]
  6. }

This will ensure that Babel uses the presets you’ve installed when transpiling your code.

Of course, if you’re going to run your code through a transpiler, that means you need a build step to do the work. Typically in Grails applications, the asset pipeline plugin is the tool of choice for processing static assets like Javascript files. While there is a Babel plugin for the Grails asset pipeline, you are going to take a different approach and use webpack for this purpose; this will give you more flexibility in processing your React code and is in keeping with typical React projects.

webpack

webpack represents a family of tools called bundlers. It is a popular choice for building React applications. It’s also a powerful and complex tool, but you can get started with a fairly minimal configuration.

Here’s the big picture: webpack will be responsible for running your React code through loaders for processing and then output the finished product as a bundle.

There are loaders for nearly every conceivable asset type you may want to access in your React application, including LESS, SASS, markdown, images, urls, generic files, and even Java properties files (such as i18n/messages.properties files). In this case, the babel-loader is all you need to configure right now. We will configure webpack to drop this bundle into the grails-app/assets/javascripts directory in your Grails application, so it may be served just like another Javascript file.

Here’s your webpack.config.js file:

  1. var path = require('path');
  2.  
  3. module.exports = {
  4. entry: {
  5. index: './src/main/js/index.js'
  6. },
  7. output: {
  8. path: './grails-app/assets/javascripts',
  9. publicPath: '/assets/',
  10. filename: 'bundle.js'
  11. },
  12. module: {
  13. loaders: [
  14. {
  15. test: /\.js$/,
  16. include: path.join(__dirname, 'src/main/js'),
  17. loader: 'babel',
  18. query: {
  19. presets: ['es2015', 'react']
  20. }
  21. }
  22. ]
  23. }
  24. };

Don’t be intimidated by this configuration; it’s actually fairly simple. The syntax is plain Javascript, which may be a bit confusing for a Grails developer accustomed to a DSL for config. The key points are that you’re defining:

You can learn more about configuring webpack from the documentation, but this should get you started.

WHERE IS src/main/js?

Typically in a Grails application, Javascript files, like other static assets, live in the grails-app/assets/ directory, which is where the asset pipeline picks them up. However, it is far more typical in a React application to keep the source files separate from the distributed bundle within a src directory, which makes sense, given that they contain “source code” for an application and are not really “assets” in the sense that bootstrap or jQuery may be. In addition, you will want to write tests for your React code, and it really doesn’t make sense for tests to live in an “assets” directory structure.

This is simply a matter of preference; in this article, we will store your React source code under src/main/js (in keeping with Grails' default src/main/java and src/main/groovy source structure), and your tests under src/test/js. These directories won’t exist by default, so you’ll need to create them ourselves.

Now you just need to add a couple of “scripts” to your package.json file in order to run webpack via npm. In the scripts section, add these two lines:

 "scripts": {
    "watch": "webpack --watch --colors --progress",
    "bundle": "webpack",

Now you can call these scripts using npm.

Why do you have two scripts that both run webpack? The bundle version runs webpack and generates the bundle once (analogous to grails war), while the watch version will run webpack in “watch” mode, where the tool will automatically regenerate the bundle every time it detects a change to the source files (similar to grails run-app, with reloading of changed classes). You also enable some pretty formatting to ensure developer happiness.

You can now run these scripts like so:

npm run bundle

However, you’ll likely get an error saying “Entry module could not be found.”

Yep, you haven’t added the “entry” file you specified earlier in your src/main/js directory yet. Let’s do that.

Create index.js and add a simple alert() statement:

alert('Hello!');

Now if you run npm run bundle, you’ll get output like this:

Hash: bc17d737c7738edc00a5
Version: webpack 1.13.0
Time: 727ms
    Asset     Size  Chunks             Chunk Names
bundle.js  1.43 kB       0  [emitted]  index
    + 1 hidden modules

If you check your grails-app/assets/javascripts directory, you should see your shiny new bundle.js!

Finally, you need to load this bundle on your page. You’ll use a Grails controller and GSP view in this demonstration, but this could easily be a plain HTML page as well.

Create a new controller AppController, and create an index.gsp page in the grails-app/views/app directory with this content:

  1. grails create-controller com.ociweb.AppController
  2.  
  3. <!doctype html>
  4. <html>
  5. <head>
  6. <title>Todo List</title>
  7. </head>
  8. <body>
  9. <div id="app"></div>
  10. <asset:javascript src="bundle.js" ></asset:javascript>
  11. </body>
  12. </html>

(Note that if you had used a plain HTML page, you would not be able to use the tag)

Browse to http://localhost:8080/app, and you should see your alert() statement.

webpack-dev-server

Webpack also includes a simple server called ‘webpack-dev-server’, which will operate similarly to “watch” mode, but is actually able to instantly reload the bundle/s on your page, so you can see your app update when you save your source file without refreshing the browser. This is a powerful feature, but it can be tricky to set up and is outside the scope of this article.

There is a starter application available on Github2 that demonstrates use of the webpack-dev-server within a Grails application.

Enter Gradle

The setup steps are almost done. With the current configuration, you can bundle your React code and output it to the asset pipeline, so the Grails app can serve it to your views. We also have a restful backend provided by your Grails app. Now you just need to make use of the gradle-node-plugin 3 to automate the webpack bundling process when you:

  1. Start the Grails app
  2. Package the Grails app as a WAR or JAR file

Add these two lines to the end of your build.gradle:

processResources.dependsOn(['npmInstall', 'npm_run_bundle'])
 
assetCompile.dependsOn(['npmInstall', 'npm_run_bundle'])

And that’s it!

All you’ve done here is “hooked” a pair of npm tasks into your Gradle build process. The first is npmInstall, which is the equivalent of npm install, and is typically the first command you’d run when setting up an existing Node-based project. npm install will read the package.json file and install any missing dependencies in your development environment.

The second task should look familiar. It’s your bundle script you just used a moment ago. The Gradle Node plugin supports this syntax for any script that you would normally run with npm. So any custom scripts you write in the future may be called via npm_run_[your new script].

Of course, you can run these scripts yourself through Gradle, using the included Gradle wrapper:

./gradlew npm_run_watch

Other than the delay from spinning up Gradle, this will have the same effect as running npm run watch directly. This also means that developers without Node installed can run these tasks without adding anything to their build environment; Gradle will handle those details seamlessly and OS-independently.

When developing with React, typically you will run the Grails app and run webpack in “watch” mode, using npm or Gradle. As you make changes to your Javascript sources, webpack will automatically regenerate the bundle.js, and you can load the changes by refreshing your page.

Image 1

Development Workflow with Grails & webpack (grails run-app in the left terminal, ./gradlew npm_run_watch in the right).

Returning to your new build.gradle steps, you’ll notice that you’ve attached these tasks to Grails' processResources (which runs every time the Grails app is started) and assetCompile (which runs when the app is packaged) tasks as dependencies. In this case, you just want to make sure the bundle is generated when the app is run, and when you build your WAR/JAR file, so that you’re always using your latest bundle.js. This also means you can exclude bundle.js from your version control if you’d prefer.

Now you can build your Grails application on a Continuous Integration server that knows nothing about Node or React. Gradle will handle installing Node (local to the project), downloading npm dependencies, and running scripts like your webpack bundle, all without any changes to your build and deployment process.

Defining Your Components

As mentioned in the introduction to this article, React provides an expressive XML-like syntax for defining your components. Let’s take a look at a simple JSX component that will render a Todo instance.

  1. /src/main/js/todo.js
  2.  
  3. import React from 'react';
  4.  
  5. function Todo(props) {
  6.  
  7. const todo = props.todo;
  8.  
  9. return(
  10. <li>
  11. <input id={ todo.id } type="checkbox"
  12. checked={ todo.complete ? 'checked' : '' }
  13. onChange={ props.toggleComplete } />
  14. <span>{ todo.name }</span>
  15. </li>
  16. );
  17. }

Again, this is not an in-depth explanation of React and JSX, but you can learn a lot from even a simple example like this one. As you can see, your component is a simple Javascript function, which takes an object (key/value pairs, similar to a Groovy map) that contains all attributes that are passed into this component.

To use your new component, you just need to render it to your page (note that a toggleComplete function has not yet been implemented, so that property will be skipped for now; your  component will still render but it won’t do anything yet):

  1. /src/main/js/index.js
  2.  
  3. import React from 'react';
  4. import ReactDOM from 'react-dom';
  5. import Todo from './todo';
  6.  
  7. //Call to render our component into the DOM…
  8. ReactDOM.render(
  9. <div>
  10.  
  11. <h1>Our first Todo!</h1>
  12.  
  13. <Todo todo={{name: 'Task 1', id: 1, complete: false}}></Todo>
  14.  
  15. </div>, document.getElementById('app')); // ...into this element on the page

Compare this to a custom GSP tag that might render similar output server-side:

//Hypothetical GSP taglib
 
def todo = { attrs ->
 
	def todo = attrs.todo
 
	out << """
  <li>
    <input type="checkbox" 
			checked=${todo.complete ? 'checked' : ''} 
			onchange=${ /* specify an Ajax function */} />	
			<span>${todo.name}</span>
	  </li>
		"""
}
<g:todo todo=${todo} />

Of course this is not an entirely fair comparison. GSP tags provide much more functionality than simply rendering of attributes, but Grails developers should find the syntax of JSX to be quite friendly and understandable coming from GSPs.

JSX allows you to write Javascript expressions bound by curly braces, supports namespacing of components, and can make large, complex UI’s easier to visualize while coding.4 However, JSX is optional; you can write React components entirely in plain Javascript, but the resulting code is more verbose.

Word of Warning

This article is not intended as a comprehensive introduction to React. For developers new to Javascript, there are plenty of pitfalls to be had when learning this library. Understanding function context, “binding,”5 and passing functional callbacks into child components are key skills when writing clean code in React. These concepts are not React-specific; they are, in fact, plain Javascript, but they can be confusing to Groovy and Java programmers. There are many resources for learning React, and a few of them are listed at the end of this article.

Calling the API

Now that you have your React app integrated into your Grails project and served up via the asset pipeline, you can start to build out your application and write components that consume your restful API.

Because React is a view library, it doesn’t offer specialized features for communicating with a restful API. Developers are encouraged to use native Javascript APIs or other libraries to supply this functionality.

The example project from this article uses the fetch API6. The full code is available on Github, so it won’t be reviewed here. The app allows a user to create new todo lists and add new todo items to them; all changes are saved to the Mongo database. It also makes use of JSON Views to customize the JSON output from your endpoints. No update or delete functions are provided at this time; those features are left as an exercise to the reader.

https://github.com/ZacharyKlein/sett-todolist

Below is a completed TodoList app:

IMage 2

Testing

One of the benefits of creating a user interface in React is testability. Because React encourages the use of stateless components, testing their functionality is often as simple as providing props and making assertions against their output.

Let’s look at a simple test for your component, and then see how the Gradle Node plugin can help us run your tests as part of your build.

There are many options for testing Javascript code.78  This example will use the mocha test framework, React’s own testing utilities, and expect.js to provide assertions.

Again, because React is focused on building your view layer, you’re mostly concerned with testing that your components output the correct content from their props. This is not an in-depth look at testing React components, but it will give you a place to start.

First, let’s install some dependencies:

npm install mocha expect react-addons-test-utils --save-dev

And add this “test” script to your package.json file:

”test": "mocha './src/test/js/*.spec.js' --compilers js:babel-core/register"

Here's a simple test for your <ToDo> component:

  1. /src/test/js/lot.spec.js
  2.  
  3. import React from 'react';
  4. import TestUtils from 'react-addons-test-utils';
  5. import expect from 'expect';
  6. import Todo from '../../main/js/todo';
  7.  
  8. describe('Todo', () => {
  9. it('should have expected content', () => {
  10.  
  11. const todo = {name: 'Task 1', complete: false, id: 1, list: { id: 1 }};
  12.  
  13. const renderer = TestUtils.createRenderer();
  14.  
  15. renderer.render(
  16. <Todo todo={todo} ></Todo>);
  17.  
  18. const output = renderer.getRenderOutput();
  19.  
  20. //We expect the <Todo> to output an <li> element
  21. expect(output.type).toBe('li');
  22.  
  23. const children = output.props.children;
  24. const [input, span] = children;
  25.  
  26. //We expect the first element in our <li> to be an input
  27. expect(input.type).toBe('input');
  28.  
  29. const todoName = span.props.children;
  30.  
  31. //We expect the span to contain the name of the todo
  32. expect(todoName).toBe(todo.name);
  33. });
  34. });

There’s a lot to unpack here that is beyond the scope of this article, so I’ll refer you to the resources at the bottom of the page for more detail.

The big picture is fairly simple. You’ve created a “mock” todo object, and used it to populate our component, which is then “rendered” using TestUtils.createRenderer() (TestUtils also includes features for simulating clicks and other user interactions with your components). At that point, you're simply traversing the “DOM” and making assertions about the expected content.

To run this test, use npm to run your new test script:

npm run test
 
> todo-list@1.0.0 test /Users/zak/Dev/TodoList
> mocha './src/test/js/*.spec.js' --compilers js:babel-core/register
 
  Todo
    ✓ should have expected content
 
  1 passing (15ms)

Finally, you can add this test script to your Gradle build using the same techniques that were explored earlier.

build.gradle
 
//Run React tests
task mochaTest(dependsOn: ['npmInstall', 'npm_run_test'])
 
check.dependsOn(mochaTest)

Now we can run our React tests via Gradle with ./gradlew mochaTest, and they will also be run as part of the check task (which runs Grails unit and integration tests together).

Conclusion

React is a powerful and exciting library, and it’s a great choice for Grails applications. While there’s some bootstrapping necessary to get started, with a project structure like what was demonstrated, you should be able to take advantage of the many resources available for learning React and the associated libraries and tools, without having to “translate” into a Grails-specific flavor.

In addition, frontend developers unfamiliar with Grails should find it much easier to work using their favorite Node-based tools and development environments. The only requirement to firing up the backend is Java and the Gradle wrapper that is included in the Grails project. With React’s tooling standardized around npm, and Grails’ build process managed by Gradle, it’s quite straightforward to set up a combined development and deployment pipeline, one that allows both frameworks to be used as designed.

Postscript

As mentioned earlier in the article, a starter project with React integrated in a Grails application, using the same structure described above has been created. It also provides a working configuration for the webpack-dev-server, including a custom taglib to switch between the “hot load” bundle and the static bundle from the Grails asset pipeline. React-Bootstrap and loading of images and CSS are also demonstrated. The project is available on Github. [2]

Resources

Documentation

References



 

Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.


secret