{"id":285595,"date":"2017-04-27T13:00:27","date_gmt":"2017-04-27T09:00:27","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=285595"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=285595","title":{"rendered":"Java \u0438 isomorphic React"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/a00\/62d\/591\/a0062d591c0c4d89b7e5b32c1521d77c.png\" alt=\"image\"\/><\/p>\n<p>  \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <a href=\"http:\/\/isomorphic.net\/\">\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/a> \u043d\u0430 <a href=\"https:\/\/facebook.github.io\/react\/\">React<\/a> \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Node.js \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u041d\u043e, \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043d\u0430 Java, \u0442\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0432 Java \u0432\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 javascript \u0434\u0432\u0438\u0436\u043e\u043a (Nashorn), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u043e\u043c HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.<\/p>\n<p>  \u041a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 React \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043d\u0430 Java, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 <a href=\"https:\/\/github.com\/complit-s\/java-examples\/tree\/master\/react-redux-isomorphic-example\">GitHub<\/a>. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b:<\/p>\n<ul>\n<li>\u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 Java \u0432 \u0441\u0442\u0438\u043b\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <a href=\"https:\/\/netty.io\/\">Netty<\/a> \u0438 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Java_API_for_RESTful_Web_Services\">JAX-RS<\/a> (\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"http:\/\/resteasy.jboss.org\/\">Resteasy<\/a>) \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 web-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>.<\/li>\n<li>Dependency Injection \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"http:\/\/docs.oracle.com\/javaee\/6\/tutorial\/doc\/giwhl.html\">CDI<\/a> (\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"http:\/\/docs.jboss.org\/weld\/reference\/latest\/en-US\/html\/environments.html#_java_se\">Weld SE<\/a>).<\/li>\n<li>\u0421\u0431\u043e\u0440\u043a\u0430 javascript \u0431\u0430\u043d\u0434\u043b\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/webpack.js.org\/\">Webpack 2<\/a>.<\/li>\n<li>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u0441\u0442\u0438\u043b\u0435\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/webpack.js.org\/configuration\/dev-server\/\">Webpack dev server<\/a>.<\/li>\n<\/ul>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 Java<\/h2>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Java \u0432 \u0441\u0442\u0438\u043b\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 (\u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0439 jar, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0441\u0435\u0440\u0432\u043b\u0435\u0442-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432). \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 CDI (Contexts and Dependency Injection), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0448\u0435\u043b \u0438\u0437 \u043c\u0438\u0440\u0430 Java EE, \u043d\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 Java SE. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f CDI \u2014 Weld SE \u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u0430\u044f \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438. \u0414\u043b\u044f CDI \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u043e\u0432 \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f CDI \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u0438 \u0434\u043b\u044f JAX-RS \u0438 Netty. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 src\/main\/resources\/META-INF \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b beans.xml (\u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 CDI), \u0440\u0430\u0437\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u041a\u043b\u0430\u0441\u0441\u044b, \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u043c\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 (\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0438 \u0440\u0443\u0447\u043d\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f).<\/p>\n<pre><code class=\"java\">\/\/ \u0421\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434.  public static void main(String[] args) {     \/\/ \u041b\u043e\u0433 JUL \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 SLF4J.     SLF4JBridgeHandler.removeHandlersForRootLogger();     SLF4JBridgeHandler.install();           LOG.info(&quot;Start application&quot;);           \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CDI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 http:\/\/weld.cdi-spec.org\/     final Weld weld = new Weld();     \/\/ \u0417\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u0441\u0430\u043c\u0438.     weld.property(Weld.SHUTDOWN_HOOK_SYSTEM_PROPERTY, false);           final WeldContainer container = weld.initialize();           \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Netty \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 JAX-RS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 CDI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c.     final CdiNettyJaxrsServer nettyServer = new CdiNettyJaxrsServer();           ...............           \/\/ \u0417\u0430\u043f\u0443\u0441\u043a web \u0441\u0435\u0440\u0432\u0435\u0440\u0430.     nettyServer.start();           ..............           \/\/ \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 TERM \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f.     try {         final CountDownLatch shutdownSignal = new CountDownLatch(1);         Runtime.getRuntime().addShutdownHook(new Thread(() -&gt; {             shutdownSignal.countDown();         }));                  try {             shutdownSignal.await();         } catch (InterruptedException e) {         }       } finally {                 \/\/ \u041e\u0441\u0442\u0430\u043d\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 CDI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.         nettyServer.stop();         container.shutdown();                   LOG.info(&quot;Application shutdown&quot;);                   SLF4JBridgeHandler.uninstall();     } }  \/\/ \u041a\u043b\u0430\u0441\u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f &quot;\u0432\u043f\u0440\u044b\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f&quot; \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b  @ApplicationScoped public class IncrementService {               .............. }  \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439  @NoCache @Path(&quot;\/&quot;) @RequestScoped @Produces(MediaType.TEXT_HTML + &quot;;charset=utf-8&quot;) public class RootResource {       \/**      * \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 {@link IncrementService}.      *\/     @Inject     private IncrementService incrementService;           .............. } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0441 CDI \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f JUnit \u043e\u0442 <a href=\"http:\/\/arquillian.org\/\">Arquillian<\/a>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u0441\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">\/**  * \u0422\u0435\u0441\u0442 \u0434\u043b\u044f {@link IncrementResource}.  *\/ @RunWith(Arquillian.class) public class IncrementResourceTest {           @Inject     private IncrementResource incrementResource;           \/**      * @return \u041d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 CDI.      *\/     @Deployment     public static JavaArchive createDeployment() {         return ShrinkWrap.create(JavaArchive.class)             .addClass(IncrementResource.class)             .addAsManifestResource(EmptyAsset.INSTANCE, &quot;beans.xml&quot;);     }             @Test     public void getATest() {         final Map&lt;String, Integer&gt; response = incrementResource.getA();                   assertNotNull(response.get(&quot;value&quot;));         assertEquals(Integer.valueOf(1), response.get(&quot;value&quot;));     }           ..............           \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u043e\u043a \u0434\u043b\u044f {@link IncrementService}. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f RequestScoped:      * Arquillian \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0435\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430.      * @return \u041c\u043e\u043a \u0434\u043b\u044f {@link IncrementService}.      *\/     @Produces     @RequestScoped     public IncrementService getIncrementService() {         final IncrementService service = mock(IncrementService.class);         when(service.getA()).thenReturn(1);         when(service.incrementA()).thenReturn(2);         when(service.getB()).thenReturn(2);         when(service.incrementB()).thenReturn(3);         return service;     }       } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 web \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 web-\u0441\u0435\u0440\u0432\u0435\u0440 \u2014 Netty. \u0414\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0438\u0439 \u0438\u0437 Java EE, JAX-RS. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 JAX-RS \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Resteasy. \u0414\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f Netty, CDI \u0438 Resteasy \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c <a href=\"https:\/\/github.com\/resteasy\/Resteasy\/tree\/master\/server-adapters\/resteasy-netty4-cdi\">resteasy-netty4-cdi<\/a>. JAX-RS \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 javax.ws.rs.core.Application. \u041e\u0431\u044b\u0447\u043d\u043e \u0432 \u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 JAX-RS \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 CDI \u0438 Resteasy \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 JAX-RS \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 CDI \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (\u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 JAX-RS: Path) \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b JAX-RS, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u043c\u0438 (\u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 JAX-RS: Provider). \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e Resteasy \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0438\u0437 <a href=\"http:\/\/docs.jboss.org\/resteasy\/docs\/3.1.2.Final\/userguide\/html\/index.html\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Netty \u0438 JAX-RS Application<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">public static void main(String[] args) {     ...............           \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Netty \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 JAX-RS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 CDI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c.     \/\/ \u0414\u043b\u044f JAX-RS \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Resteasy http:\/\/resteasy.jboss.org\/     final CdiNettyJaxrsServer nettyServer = new CdiNettyJaxrsServer();           \/\/ \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Netty (\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442).     final String host = configuration.getString(             AppConfiguration.WEBSERVER_HOST, AppConfiguration.WEBSERVER_HOST_DEFAULT);     nettyServer.setHostname(host);     final int port = configuration.getInt(             AppConfiguration.WEBSERVER_PORT, AppConfiguration.WEBSERVER_PORT_DEFAULT);     nettyServer.setPort(port);           \/\/ \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 JAX-RS.           final ResteasyDeployment deployment = nettyServer.getDeployment();     \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f JAX-RS (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b).     deployment.setInjectorFactoryClass(CdiInjectorFactory.class.getName());     \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u0435\u043d JAX-RS \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432.     deployment.setApplicationClass(ReactReduxIsomorphicExampleApplication.class.getName());           \/\/ \u0417\u0430\u043f\u0443\u0441\u043a web \u0441\u0435\u0440\u0432\u0435\u0440\u0430.     nettyServer.start();       ............... }   \/**  * \u041a\u043b\u0430\u0441\u0441 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u0445 \u0434\u043b\u044f JAX-RS  *\/ @ApplicationScoped @ApplicationPath(&quot;\/&quot;) public class ReactReduxIsomorphicExampleApplication extends Application {       \/**      * \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 CDI \u0434\u043b\u044f Resteasy.      *\/     @Inject     private ResteasyCdiExtension extension;       \/**      * @return \u0421\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u0434\u043b\u044f JAX-RS.      *\/     @Override     @SuppressWarnings(&quot;unchecked&quot;)     public Set&lt;Class&lt;?&gt;&gt; getClasses() {         final Set&lt;Class&lt;?&gt;&gt; result = new HashSet&lt;&gt;();           \/\/ \u0418\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f CDI \u0434\u043b\u044f Resteasy \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 JAX-RS.         result.addAll((Collection&lt;? extends Class&lt;?&gt;&gt;) (Object)extension.getResources());         \/\/ \u0418\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f CDI \u0434\u043b\u044f Resteasy \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u0445 JAX-RS.              result.addAll((Collection&lt;? extends Class&lt;?&gt;&gt;) (Object)extension.getProviders());         return result;     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u0441\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b (\u0431\u0430\u043d\u0434\u043b\u044b javascript, css, \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438) \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c \u0432 classpath (src\/main\/resources\/webapp), \u043e\u043d\u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u044f\u0442\u0441\u044f \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 jar \u0444\u0430\u0439\u043b. \u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0442\u0430\u043a\u0438\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a URL \u0432\u0438\u0434\u0430 {fileName:.*}.{ext}, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0444\u0430\u0439\u043b \u0438\u0437 classpath \u0438 \u043e\u0442\u0434\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0442\u0430\u0442\u0438\u043a\u0435<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">\/**  * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0444\u0430\u0439\u043b\u0430\u043c.  * &lt;p&gt;\u0417\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u044e\u0431\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u0438\u0434\u0430 {filename}.{ext}&lt;\/p&gt;  *\/ @Path(&quot;\/&quot;) @RequestScoped public class StaticFilesResource {           private final static Date START_DATE = DateUtils.setMilliseconds(new Date(), 0);           @Inject     private Configuration configuration;       \/**      * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0444\u0430\u0439\u043b\u0430\u043c. \u0424\u0430\u0439\u043b\u044b \u043e\u0442\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u0437 classpath.      * @param fileName \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0441 \u043f\u0443\u0442\u0435\u043c.      * @param ext \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430.      * @param uriInfo URL \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.      * @param request \u0414\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.      * @return \u041e\u0442\u0432\u0435\u0442 \u0441 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 404 - \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e.      * @throws Exception \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430.      *\/     @GET     @Path(&quot;{fileName:.*}.{ext}&quot;)     public Response getAsset(             @PathParam(&quot;fileName&quot;) String fileName,             @PathParam(&quot;ext&quot;) String ext,             @Context UriInfo uriInfo,             @Context Request request)                     throws Exception {         if(StringUtils.contains(fileName, &quot;nomin&quot;) || StringUtils.contains(fileName, &quot;server&quot;)) {                       \/\/ \u041d\u0435\u043c\u0438\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c.             return Response.status(Response.Status.NOT_FOUND)                     .build();                   }                   \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 ifModifiedSince \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0444\u0430\u0439\u043b\u044b \u043e\u0442\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u0437 classpath,         \/\/ \u0442\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.         final ResponseBuilder builder =                 request.evaluatePreconditions(START_DATE);         if (builder != null) {             \/\/ \u0424\u0430\u0439\u043b \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f.             return builder.build();         }                   \/\/ \u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0432 classpath.         final String fileFullName =                 &quot;webapp\/static\/&quot; + fileName + &quot;.&quot; + ext;         \/\/ \u041a\u043e\u043d\u0442\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0430.         final InputStream resourceStream =                 ResourceUtilities.getResourceStream(fileFullName);         if(resourceStream != null) {                    \/\/ \u0424\u0430\u0439\u043b \u0435\u0441\u0442\u044c, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435.             final String cacheControl = configuration.getString(                     AppConfiguration.WEBSERVER_HOST, AppConfiguration.WEBSERVER_HOST_DEFAULT);             \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0441 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0430.             return Response.ok(resourceStream)                     .type(URLConnection.guessContentTypeFromName(fileFullName))                     .cacheControl(CacheControl.valueOf(cacheControl))                     .lastModified(START_DATE)                     .build();         }           \/\/ \u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.         return Response.status(Response.Status.NOT_FOUND)                 .build();     }   } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h2>\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 HTML \u043d\u0430 React<\/h2>\n<p>  \u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 Java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c maven \u043f\u043b\u0430\u0433\u0438\u043d <a href=\"https:\/\/github.com\/eirslett\/frontend-maven-plugin\">frontend-maven-plugin<\/a>. \u041e\u043d \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 NodeJs \u043d\u0443\u0436\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0441\u0442\u0440\u043e\u0438\u0442 \u0431\u0430\u043d\u0434\u043b\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e webpack. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 Java \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 mvn (\u043b\u0438\u0431\u043e \u0432 IDE, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 maven). \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 javascript, \u0441\u0442\u0438\u043b\u0438, package.json, \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 webpack \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 src\/main\/frontend, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0431\u0430\u043d\u0434\u043b \u0432 src\/main\/resources\/webapp\/static\/assets.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 fronend-maven-plugin<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;plugin&gt;     &lt;groupId&gt;com.github.eirslett&lt;\/groupId&gt;     &lt;artifactId&gt;frontend-maven-plugin&lt;\/artifactId&gt;     &lt;configuration&gt;         &lt;nodeVersion&gt;v${node.version}&lt;\/nodeVersion&gt;         &lt;npmVersion&gt;${npm.version}&lt;\/npmVersion&gt;         &lt;installDirectory&gt;${basedir}\/src\/main\/frontend&lt;\/installDirectory&gt;         &lt;workingDirectory&gt;${basedir}\/src\/main\/frontend&lt;\/workingDirectory&gt;     &lt;\/configuration&gt;     &lt;executions&gt;         &lt;!-- \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 nodejs \u0438 npm \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. --&gt;         &lt;execution&gt;             &lt;id&gt;nodeInstall&lt;\/id&gt;             &lt;goals&gt;                 &lt;goal&gt;install-node-and-npm&lt;\/goal&gt;             &lt;\/goals&gt;         &lt;\/execution&gt;              &lt;!-- \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 npm \u0438\u0437 src\/main\/frontend\/package.json. --&gt;         &lt;execution&gt;             &lt;id&gt;npmInstall&lt;\/id&gt;             &lt;goals&gt;                 &lt;goal&gt;npm&lt;\/goal&gt;             &lt;\/goals&gt;                               &lt;\/execution&gt;         &lt;!-- \u0421\u0431\u043e\u0440\u043a\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e webpack. --&gt;         &lt;execution&gt;                 &lt;id&gt;webpackBuild&lt;\/id&gt;                 &lt;goals&gt;                     &lt;goal&gt;webpack&lt;\/goal&gt;                 &lt;\/goals&gt;                 &lt;configuration&gt;                     &lt;skip&gt;${webpack.skip}&lt;\/skip&gt;                     &lt;arguments&gt;${webpack.arguments}&lt;\/arguments&gt;                     &lt;srcdir&gt;${basedir}\/src\/main\/frontend\/app&lt;\/srcdir&gt;                     &lt;outputdir&gt;${basedir}\/src\/main\/resources\/webapp\/static\/assets&lt;\/outputdir&gt;                     &lt;triggerfiles&gt;                         &lt;triggerfile&gt;${basedir}\/src\/main\/frontend\/webpack.config.js&lt;\/triggerfile&gt;                         &lt;triggerfile&gt;${basedir}\/src\/main\/frontend\/package.json&lt;\/triggerfile&gt;                     &lt;\/triggerfiles&gt;                 &lt;\/configuration&gt;             &lt;\/execution&gt;     &lt;\/executions&gt;                     &lt;\/plugin&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 HTML \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0432 JAX-RS \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043b\u0430\u0441\u0441, \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 Provider, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 javax.ws.rs.ext.MessageBodyWriter, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 web-\u0437\u0430\u043f\u0440\u043e\u0441\u0430.<br \/>  \u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e \u0432 Java javascript \u0434\u0432\u0438\u0436\u043a\u0430 \u2014 Nashorn. \u042d\u0442\u043e \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a: \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0435\u0448\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0434\u0432\u0438\u0436\u043a\u0430, \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 HTML, \u0437\u0430\u0442\u0435\u043c \u043e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043f\u0443\u043b (<a href=\"https:\/\/commons.apache.org\/proper\/commons-pool\/\">Apache Commons Pool 2<\/a>).<\/p>\n<pre><code class=\"java\">\/**  * \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f web-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.  *\/ public class ViewResult {           private final String template;               private final Map&lt;String, Object&gt; viewData = new HashMap&lt;&gt;();           private final Map&lt;String, Object&gt; reduxInitialState = new HashMap&lt;&gt;();       .............. }   \/**  * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0445 \u0432 {@link ViewResult} \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 HTML.  * &lt;p&gt;  *  \u0415\u0441\u043b\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 React \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0432\u0438\u0436\u043a\u0430 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML (React Isomorphic),  *  \u0442\u043e \u0432 \u0448\u0430\u0431\u043b\u043e\u043d \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.  * &lt;\/p&gt;  *\/ @Provider @ApplicationScoped public class ViewResultBodyWriter implements MessageBodyWriter&lt;ViewResult&gt; {           ..............           private ObjectPool&lt;AbstractScriptEngine&gt; enginePool = null;               @PostConstruct     public void initialize() {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.         final boolean useIsomorphicRender = configuration.getBoolean(                 AppConfiguration.WEBSERVER_ISOMORPHIC, AppConfiguration.WEBSERVER_ISOMORPHIC_DEFAULT);                  final int minIdleScriptEngines = configuration.getInt(                 AppConfiguration.WEBSERVER_MIN_IDLE_SCRIPT_ENGINES, AppConfiguration.WEBSERVER_MIN_IDLE_SCRIPT_ENGINES_DEFAULT);                              LOG.info(&quot;Isomorphic render: {}&quot;, useIsomorphicRender);                   if(useIsomorphicRender) {             \/\/ \u0415\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 React \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u043b             \/\/ javascript \u0434\u0432\u0438\u0436\u043a\u043e\u0432. Javascript \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439,             \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 javascript.             final GenericObjectPoolConfig config = new GenericObjectPoolConfig();             config.setMinIdle(minIdleScriptEngines);                    enginePool = new GenericObjectPool&lt;AbstractScriptEngine&gt;(new ScriptEngineFactory(), config);         }     }           @PreDestroy     public void destroy() {         if(enginePool != null) {             enginePool.close();         }           }             ..............       @Override     public void writeTo(             ViewResult t,             Class&lt;?&gt; type,             Type genericType,             Annotation[] annotations,             MediaType mediaType,             MultivaluedMap&lt;String, Object&gt; httpHeaders,             OutputStream entityStream)                     throws IOException, WebApplicationException {           ..............                   if(enginePool != null && t.getUseIsomorphic()) {             \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f React \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.             try {                 \/\/ \u0418\u0437 \u043f\u0443\u043b\u0430 \u0434\u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a javascript.                 final AbstractScriptEngine scriptEngine = enginePool.borrowObject();                 try {                     \/\/ URL \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u0443\u0436\u0435\u043d react-router \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c.                     final String uri = uriInfo.getPath() +                             (uriInfo.getRequestUri().getQuery() != null                                 ? (String) (&quot;?&quot; + uriInfo.getRequestUri().getQuery())                                 : StringUtils.EMPTY);                     \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 React.                     final String htmlContent =                             (String)((Invocable)scriptEngine).invokeFunction(                                     &quot;renderHtml&quot;, uri, initialStateJson);                                       \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0442 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0432\u0448\u0435\u0433\u043e\u0441\u044f \u0434\u0432\u0438\u0436\u043a\u0430 \u0432 \u043f\u0443\u043b.                     enginePool.returnObject(scriptEngine);                                           viewData.put(HTML_CONTENT_KEY, htmlContent);                 } catch (Throwable e) {                     enginePool.invalidateObject(scriptEngine);                                           throw e;                 }             } catch (Exception e) {                 throw new WebApplicationException(e);             }         } else {             viewData.put(HTML_CONTENT_KEY, StringUtils.EMPTY);         }                         \/\/ \u041d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 HTML \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.         final String pageContent =                 StrSubstitutor.replace(templateContent, viewData);         entityStream.write(pageContent.getBytes(StandardCharsets.UTF_8));     }           \/**      * \u0424\u0430\u0431\u0440\u0438\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u0432\u0438\u0436\u043a\u0430 javascript.      *\/     private static class ScriptEngineFactory extends BasePooledObjectFactory&lt;AbstractScriptEngine&gt; {           @Override         public AbstractScriptEngine create()                 throws Exception {             LOG.info(&quot;Create new script engine&quot;);                           \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c nashorn \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 javascript \u0434\u0432\u0438\u0436\u043a\u0430.             final AbstractScriptEngine scriptEngine =                     (AbstractScriptEngine) new ScriptEngineManager().getEngineByName(&quot;nashorn&quot;);             try(final InputStreamReader polyfillReader =                     ResourceUtilities.getResourceTextReader(WEBAPP_ROOT + &quot;server-polyfill.js&quot;);                    final InputStreamReader serverReader =                     ResourceUtilities.getResourceTextReader(WEBAPP_ROOT + &quot;static\/assets\/server.js&quot;)) {                 \/\/ \u0418\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u0442 \u0432 nashorn, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.                 scriptEngine.eval(polyfillReader);                 \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c HTML \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.                 scriptEngine.eval(serverReader);             }                           \/\/ \u0417\u0430\u043f\u0443\u0441\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.             ((Invocable)scriptEngine).invokeFunction(                     &quot;initializeEngine&quot;, ResourceUtilities.class.getName());               return scriptEngine;         }           @Override         public PooledObject&lt;AbstractScriptEngine&gt; wrap(AbstractScriptEngine obj) {             return new DefaultPooledObject&lt;AbstractScriptEngine&gt;(obj);         }     }   } <\/code><\/pre>\n<p>  \u0414\u0432\u0438\u0436\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 Javascript \u0432\u0435\u0440\u0441\u0438\u0438 ECMAScript 5.1 \u0438 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043c\u043e\u0434\u0443\u043b\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u0430\u043a \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439, \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0432 \u0431\u0430\u043d\u0434\u043b\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e webpack. \u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u0431\u0430\u043d\u0434\u043b \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u044b, \u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430. \u041f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 Nashorn \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b (\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u044b\u0439 webpack \u0441 \u043a\u043b\u044e\u0447\u043e\u043c &#8212;optimize-minimize) \u2014 \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0435\u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b. \u0414\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043e\u0431\u043e\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d \u043a Webpack: <a href=\"https:\/\/github.com\/leftstick\/unminified-webpack-plugin\">unminified-webpack-plugin<\/a>. <\/p>\n<p>  \u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043b\u0438\u0431\u043e \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0434\u0432\u0438\u0436\u043a\u0430, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 Nashorn \u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0438\u0437 classpath. Nashorn \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0445 javascript \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a setInterval, setTimeout, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0441\u043a\u0440\u0438\u043f\u0442-polyfill. \u0417\u0430\u0442\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 HTML \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435). \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u044b\u0439, \u043d\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043e\u0449\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0430\u0440\u0443 \u0441\u0435\u043a\u0443\u043d\u0434, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043d\u0443\u0436\u0435\u043d \u043a\u0435\u0448 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0434\u0432\u0438\u0436\u043a\u043e\u0432.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u0438\u0444\u0438\u043b \u0434\u043b\u044f Nashorn<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 global \u0434\u043b\u044f javascript \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. var global = this;   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 window \u0434\u043b\u044f javascript \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \/\/ \u043e\u043d\u0438 \u0434\u0443\u043c\u0430\u044e\u0442 \u0447\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. var window = this;   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u043e\u0432, \u0432 Nashorn \u043d\u0435\u0442 console. var console = {     error: print,     debug: print,     warn: print,     log: print };   \/\/ \u0412 Nashorn \u043d\u0435\u0442 setTimeout, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c callback - \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441\u0440\u0430\u0437\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0442. function setTimeout(func, delay) {     func();     return 0; }; function clearTimeout() {   };   \/\/ \u0412 Nashorn \u043d\u0435\u0442 setInterval, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c callback - \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441\u0440\u0430\u0437\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0442. function setInterval(func, delay) {     func();     return 0; }; function clearInterval() {  }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 HTML \u043d\u0430 \u0443\u0436\u0435 \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0434\u0432\u0438\u0436\u043a\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f HTML, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e React, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e renderHtml, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 (src\\server.jsx). \u0412 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u0439 URL, \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e react-router, \u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 redux \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0432 \u0432\u0438\u0434\u0435 JSON). \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f redux, \u0432 \u0432\u0438\u0434\u0435 JSON, \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e window.INITIAL_STATE. \u042d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u0435\u0440\u0435\u0432\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0435 React \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043b\u043e \u0441 HTML, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p>  \u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 js \u0431\u0430\u043d\u0434\u043b\u0430:<\/p>\n<pre><code class=\"javascript\">  \/**  * \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.  * @param  {String} url              URL \u0442\u043a\u0443\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.  * @param  {String} initialStateJson \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f Redux \u0432 \u0441\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0441 JSON.  * @return {String}                  HTML, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 React.  *\/ renderHtml = function renderHtml(url, initialStateJson) {   \/\/ \u041f\u0430\u0440\u0441\u0438\u043d\u0433 JSON \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0434\u043b\u044f Redux.   const initialState = JSON.parse(initialStateJson)   \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u0434\u043b\u044f react-router (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u043e\u0438\u0445\u043e\u0434\u0438\u0442 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438).   const history = createMemoryHistory()   \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Redux \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e.   const store = configureStore(initialState, history, true)   \/\/ \u041e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u043d\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.   const htmlContent = {}     global.INITIAL_STATE = initialState     \/\/ \u042d\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c URL \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e react-router.   match({     routes: routes({history}),     location: url   }, (error, redirectLocation, renderProps) =&gt; {     if (error) {       throw error     }       \/\/ \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 HTML \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.     htmlContent.result = ReactDOMServer.renderToString(       &lt;AppContainer&gt;         &lt;Provider store={store}&gt;           &lt;RouterContext {...renderProps}\/&gt;         &lt;\/Provider&gt;       &lt;\/AppContainer&gt;     )   })     return htmlContent.result } <\/code><\/pre>\n<p>  \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 js \u0431\u0430\u043d\u0434\u043b\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Redux. const store = configureStore(initialState, history, false) \/\/ \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c HTML, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 React. const contentElement = document.getElementById(&quot;content&quot;)   \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React. ReactDOM.render(&lt;App store={store} history={history}\/&gt;, contentElement) <\/code><\/pre>\n<p>  <\/p>\n<h2>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 HTML\/\u0441\u0442\u0438\u043b\u0435\u0439<\/h2>\n<p>  \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c webpack dev server \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438\u043b\u0438 \u0441\u0442\u0438\u043b\u0435\u0439. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 webpack dev server \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0440\u0442\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 \u0432 package.json \u043a\u043e\u043c\u0430\u043d\u0434\u0443 npm run debug) \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u043b\u0435\u0442\u0443, \u044d\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a HTML \u043a\u043e\u0434\u0430, \u0442\u0430\u043a \u0438 \u043a\u043e\u0434\u0430 \u0441\u0442\u0438\u043b\u0435\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 webpack dev \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u0442\u0440\u043e\u0438\u0442 \u0431\u0430\u043d\u0434\u043b\u044b \u043d\u0430 \u043b\u0435\u0442\u0443, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e. <\/p>\n<p>  package.json:  <\/p>\n<pre><code>{   &quot;name&quot;: &quot;java-react-redux-isomorphic-example&quot;,   &quot;version&quot;: &quot;1.0.0&quot;,   &quot;private&quot;: true,   &quot;scripts&quot;: {     &quot;debug&quot;: &quot;cross-env DEBUG=true APP_PORT=8080 PROXY_PORT=8081 webpack-dev-server --hot --colors --inline&quot;,     &quot;build&quot;: &quot;webpack&quot;,     &quot;build:debug&quot;: &quot;webpack -p&quot;   } } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435.<\/p>\n<p>  \u0412 \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a webpack:<\/p>\n<ul>\n<li>\u0412 devtools \u0443\u043a\u0430\u0437\u0430\u0442\u044c module-source-map \u043b\u0438\u0431\u043e module-eval-source-map. \u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c module-source-map, \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u043b\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u2014 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0442\u043e\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0430 \u043f\u0440\u0438 \u043e\u0431\u0449\u0435\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043d\u043e, \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u0435\u043a \u0432 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u0445 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 Chrome, \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0443\u0431\u043b\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439, \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439. \u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c module-eval-source-map, \u0442\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0443\u0431\u043b\u0435\u0439, \u043f\u0440\u0430\u0432\u0434\u0430 \u0442\u043e\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0430 \u043f\u0440\u0438 \u043e\u0431\u0449\u0435\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c.\n<pre><code class=\"javascript\"> devtool: isHot    \/\/ \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043f\u0440\u0438 &quot;\u0433\u043e\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435.    ? &quot;module-source-map&quot; \/\/ &quot;module-eval-source-map&quot;    \/\/ \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0432 production.    : &quot;source-map&quot; <\/code><\/pre>\n<p>  <\/li>\n<li>\u0412 devServer \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 webpack: \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0444\u043b\u0430\u0433 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e.\n<pre><code class=\"javascript\">  \/\/ \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.   devServer: {     \/\/ \u0413\u043e\u0440\u044f\u0447\u0430\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430.     hot: true,     \/\/ \u041f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.     port: proxyPort,     \/\/ \u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.     proxy: {       &quot;*&quot;: `http:\/\/localhost:${appPort}`     }   } <\/code><\/pre>\n<p>  <\/li>\n<li>\u0412 entry \u0434\u043b\u044f \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c \u2014 \u043c\u0435\u0434\u0438\u0430\u0442\u043e\u0440: react-hot-loader\/patch.\n<pre><code class=\"javascript\">  entry: {     \/\/ \u0411\u0430\u043d\u0434\u043b \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430.     main: [&quot;es6-promise&quot;, &quot;babel-polyfill&quot;]       .concat(isHot         \/\/ \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f &quot;\u0433\u043e\u0440\u044f\u0447\u0430\u044f&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 - \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u043e\u0440.         ? [&quot;react-hot-loader\/patch&quot;]         \/\/ \u0421\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430.         : [])       .concat([&quot;.\/src\/main.jsx&quot;]),     \/\/ \u0411\u0430\u043d\u0434\u043b \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.     [isProduction ? &quot;server.min&quot; : &quot;server&quot;]:       [&quot;es6-promise&quot;, &quot;babel-polyfill&quot;, &quot;.\/src\/server.jsx&quot;]   } <\/code><\/pre>\n<p>  <\/li>\n<li>\u0412 output \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 publicPath \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 URL webpack dev \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\n<pre><code class=\"javascript\">  output: {     \/\/ \u041f\u0443\u0442\u044c \u0434\u043b\u044f \u0431\u0430\u043d\u0434\u043b\u043e\u0432.     path: Path.join(__dirname, &quot;..\/resources\/webapp\/static\/assets\/&quot;),     publicPath: isHot       \/\/ \u0421\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0441 &quot;\u0433\u043e\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c).       ? `http:\/\/localhost:${proxyPort}\/assets\/`       : &quot;\/assets\/&quot;,     filename: &quot;[name].js&quot;,     chunkFilename: &quot;[name].js&quot;   } <\/code><\/pre>\n<p>  <\/li>\n<li>\u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0430 babel \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438: syntax-dynamic-import \u0438 react-hot-loader\/babel.\n<pre><code class=\"javascript\">  {         \/\/ \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a JavaScript (Babel).         test: \/\\.(js|jsx)?$\/,         exclude: \/(node_modules)\/,         use: [           {             loader: isHot               \/\/ \u0414\u043b\u044f &quot;\u0433\u0430\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c babel.               ? &quot;babel-loader?plugins[]=syntax-dynamic-import,plugins[]=react-hot-loader\/babel&quot;               : &quot;babel-loader&quot;           }         ]       } <\/code><\/pre>\n<p>  <\/li>\n<li>\u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0430 \u0441\u0442\u0438\u043b\u0435\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0430 style-loader. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0442\u0438\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u043d\u043b\u0430\u0439\u043d\u0438\u0442\u0441\u044f \u0432 javascript \u043a\u043e\u0434. \u041f\u0440\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u0439 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0438\u043b\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 production) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043d\u0434\u043b\u0430 \u0441\u0442\u0438\u043b\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e extract-text-webpack-plugin.\n<pre><code class=\"javascript\"> {         \/\/ \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a \u0441\u0442\u0438\u043b\u0435\u0439 CSS.         test: \/\\.css$\/,         use: isHot         \/\/ \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 &quot;\u0433\u043e\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0438\u043b\u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u0430\u043d\u0434\u043b \u0441 JavaScript \u043a\u043e\u0434\u043e\u043c.           ? [&quot;style-loader&quot;].concat(cssStyles)           \/\/ \u0412 production - \u0441\u0442\u0438\u043b\u0438 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b.           : ExtractTextPlugin.extract({use: cssStyles, publicPath: &quot;..\/assets\/&quot;})       } <\/code><\/pre>\n<p>  <\/li>\n<li>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d Webpack.NamedModulesPlugin \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439.  <\/li>\n<\/ul>\n<p>  \u0412 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u0432\u0445\u043e\u0434\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.<\/p>\n<pre><code class=\"javascript\">\/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React. ReactDOM.render(&lt;App store={store} history={history}\/&gt;, contentElement)   if (module.hot) {   \/\/ \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 &quot;\u0433\u043e\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.   module.hot.accept(&quot;.\/containers\/app&quot;, () =&gt; {     const app = require(&quot;.\/containers\/app&quot;).default       ReactDOM.render(app({store, history}), contentElement)   }) } <\/code><\/pre>\n<p>  \u0412 \u043c\u043e\u0434\u0443\u043b\u0435, \u0433\u0434\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 redux, \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f. \u042d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 redux-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0438 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u043c\u0438 \u0441\u0442\u0430\u0440\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438.<\/p>\n<pre><code class=\"javascript\">const store = createStore(reducers, initialState, applyMiddleware(...middleware))     if (module.hot) {     \/\/ \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 &quot;\u0433\u043e\u0440\u044f\u0447\u0435\u0439&quot; \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 Redux-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.     module.hot.accept(&quot;.\/reducers&quot;, () =&gt; {       const nextRootReducer = require(&quot;.\/reducers&quot;)         store.replaceReducer(nextRootReducer)     })   }     return store <\/code><\/pre>\n<p>  \u0412 \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 Java \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 frontend-maven-plugin \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 React: \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438 \u0441\u0442\u0438\u043b\u0435\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c webpack dev server, \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u0434\u0438\u0441\u043a \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435\u043c \u0431\u0430\u043d\u0434\u043b\u043e\u0432. \u0414\u043b\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e frontend-maven-plugin \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 React \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c maven: frontendDevelopment (\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 IDE, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 maven). \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0431\u0430\u043d\u0434\u043b\u044b \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e webpack.<br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/327480\/\"> https:\/\/habrahabr.ru\/post\/327480\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/a00\/62d\/591\/a0062d591c0c4d89b7e5b32c1521d77c.png\" alt=\"image\"\/><\/p>\n<p>  \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <a href=\"http:\/\/isomorphic.net\/\">\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/a> \u043d\u0430 <a href=\"https:\/\/facebook.github.io\/react\/\">React<\/a> \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Node.js \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u041d\u043e, \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043d\u0430 Java, \u0442\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0432 Java \u0432\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 javascript \u0434\u0432\u0438\u0436\u043e\u043a (Nashorn), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u043e\u043c HTML \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.<\/p>\n<p>  \u041a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 React \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043d\u0430 Java, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 <a href=\"https:\/\/github.com\/complit-s\/java-examples\/tree\/master\/react-redux-isomorphic-example\">GitHub<\/a>. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b:<\/p>\n<ul>\n<li>\u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 Java \u0432 \u0441\u0442\u0438\u043b\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <a href=\"https:\/\/netty.io\/\">Netty<\/a> \u0438 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Java_API_for_RESTful_Web_Services\">JAX-RS<\/a> (\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"http:\/\/resteasy.jboss.org\/\">Resteasy<\/a>) \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 web-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>.<\/li>\n<li>Dependency Injection \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"http:\/\/docs.oracle.com\/javaee\/6\/tutorial\/doc\/giwhl.html\">CDI<\/a> (\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"http:\/\/docs.jboss.org\/weld\/reference\/latest\/en-US\/html\/environments.html#_java_se\">Weld SE<\/a>).<\/li>\n<li>\u0421\u0431\u043e\u0440\u043a\u0430 javascript \u0431\u0430\u043d\u0434\u043b\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/webpack.js.org\/\">Webpack 2<\/a>.<\/li>\n<li>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u0434\u0435\u0440\u0438\u043d\u0433\u0430 HTML \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React.<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u00ab\u0433\u043e\u0440\u044f\u0447\u0435\u0439\u00bb \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u0441\u0442\u0438\u043b\u0435\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/webpack.js.org\/configuration\/dev-server\/\">Webpack dev server<\/a>.<\/li>\n<\/ul>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-285595","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/285595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=285595"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/285595\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=285595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=285595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=285595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}