В жизни каждого Java разработчика может наступить момент, когда ничего не остаётся, как использовать в своём приложении ReactJS. Если, конечно, не AngularJS. Вы долго сопротивлялись, но этот момент настал и надо что-то делать. Вы слышали, что есть Node.JS, что он умеет быть web-сервером, но это уже через чур. У вас будет кошерный Spring Boot. К сожалению, поиск в гугл способен очень запутать. Много разных гайдов, все оперируют разными версиями реакта и сопутствующих средств. Данный гайд описывает процесс создания простейшего Spring Boot + ReactJS приложения, простой и приятный.
Сначала надо скачать и установить Node.js. При установке (требуется наличие административных прав) важно убедиться, что устанавливается npm и прописываются системные пути. В случае Windows появляется «Node.js command prompt», в других OS наверное тоже что-то такое появляется. Запускаем его. Если вы работаете без доступа к интернету (это очень не удобно, но так бывает), вы можете указать пусть к локальному npm-репозиторию; им вполне может быть ваш корпоративный Nexus. Для этого в командной строке выполните команду
Далее мы будем делать классическое maven-приложение. Поскольку статья предназначена прежде всего Java-программистам, рассказывать как это делать, и что указывать в pom.xml, чтобы получилось Spring Boot приложение, я не буду. Создайте папку src\main\resources\static (далее просто static). Перейдите в консоли в неё, и инициализируйте node-приложение, выполнив команду npm init. В интерактивном режиме вам будет предложено ввести основные параметры вашего приложения (название, автор и т.п.). По завершении работы появится файл static\package.json, его можно всегда поменять вручную. Перед выполнением дальнейших шагов крайне желательно обновить менеджер пакетов npm до актуальной версии. Для этого в консоли выполните команду
Подключите зависимости, которые вам потребуются. Они делятся на две категории, основные и разработческие — последние не попадут в поставляемую сборку. Минимальный набор для нашего примера такой:
В результате обновится файл static\package.json и создастся папка static\node_modules. Эту папку надо добавить в .gitignore. Также её следует исключить из сборки ресурсов maven'а:
О том, как писать приложения на ReacJS вполне доступно написано в аутентичном руководстве от Facebook. Говоря совсем коротко, программирование на ReacJS сводится к тому, что вы пишете обработчики, которые рендерят кастомные тэги в html-код.
Для начала создайте папку static\app, в ней файл app.jsx — там будет основной класс приложения. Добавьте в него следующее содержание:
Тут важно следующее: в нашем небольшом классе используется синтаксис JSX, используется синтаксис ES2015 языка JavaScript. Предполагается, что на странице html, куда будет добавлен этот скрипт, есть элемент с id=«react», и именно он будет заменён тэгом <App />, который, в свою очередь, рендерится в сакраментальную надпись. Далее создаём файл static\index.js со следующим содержимым:
Это будет точка входа в наше приложение. Если вы используете Idea, и она после этого ругается, что текущая версия JavaScript не поддерживает импорты, жмёте Alt-Enter и включаете ES6.
Наконец, создайте файл src\mail\resources\templates\greeting.html со следующим содержимым:
Собственно это всё в части программирования. Если вы используете Spring MVC, вам не составит труда сделать приложение, которое покажет этот html. Осталось только преобразовать наш JSX скрипт в годный JavaScript, и всё взлетит. Для этого мы будем использовать Webpack.
Использование Webpack совместно с ReactJS является распространённой практикой. Грубо говоря, процесс сводится к тому, что Webpack, используя различные библиотеки babel транслирует наш код в такой, который поймёт браузер. При этом нам было бы очень приятно, чтобы в нём можно было ставить брекпойнты, и не в какое-то сгенерённое не пойми что, а в исходный понятный JSX скрипт. К счастью, эта задача разрешима. Для успешного выполнения дальнейших шагов предполагается, что рекомендованные выше обязательные и девелоперские зависимости были подключены, и ваш файл package.json в этой части имеет примерно следующий вид:
Важно, что мы используем Webpack2, с первым всё по-другому. Создайте файл static\.babelrc со следующим содержанием (как не трудно догадаться, это конфигурация Babel):
Создайте файл static\webpack.config.js со следующим содержимым:
Обратите внимание, что:
Ключ "-d" означает «development», если использовать -p «production», то результат будет минифицирован. В принципе, это не существенно, на возможность дебажить это не влияет. Выполните компиляцию, запустив в командной строке Node.js команду npm run build. Добавьте в .gitignore npm-*.log и generated/.
Обратите внимание, что даже в таком минимальной примере компиляция webpack занимает несколько секунд (у меня до 8с). Это много. Имеет смысл настроить автоматическую перекомпиляцию. С этой целью был ранее установлен пакет webpack-dev-server, и добавлены его конфигурационные параметры в секции devServer. Данная задача реализуется как фоновый процесс, запускаемый скриптом. Чтобы этот скрипт запустить, нужно добавить в секцию scripts файла package.json элемент "«dev»: «webpack-dev-server --content-base app/»" (здесь «dev» — алиас скрипта, можно использовать любой). Этим мы настраиваем процесс мониторинга изменений в папке app/, в которой лежит наш JSX скрипт.

