📜 ⬆️ ⬇️

Moving to the server side with bem-express

“First, you deny him, then you hate him, and then you cannot live without him.”
from the report of Artem Kurbatov "BEM: master class"


The BEM methodology exists for quite a long time and has been adopted by Google, EPAM Systems, BBC, Alfa-Bank. However, it is still of concern to the typical developer and mid-level project manager.




For some brave souls, studying BEM did not go beyond limiting the possibilities of CSS to produce more predictable results. And although BEM has long gone beyond the layout, still the question “Do you know BEM?” Can be heard: “Of course, this is about underscores in classes.”


If your understanding of BEM is close to this, I will answer you with the words of the employer when hiring a new graduate: “Forget about what you heard about BEM before.” The BEM methodology is as interesting as the majority knows nothing about it. To understand the beauty of BEM, you need to be aware of all the technologies, libraries, frameworks and tools that BEM provides. Examine them, remain an alien, a child who is surprised at what adults have come to terms with.


Table of contents



What is BEM for me?


Surely you have heard the stories, as daring geeks, having closed in the garage, invented another startup. The first successes allowed them to attract investment and enter the market with a stunning product. How did they manage to do this, how did they manage to withstand the peak loads and not get bogged down in eternal refactoring? How to not to as usual?


BEM is a life hack for startups. Compared to many other frameworks and technologies, starting to work with BEM requires some effort, but it pays off with architecture that provides sustainable extensibility. All technologies, frameworks and libraries of BEM initially laid down the principles of a declarative approach. And this is what makes them so incomprehensible at first glance and loved in the end.


After reading this article, you will not comprehend Zen BEM, but you will definitely be able to respond to adults that they learned how to create full-fledged dynamic BEM projects using not only CSS. And if tomorrow your application will suffer the fate of +10 K users per day, be calm - you will have time to celebrate this event.


Today we will talk about the new template repository for dynamic projects bem-express , which not only allows you to deploy a BEM project in one click, but also does automatic reassembly of the project and restarting the browser. On its basis, we will develop a dynamic application and describe the interaction process of various BEM technologies. We will deliberately not consider the issues of typesetting and client-side JavaScript, in order to avoid the fate of “underscore in classes”.


What will we develop?


Search application Social Services Search Robot (abbr. SSSR), which on demand will show the latest tweets and videos from YouTube.


We will use:



First you need to install:



Important! Users of the Windows operating system must additionally install Git Bash .

Used notation


To make the article brighter, we will paint a little:



Used technologies


In BEM, there is no separation of technology into major and minor. There is a set, and the choice of application is determined individually:



Learn more about the BEMJSON input format .

Let's look at them in more detail.


BEMDECL


Defines a list of BEM entities for the page.


Such a list in BEM is called a declaration . The task of the declaration is to determine what and in what order to connect to the assembly.


Declarations are described in files with the .bemdecl.js extension.


Example


 exports.blocks = [ { name: 'page' }, { name: 'header' }, { name: 'body' }, { name: 'footer' } ]; 

When the number of blocks goes over the line “easy to remember”, the problem arises of enumerating them in the necessary order. Therefore, they usually declare a particular block, which should be considered as the central "entry point".


All other BEM entities fall into an assembly according to dependencies .


Deps


Defines dependencies between BEM entities that are spaced apart in the file structure of the project and not reflected in the declaration.


Dependencies are described as a JavaScript object in files with the .deps.js extension.


Example


 /* page   header */ ({ block: 'page', shouldDeps: [ { block: 'header' } ] }) 

The name of the technology comes from the English word dependence and indicates the desire to connect to the assembly some kind of BEM entity. Students of BEM sometimes forget about the declarativeness of technologies and wonder: why for the block described in the template, its styles and scripts are not collected.


Remember: when you describe a template ( BEMHTML or BEMTREE ) with some kind of block inside (a child node), you simply add a new HTML element. In order for the styles and scripts of this block to fall into an assembly, it is necessary to describe the dependency on it.


For example, in order to add blocks header , body and footer to an assembly, it is necessary to describe dependence on them:


 /* page   header, body, footer */ ({ block: 'page', shouldDeps: [ 'header', 'body', 'footer' ] }) 

The following diagram shows the dependency build logic:


 index(DECL) #   page | └──> page(DEPS) #   page  header, body, footer | ├──> header(DEPS) | | | └──> ... | ├──> body(DEPS) | | | └──> ... | └──> footer(DEPS) | └──> ... 

BEMTREE


It is part of the bem-xjst template engine and converts data to BEMJSON.


Templates are described in BEMJSON format in files with the .bemtree.js extension.


Template input and output:


BEMTREE


BEMHTML


It is part of the bem-xjst template engine and converts the BEMJSON description of the page into HTML.


Templates are described in files with the .bemhtml.js extension.


