How to integrate ReactJS in 1C-Bitrix with automatic generation of templates on the back-end using the example of the Globus network
This year, for the first time, ReactJS was introduced for the Globus hypermarket online store. The project is interesting because it extends the capabilities of the Bitrix platform and at the same time retains the ability to generate pages for search engines and does not litter the duplication of code and layout. This article describes how to link Bitrix components with ReactJS components using the php v8js module and save the main front-end part of the site.
Initially, the logic of the website of the online store was built on the library Marionette.js. Several years ago, this logic justified itself, but over time, the business requirements for the front-end functionality grew so much that every revision was accompanied by serious difficulties. Due to the high load, the speed of the front part of work decreased and left much to be desired. To solve this problem, we chose ReactJS, but there was a problem with rendering pages on the back-end and then associating parts of the pages with react components. In this case, our task was a gradual transition to ReactJS, because fundamental changes could lead to a complete reworking of the front. As a result, the choice fell on the following components:
The main difficulty in transferring mini-baskets and product cards to ReactJS consisted in instant synchronization of the quantity of goods in both components, i.e. if the basket contains 3 kg of carrots, then in the block for adding goods to the basket (picker) 3 kg should be displayed and when the quantity of goods changes in the mini-basket, the change should occur in the picker and vice versa. It was also necessary to level the lag of requests to the back-end, so that the interface worked as much as possible without delay.
"
An additional difficulty was the specificity of the store (food retail), where there is the concept of piece-weight goods. This is a product that is considered to be in kg, but the user buys it in pieces, for example, a watermelon, which the customer cannot partially buy, only entirely. Such a product for the user should be displayed in the number of pieces, but on the back-end is considered in kilograms.
In order not to duplicate the layout of components in the 1C-Bitrix and React templates, it was decided to put it on the React components. The name of the component in React should have coincided with the template component of the 1C-Bitrix system. To implement this idea, we used:
The first item is the v8js module which should convert our react components to a static layout in the php environment.
Next comes a small library from the React Community, which is a wrapper for easier initialization of React in the js environment of the v8js module.
And of course webpack, where without it. In conjunction with the babel, it allows you to use jsx-templates and the es6 standard for writing code. All examples will be presented in es6. It is quite simple, but if it is not clear with the move, then you should refresh the memory of it.
V8js module for php.
This module is a php extension that allows you to use the V8 Javascript Engine to execute js code in php. Installing is quite simple, like a regular PECL extension. The main thing is that you have libraries and V8 header files in the system.
Webpack
We use webpack to build the react and react components library. Assembly files for the front and back are slightly different. We collect 3 files:
The main difference between assembling for server rendering is that all libraries and components need to be put into a global object and libraries must be connected via the require function. The import directive for some reason does not work.
All source files are located in the local / templates / <template name> / src / directory.

The root of the project contains the webpack.config.js settings.

The contents of the assembly files can be found at the end of the article.
Npm and the following packages must be installed:
The
build is made by running the command: $ webpack.
Customization of the bitrix template engine
To register a custom engine in the 1C-Bitrix system, you need to add its settings to the global variable $ arCustomTemplateEngines. In the key you need to specify the code of your engine. We used “jsx”. In the values you need to specify the file extension of the template, the function of drawing the template. It is advisable to specify a sort below the value 100, so that the priority of our engine is above the standard.
Create a JSXEngine class with the following methods:
and the wrapper function for drawing the _JSXEngineExecute template, since The 1C-Bitrix system requires the registration of a particular function.
In order not to initialize the React instance each time, place it in a static variable and add an initialization method.
To draw the react component in the ReactJS class of the reactjs / react-php-v8js library, a special interface is implemented. The class constructor takes as input two parameters that must contain the react code of the module and all react components used in the project, collected via the webpack js-code. After initialization, we can render them. To do this, call the setComponent method of the component installation with the component name parameters and the props array. After the getMarkup method displays the contents of the component, and getJS - js-code to bind the component on the front. The getJS method requires itself in the parameters the identifier of the html-block in which the component is located. To do this, we have implemented a simple template for wrapping the rendered component into an html block. The settings of the block itself are made in a json-file, which is located in the template component of the 1C-Bitrix system.