Затем выполните команду npm run dev. В результате запустится Node.js Express сервер, который сначала выполнит обычную компиляцию webpack, закэширует всё, что нужно, и затем будет при каждом изменении инкрементально перекомпиливать. У этого сервера довольно много опций, отсылаю к оригинальной документации (ссылка ниже). Если требуется выполнять ещё какие-то действия в командной строке npm, придётся запустить новую, эта теперь занята.
И теперь совсем всё. Запускаете приложение и оно радуется миру.
Для полноты картины надо упомянуть, что можно обойтись и без консоли. Для работы с npm существует довольно удобный maven-плагин frontend-maven-plugin. Фрагмент pom-файла с его участием приведён ниже:
Подготовка среды разработки
Сначала надо скачать и установить Node.js. При установке (требуется наличие административных прав) важно убедиться, что устанавливается npm и прописываются системные пути. В случае Windows появляется «Node.js command prompt», в других OS наверное тоже что-то такое появляется. Запускаем его. Если вы работаете без доступа к интернету (это очень не удобно, но так бывает), вы можете указать пусть к локальному npm-репозиторию; им вполне может быть ваш корпоративный Nexus. Для этого в командной строке выполните команду
npm config set registry http://ваш_npm_репозиторий
Далее мы будем делать классическое maven-приложение. Поскольку статья предназначена прежде всего Java-программистам, рассказывать как это делать, и что указывать в pom.xml, чтобы получилось Spring Boot приложение, я не буду. Создайте папку src\main\resources\static (далее просто static). Перейдите в консоли в неё, и инициализируйте node-приложение, выполнив команду npm init. В интерактивном режиме вам будет предложено ввести основные параметры вашего приложения (название, автор и т.п.). По завершении работы появится файл static\package.json, его можно всегда поменять вручную. Перед выполнением дальнейших шагов крайне желательно обновить менеджер пакетов npm до актуальной версии. Для этого в консоли выполните команду
npm install npm@latest -g
Подключите зависимости, которые вам потребуются. Они делятся на две категории, основные и разработческие — последние не попадут в поставляемую сборку. Минимальный набор для нашего примера такой:
- Основные:
npm install react requirejs react-dom rest --save
- Разработческие:
npm install babel-loader babel-core webpack webpack-dev-server babel-preset-stage-0 babel-plugin-transform-regenerator babel-preset-es2015 babel-preset-react --save-dev
В результате обновится файл static\package.json и создастся папка static\node_modules. Эту папку надо добавить в .gitignore. Также её следует исключить из сборки ресурсов maven'а:
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>static/node_modules/**/*.*</exclude> </excludes> </resource> </resources> </build>
Создание каркаса приложения
О том, как писать приложения на ReacJS вполне доступно написано в аутентичном руководстве от Facebook. Говоря совсем коротко, программирование на ReacJS сводится к тому, что вы пишете обработчики, которые рендерят кастомные тэги в html-код.
Для начала создайте папку static\app, в ней файл app.jsx — там будет основной класс приложения. Добавьте в него следующее содержание:
import React from "react"; import ReactDom from "react-dom"; class App extends React.Component { render() { return <p>Hello, World!</p> } } ReactDom.render(<App />, document.getElementById('react'));
Тут важно следующее: в нашем небольшом классе используется синтаксис JSX, используется синтаксис ES2015 языка JavaScript. Предполагается, что на странице html, куда будет добавлен этот скрипт, есть элемент с id=«react», и именно он будет заменён тэгом <App />, который, в свою очередь, рендерится в сакраментальную надпись. Далее создаём файл static\index.js со следующим содержимым:
import App from './app/app.jsx';
Это будет точка входа в наше приложение. Если вы используете Idea, и она после этого ругается, что текущая версия JavaScript не поддерживает импорты, жмёте Alt-Enter и включаете ES6.
Наконец, создайте файл src\mail\resources\templates\greeting.html со следующим содержимым:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8"/> <title>Hello demo</title> </head> <body> <div id="react"/> <script src="/generated/app-bundle.js"/> </body> </html>
Собственно это всё в части программирования. Если вы используете Spring MVC, вам не составит труда сделать приложение, которое покажет этот html. Осталось только преобразовать наш JSX скрипт в годный JavaScript, и всё взлетит. Для этого мы будем использовать Webpack.
Настройка компиляции с Webpack
Использование Webpack совместно с ReactJS является распространённой практикой. Грубо говоря, процесс сводится к тому, что Webpack, используя различные библиотеки babel транслирует наш код в такой, который поймёт браузер. При этом нам было бы очень приятно, чтобы в нём можно было ставить брекпойнты, и не в какое-то сгенерённое не пойми что, а в исходный понятный JSX скрипт. К счастью, эта задача разрешима. Для успешного выполнения дальнейших шагов предполагается, что рекомендованные выше обязательные и девелоперские зависимости были подключены, и ваш файл package.json в этой части имеет примерно следующий вид:
"dependencies": { "react": "^15.4.2", "react-dom": "^15.4.2", "requirejs": "^2.3.2", }, "devDependencies": { "babel-core": "^6.22.1", "babel-loader": "^6.2.10", "babel-plugin-transform-regenerator": "^6.22.0", "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.22.0", "babel-preset-stage-0": "^6.22.0", "react-frame-component": "^0.6.6", "webpack": "^2.2.1", "webpack-dev-server": "^2.3.0" }
Важно, что мы используем Webpack2, с первым всё по-другому. Создайте файл static\.babelrc со следующим содержанием (как не трудно догадаться, это конфигурация Babel):
{ "presets": ["react", "es2015", "stage-0"], "plugins": ["transform-regenerator"] }
Создайте файл static\webpack.config.js со следующим содержимым:
var packageJSON = require('./package.json'); var path = require('path'); var webpack = require('webpack'); module.exports = { devtool: 'source-map', entry: './index.js', output: { path: path.join(__dirname, 'generated'), filename: 'app-bundle.js'}, resolve: {extensions: ['.js', '.jsx']}, plugins: [ new webpack.LoaderOptionsPlugin({ debug: true}), new webpack.DefinePlugin({ "process.env": { NODE_ENV: JSON.stringify("development") } }) ], module: { rules: [ { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ } ] }, devServer: { noInfo: false, quiet: false, lazy: false, watchOptions: { poll: true } } }
Обратите внимание, что:
- Точкой входа является ранее определённый скрипт index.js
- Результат компиляции будет положен в папку static\generated
- Настройки установлены разработческие. В дальнейшем имеет смысл использовать профили webpack, разделяя конфигурации по средам dev\test\prod. За подробностями отсылаю к документации (ссылка ниже)
- Результирующий скрипт будет называться "/generated/app-bundle.js". Именно его мы указали в greeting.html.
Добавьте в файл package.json раздел: "scripts": { "build": "webpack -d" },
Ключ "-d" означает «development», если использовать -p «production», то результат будет минифицирован. В принципе, это не существенно, на возможность дебажить это не влияет. Выполните компиляцию, запустив в командной строке Node.js команду npm run build. Добавьте в .gitignore npm-*.log и generated/.
Обратите внимание, что даже в таком минимальной примере компиляция webpack занимает несколько секунд (у меня до 8с). Это много. Имеет смысл настроить автоматическую перекомпиляцию. С этой целью был ранее установлен пакет webpack-dev-server, и добавлены его конфигурационные параметры в секции devServer. Данная задача реализуется как фоновый процесс, запускаемый скриптом. Чтобы этот скрипт запустить, нужно добавить в секцию scripts файла package.json элемент "«dev»: «webpack-dev-server --content-base app/»" (здесь «dev» — алиас скрипта, можно использовать любой). Этим мы настраиваем процесс мониторинга изменений в папке app/, в которой лежит наш JSX скрипт.