Template input and output:


BEMHTML


i-bem.js


Client - side JavaScript framework for web development within the framework of the BEM methodology.


JavaScript code is described in files with a .js extension.


Allows:



Hello, World application


Programmers have a tradition: start programming in a new language or framework with the Hello, World application. The application typically displays the words “Hello, World” in the output stream, thereby demonstrating that it starts and performs I / O operations.


Let's create it and then expand it to the desired SSSR.


We need a local copy of the bem-express template repository . It can be done with git.


Note. For OS X or Linux users, all commands are executed in the terminal. Windows users will need Git Bash. Make sure Git Bash is running as administrator.

Template repository


When solving problems of developing dynamic applications within BEM, a template repository bem-express was created . It contains the necessary minimum of configuration files and solves a whole class of tasks, such as building a project, setting up linters, connecting libraries, etc.


By default, the main BEM libraries are connected to it:



Fast start


To create the Hello, World application:


  1. Clone bem-express:


     git clone https://github.com/bem/bem-express.git sssr-project 

    Note. This example uses bem-express version 2.00.

  2. Go to the project directory:


     cd sssr-project 

  3. Delete the versioning history of the source repository:


     rm -rf .git 

  4. Initialize your own Git repository:


     git init 

  5. Install dependencies:


     npm install 

    Note. Do not use root root when installing npm dependencies.

  6. Build the project and start the server:


     npm run dev 

    Note. For the assembly is responsible ENB .

    When you start the application in the terminal, a message appears stating that the server is running on port 3000:


    Server is listening on 3000 .


    Note. If port 3000 used by another program, it can be reassigned. For example, at 8000 :

    Method 1. Change the value when you start the application.
     PORT=8000 npm run dev 


    Method 2: Change the default value in the server/config.js .
     defaultPort: 8000, 

    On the computer started:


    • server - is responsible for processing dynamic data;
    • nodemon - monitors changes in the file structure and restarts the server;
    • chokidar - monitors changes in the files directories *.blocks/ and rebuilds the structure of the project;
    • livereload - refreshes the page in the browser.

  7. Open a browser and enter the address localhost: 3000 .


    A page should open with the following content:


     Index page content footer content 

    Note. If, when the application is launched in Windows, a notification from the Firewall is displayed:
    1. Disable the Public Network option.
    2. Install the Private Network option.
    3. Allow access.


  8. Open the server/index.js and make the following changes (see comments) to the code beginning with the line app.get('/', function(req, res) :


     /** *    GET-     * @function * @param {object} req - . * @param {object} res - . */ app.get('/', function(req, res) { var hello = 'Hello'; //   `hello` var world = 'World'; //   `world` render(req, res, { view: 'page-index', title: 'Main page', meta: { description: 'Page description', og: { url: 'https://site.com', siteName: 'Site name' } }, hello: hello, //   `hello`  `this.data.hello` world: world //   `world`  `this.data.world` }) }); 

  9. Open the common.blocks/page-index/page-index.bemtree.js and replace its contents with the following:


     block('page-index').content()(function() { //      `this` var data = this.data; //   : `data.hello: 'Hello'`, `data.world: 'World'` return data.hello + ', ' + data.world; }); 

    After saving, the server will automatically restart and the page content will change to:


     Hello, World footer content 


Hello, World app is ready.


Did not work out?


If you are having difficulty creating an application, look for a solution on the forum . If there is no ready answer, ask a question.


Social Services Search Robot application


Actually, we have reached the development stage of the SSSR application. Let me remind you that on request the application will display the latest tweets and videos from YouTube.


Immediately we will run into the near future - the application will look like this:



Scheme of the application


You saw her in the introductory part of the article.

Chart of Social Services Search Robot


Step 1. Request


The user sends a request to the server.


Step 2. Receive data


The application applies for data to the Twitter Search API and the YouTube Data API in accordance with the received request.


Step 3. BEMTREE-template


The application passes the received data to a BEMTREE template that converts the data to BEMJSON.


Step 4. BEMHTML-template


The application sends a BEMJSON BEMHTML template engine that converts BEMJSON to HTML.


Step 5. Sending the result to the user


The application returns the result (HTML page) to the user.


Node modules used


The basic implementation of Node remains as simple as possible. Instead of embedding all the possible components directly in Node, the developers provide additional functionality in the form of separate modules (packages).


The Node module system is modeled on the CommonJS system, the mechanism for creating interacting modules. A central place in the system is occupied by a contract that must be carried out by developers in order for their modules to interact normally with others.


All packages installed using the npm package manager are located in the node_modules directory.


The modules are connected using the require command. If the package is installed using npm, you do not need to specify the path. It is enough to specify the name:


 var express = require('express'); 

When you connect your own local module, you must specify the path to it:


 var someModule = require('./somefolder/somemodule'); 

An important feature of any module is that it must be designed to interact with Node. To do this, the module must be exported using module.exports :


 module.exports = { // some module }; 

The application will require the following modules:



You can install them with one command:


 npm install express passport passport-youtube-v3 twitter googleapis moment --save 

Preparation of the project structure


Before starting to write code, we will slightly change the structure of the Hello, World application taken as the basis.


Changes for:



Changes for static files


static


static directory



common.blocks directory



server directory



Changes for server code


server changes


server directory



Directory controllers



helpers directory



Directory middleware



Getting OAuth Tokens


Twitter and Google services store a variety of user data — tweets, Youtube videos, Mail messages, photos, and so on. To provide convenient access to this data from other applications or third-party services, they use the open authorization protocol OAuth 2.0 .


According to the protocol, the developer registers the application on the OAuth server and requests access to certain data. An authorized user permits or denies it.


Getting OAuth Token for Twitter


Twitter offers applications the ability to issue authenticated requests on behalf of the application itself.


Where to begin?


  1. Check out the documentation .
  2. Register the app and get the keys (Consumer Key, Consumer Secret).
  3. Install Postman any way you like.
  4. Encode the Consumer Key:Consumer Secret using the Base64 method.
  5. Get an OAuth token in exchange for a code .
  6. Use received tokens and keys in the Twitter Search API requests.


    Note. Postman will help you get an OAuth token using a POST request in exchange for code derived from the Base64 method.


How to encode a string?


To encode a string using the Base64 method:


  1. Create a string like: Consumer Key:Consumer Secret .


    Example


    xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg


    Note. You can get the Consumer Key and Consumer Secret keys by going to the Keys and Access Tokens tab of your application .

  2. Run a terminal or git bash.
  3. Run the echo -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64 echo -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64 .
  4. Copy the resulting code.


    Example


    eHZ6MWV2RlM0d0VFUFRHRUZQSEdFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==



Note. If you are having difficulty, use the online resource base64encode.org .

How to get an OAuth token in exchange for a code?


To get a token in exchange for a code:


  1. Run Postman.


    Note. By default, a tab opens in which you need to form a POST request to the Twitter OAuth server.

  2. Select the type of POST request.
  3. Enter the server address https://api.twitter.com/oauth2/token .
  4. Click the Headers tab.
  5. Enter the Authorization header with a value (Value field) Basic < Consumer Key:Consumer Secret> in the Key field.


    Example


    Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEdFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==


    Note. Basic indicates the basic authentication method.

  6. Enter a second Content-Type header with the value application/x-www-form-urlencoded;charset=UTF-8 .


    Example


    Content-Type: application/x-www-form-urlencoded;charset=UTF-8


  7. Click the Body tab.
  8. Select the x-www-form-urlencoded option.
  9. Enter in the Key field the request body grant_type with the value client_credentials .
  10. Click the Send button.


    The OAuth server will return the token in JSON format:


     { "token_type": "bearer", "access_token": "AAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAA" } 

    Important! Save received tokens and keys (Consumer Key and Consumer Secret). They are required for the application configuration file .


Getting OAuth Token for Google


Google offers applications the ability to issue authenticated requests on behalf of the application itself.


Note. The module passport-youtube-v3 is responsible for receiving and updating the OAuth token using a POST request in exchange for an authorization code.

Where to begin?


  1. Check out the documentation .
  2. Register the application and get Client ID and Client Secret.
  3. Enter the callback URL (in our case it is http://localhost:3000 ) in your application account.
  4. Use the received Client ID and Client Secret in requests to the YouTube Data API.

Important! Save the received keys (Client ID and Client Secret). They are required for the application configuration file .

Application configuration


After all the keys and tokens are received, they must be added to the application configuration file:



Work with Twitter Search API


The Twitter Search API allows you to find the latest or most popular tweets posted on Twitter.com in the last 7 days.


For a successful API call, you need to make the following changes:


twitter changes


Directory controllers



helpers directory



Work with YouTube Data API


YouTube Data API allows you to find videos published on Youtube.com. By default, the following resources are included in the search result set: video, channels, playlists.


For a successful API call, you need to make the following changes:


youtube-changes


server directory



Directory controllers



helpers directory



Directory middleware



Layout


We deliberately did not consider the issues of layout and client-side JavaScript. This would lead to a larger volume, and, therefore, to a lesser practical value of this article.


The layout process is reduced to the following steps:


  1. Delete all blocks from the common.blocks directory.
  2. Clone the following blocks into the common.blocks directory.
  3. Add logo.svg to the static/images directory.
  4. Restart the server: npm run dev .

The Social Services Search Robot application is ready.


Did not work out?


If you are having difficulty creating an application, look for a solution on the forum . If there is no ready answer, ask a question.


')

Source: https://habr.com/ru/post/337166/


All Articles