Translating a component to a new template
We will show the translation of a component to React using a standard menu component as an example. The layout of the component has already been integrated into the standard template engine. React recommends the policy of breaking the functional into components. The components may be very small. Up to the hyperlink tag. We will not break our menu to such trifles, but we will still make a small decomposition.
Our menu uses nesting up to 3 levels. Therefore, it will be logical to break the menu functionality into 3 react components, each for a level. If you look closely, you will notice that the second-level menu items are arranged in two columns. This functionality should be placed in an additional component.

Thus, we have 4 components. Put them in the files TopMenu.js, SubMenuLevel2.js, SubMenuLevel3.js, TwoColumnItem.js in the src / components directory (see the rest of the code for the other components):

to make our template work, you need to create a template component of the 1C-1 system menu Bitrix The name of the pattern must match the name of the react component. Inside the template, you need to place the file with the extension corresponding to the settings of our engine. Inside the file you need to specify the html node in which our react component will be drawn.
This solution allows the use of react components on the back-end side and on the front-end side. Thus, we have the logic of displaying the functionality stored in one place, which greatly facilitates the support of the project.
The initial page rendering speed increased by almost 1s. Because now no need to repaint the house element in which the component is located. ReactJs picks it up on the fly. Also disappeared blinking elements on weak devices.
In the future, we plan to switch to the rendering of components on the back-end side through a node.js based service and the implementation of a single page application while maintaining the possibility of generating pages for SEO.
initialize.js

components.js

reactServer.js

SubMenuLevel2.js

SubMenuLevel3.js

TwoColumnItems.js

Why was this needed?
Initially, the logic of the website of the online store was built on the library Marionette.js. Several years ago, this logic justified itself, but over time, the business requirements for the front-end functionality grew so much that every revision was accompanied by serious difficulties. Due to the high load, the speed of the front part of work decreased and left much to be desired. To solve this problem, we chose ReactJS, but there was a problem with rendering pages on the back-end and then associating parts of the pages with react components. In this case, our task was a gradual transition to ReactJS, because fundamental changes could lead to a complete reworking of the front. As a result, the choice fell on the following components:
- Cards of goods;
- Mini basket;
- Menu.
The main difficulty in transferring mini-baskets and product cards to ReactJS consisted in instant synchronization of the quantity of goods in both components, i.e. if the basket contains 3 kg of carrots, then in the block for adding goods to the basket (picker) 3 kg should be displayed and when the quantity of goods changes in the mini-basket, the change should occur in the picker and vice versa. It was also necessary to level the lag of requests to the back-end, so that the interface worked as much as possible without delay.

An additional difficulty was the specificity of the store (food retail), where there is the concept of piece-weight goods. This is a product that is considered to be in kg, but the user buys it in pieces, for example, a watermelon, which the customer cannot partially buy, only entirely. Such a product for the user should be displayed in the number of pieces, but on the back-end is considered in kilograms.
How did you solve the problem?
In order not to duplicate the layout of components in the 1C-Bitrix and React templates, it was decided to put it on the React components. The name of the component in React should have coincided with the template component of the 1C-Bitrix system. To implement this idea, we used:
- V8js module for php;
- reactjs / react-php-v8js;
- webpack.
The first item is the v8js module which should convert our react components to a static layout in the php environment.
Next comes a small library from the React Community, which is a wrapper for easier initialization of React in the js environment of the v8js module.
And of course webpack, where without it. In conjunction with the babel, it allows you to use jsx-templates and the es6 standard for writing code. All examples will be presented in es6. It is quite simple, but if it is not clear with the move, then you should refresh the memory of it.
V8js module for php.
This module is a php extension that allows you to use the V8 Javascript Engine to execute js code in php. Installing is quite simple, like a regular PECL extension. The main thing is that you have libraries and V8 header files in the system.
Webpack
We use webpack to build the react and react components library. Assembly files for the front and back are slightly different. We collect 3 files:
- initialize.js -> app.js - an application for the front;
- reactServer.js -> reactBuild.js - react library for the server part;
- components.js -> reactComponents.js - a collection of react components.
The main difference between assembling for server rendering is that all libraries and components need to be put into a global object and libraries must be connected via the require function. The import directive for some reason does not work.
All source files are located in the local / templates / <template name> / src / directory.