Затем выполните команду npm run dev. В результате запустится Node.js Express сервер, который сначала выполнит обычную компиляцию webpack, закэширует всё, что нужно, и затем будет при каждом изменении инкрементально перекомпиливать. У этого сервера довольно много опций, отсылаю к оригинальной документации (ссылка ниже). Если требуется выполнять ещё какие-то действия в командной строке npm, придётся запустить новую, эта теперь занята.
И теперь совсем всё. Запускаете приложение и оно радуется миру.
И ещё кое-что
Для полноты картины надо упомянуть, что можно обойтись и без консоли. Для работы с npm существует довольно удобный maven-плагин frontend-maven-plugin. Фрагмент pom-файла с его участием приведён ниже:
Подключение плагинов maven
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.4.2.RELEASE</version> </plugin> <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.0</version> <configuration> <workingDirectory>src/main/resources/static</workingDirectory> </configuration> <executions> <execution> <id>install node and npm</id> <goals> <goal>install-node-and-npm</goal> </goals> <configuration> <nodeVersion>v6.9.4</nodeVersion> <npmVersion>4.1.1</npmVersion> </configuration> </execution> <execution> <id>npm install</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>install</arguments> <npmRegistryURL>http://some_url> </configuration> </execution> <execution> <id>npm run build</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>run build</arguments> </configuration> </execution> </executions> </plugin> </plugins>