EN RU
Forum

Methodology

Technology

Toolbox

Libraries

Tutorials

Creating a dynamic BEM project

Introduction

Many modern applications exchange data in online mode, partially or fully reloading the page afterwards.

This article explains how to develop BEM projects that deal with dynamic data.

We will cover how to create two applications:

You will need:

Note: This article will not look at layout and client JS issues.

Hello World application

This is a dynamic application that outputs the words "Hello, World!" thus showing that it can launch and complete input/output operations.

Let's create this application and then extend it to the Social Services Search Robot.

To create a Hello World application:

The Hello World application is ready.

Note: If you had difficulties creating the application, search for a solution on the forum. If you can't find an answer, ask the experts in the forum.

Social Services Search Robot application

This is a dynamic application that displays recent tweets and videos by keyword.

The purpose of this application is to show the relationship between:

Demo

Application flow

The application flow can be visualized as follows:

Chart of Social Services Search Robot

BEM technologies used

We will use the following technologies:

BEMDECL

Defines the list of BEM entities used on the page.

In BEM, this list is called a declaration. The purpose of the declaration is to define what to include in the build and in what order.

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

Example of a declaration from the Hello World application:

// The `desktop.bundles/index/index.bemdecl.js` file
exports.blocks = [
    { name: 'root' }
];

As the example shows, the index.bemdecl.js file only defines the root block. This doesn't mean there are no other blocks on the page. You should treat the root block as the central "entry point" for the compiler. Other BEM entities are included in the build by dependencies. In the DEPS technology, declarations define the block from which the project build starts.

This example shows how a project is built by dependencies (from the Hello World application):

root(DECL)                      # The compiler searches for the index.bemdecl.js file
|
└──> root(DEPS)                 # The compiler searches for the root.deps.js file
     |
     └──> page(DEPS)            # The compiler searches for the page.deps.js file
          |
          ├──> header(DEPS)     # The compiler searches for the header.deps.js file
          |    |
          |    └──> ...
          |
          ├──> body(DEPS)       # The compiler searches for the body.deps.js file
          |    |
          |    └──> ...
          |
          └──> footer(DEPS)     # The compiler searches for the footer.deps.js file
               |
               └──> ...

Learn more about the BEMDECL technology.

DEPS

Defines dependencies between BEM entities that are spread out across the project's file system and not listed in the declarations.

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

Example of dependencies for the root block from the Hello World application:

// File `common.blocks/root/root.deps.js`
({
    shouldDeps: 'page'
})

Learn more about the DEPS technology.

BEMTREE

Part of the bem-xjst template engine that transforms data to BEMJSON.

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

Input and output of the template engine:

BEMTREE

Learn more about the BEMTREE technology.

BEMHTML

Part of the bem-xjst template engine that transforms the BEMJSON description to HTML.

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

Input and output of the template engine:

BEMHTML

Learn more about the BEMHTML technology.

i-bem.js

The client JavaScript framework for web development using the BEM methodology.

The JavaScript code is described in files with the .js extension.

It allows you to:

Learn more about the i-bem.js technology.

The projects' file system

Looks like this:

bem-project/
    .enb/                 # Config files for the ENB compiler
    common.blocks/        # Basic implementations of blocks
    desktop.bundles/      # Directories of project bundles
    development.blocks/   # Blocks that are integrated during development
    node_modules/         # Installed Node modules (packages)
    server/               # Directory with server code
    static/               # Root directory for distribution of static files
    .bemhint.js           # Bemhint linter configuration
    .borschik             # Borschik compiler configuration
    .eslintignore         # Excluding files and directories in ESLint
    .eslintrc             # ESLint configuration
    .gitignore            # Excluding files and directories in Git
    .stylelintrc          # Stylelint configuration
    .travis.yml           # Automatically starting linters in Continuous Integration
    nodemon.json          # Nodemon package configuration
    package.json          # Describing a project for npm
    README.md             # Text description of the project

Creating the application

Changing the project's file structure

Before moving on to work with the Twitter Search API and the YouTube Data API, let's change the structure of the Hello World application.

When you complete all the steps, the localhost:3000 address should still show the page with the following content:

Hello, World!
footer content

Note: If your code doesn't work, look for typos.

Installing additional modules

To run the application, install the following modules:

To install the modules, use the command:

$ npm install express passport passport-youtube-v3 twitter googleapis@^20.0.1 moment --save

Getting an OAuth token for Twitter

Twitter allows applications to make authenticated requests on behalf of the application itself. The API is accessed via the OAuth 2.0 open authorization protocol.

To get an OAuth token:

Use the token and keys you got in requests you send to the Twitter Search API. Learn more in Working with the Twitter Search API.

Important: Save the token and keys you received: Consumer Key and Consumer Secret. You will need them for the application configuration file.

Getting an OAuth token for Google

Google allows applications to make authenticated requests on behalf of the application itself. The API is accessed via the OAuth 2.0 open authorization protocol.

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

To get an OAuth token:

Use the Client ID and Client Secret you got in the requests you send to the YouTube Data API. Learn more in Working with the YouTube Data API.

Important: Save the keys you received: Client ID and Client Secret. You will need them for the application configuration file.

Configuring the application

Working with the Twitter Search API

The Twitter Search API lets you find tweets published over the last 7 days.

To configure the application for interacting with the API:

Working with the YouTube Data API

The YouTube Data API lets you search videos by keyword.

To configure the application for interacting with the API:

Layout

This article doesn't cover layout and the JavaScript client. Describing layout issues would make this document unreasonably large and difficult to use.

To prepare the layout, follow these steps:

Social Services Search Robot application is ready.

Note: If you had difficulties creating the application, search for a solution on the forum. If you can't find an answer, ask the experts in the forum.

FAQ

How do I encode a string using the Base64 method?

To encode a string:

Note: If you have any difficulties, use the online resource base64encode.org.

How do I get an OAuth token?

To get the token:

The OAuth server returns the token in JSON format:

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

Important: Save the token you received for the configuration file.