The root of the project contains the webpack.config.js settings.

The contents of the assembly files can be found at the end of the article.
Npm and the following packages must be installed:
- babel;
- babel-cli;
- webpack;
- react;
- react-dom;
- underscore // optional.
The
build is made by running the command: $ webpack.
Customization of the bitrix template engine
To register a custom engine in the 1C-Bitrix system, you need to add its settings to the global variable $ arCustomTemplateEngines. In the key you need to specify the code of your engine. We used “jsx”. In the values you need to specify the file extension of the template, the function of drawing the template. It is advisable to specify a sort below the value 100, so that the priority of our engine is above the standard.
Create a JSXEngine class with the following methods:
- setEngine - registration template;
- init - initialize v8js via the wrapper of the reactjs / react-php-v8js library;
- execute - template rendering functionality
and the wrapper function for drawing the _JSXEngineExecute template, since The 1C-Bitrix system requires the registration of a particular function.
In order not to initialize the React instance each time, place it in a static variable and add an initialization method.
To draw the react component in the ReactJS class of the reactjs / react-php-v8js library, a special interface is implemented. The class constructor takes as input two parameters that must contain the react code of the module and all react components used in the project, collected via the webpack js-code. After initialization, we can render them. To do this, call the setComponent method of the component installation with the component name parameters and the props array. After the getMarkup method displays the contents of the component, and getJS - js-code to bind the component on the front. The getJS method requires itself in the parameters the identifier of the html-block in which the component is located. To do this, we have implemented a simple template for wrapping the rendered component into an html block. The settings of the block itself are made in a json-file, which is located in the template component of the 1C-Bitrix system.


Translating a component to a new template
We will show the translation of a component to React using a standard menu component as an example. The layout of the component has already been integrated into the standard template engine. React recommends the policy of breaking the functional into components. The components may be very small. Up to the hyperlink tag. We will not break our menu to such trifles, but we will still make a small decomposition.
Our menu uses nesting up to 3 levels. Therefore, it will be logical to break the menu functionality into 3 react components, each for a level. If you look closely, you will notice that the second-level menu items are arranged in two columns. This functionality should be placed in an additional component.

Thus, we have 4 components. Put them in the files TopMenu.js, SubMenuLevel2.js, SubMenuLevel3.js, TwoColumnItem.js in the src / components directory (see the rest of the code for the other components):

to make our template work, you need to create a template component of the 1C-1 system menu Bitrix The name of the pattern must match the name of the react component. Inside the template, you need to place the file with the extension corresponding to the settings of our engine. Inside the file you need to specify the html node in which our react component will be drawn.
Result
This solution allows the use of react components on the back-end side and on the front-end side. Thus, we have the logic of displaying the functionality stored in one place, which greatly facilitates the support of the project.
The initial page rendering speed increased by almost 1s. Because now no need to repaint the house element in which the component is located. ReactJs picks it up on the fly. Also disappeared blinking elements on weak devices.
In the future, we plan to switch to the rendering of components on the back-end side through a node.js based service and the implementation of a single page application while maintaining the possibility of generating pages for SEO.
application
initialize.js

components.js

reactServer.js

SubMenuLevel2.js

SubMenuLevel3.js

TwoColumnItems.js
