рдбреЙрдХрд░рдордзреНрдпреЗ VueJS + NodeJS + MongoDB рдНрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╕реЗ рдкреЕрдХреЗрдЬ рдХрд░рд╛рд╡реЗ

рдбреЙрдХрд░рдордзреНрдпреЗ VueJS + NodeJS + MongoDB рдНрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╕реЗ рдкреЕрдХреЗрдЬ рдХрд░рд╛рд╡реЗ
рдорд╛рдЧреАрд▓ рд▓реЗрдЦрд╛рд╡рд░реВрди рддреБрдореНрд╣реА рд╕рдордЬреВ рд╢рдХрддрд╛ рдХреА, рдореА рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдкреНрд░рдХрд▓реНрдкрд╛рдВрд╡рд░ рдХрд╛рдо рдХреЗрд▓реЗ. рдирд╡реАрди рд╕рдВрдШрд╛рддреАрд▓ рдкрд╣рд┐рд▓реЗ рджрд┐рд╡рд╕ рд╕рд╛рдорд╛рдиреНрдпрдд: рд╕рд╛рд░рдЦреЗрдЪ рдЬрд╛рддрд╛рдд: рдмреЕрдХреЗрдВрдбрд░ рдорд╛рдЭреНрдпрд╛рдмрд░реЛрдмрд░ рдмрд╕рддреЛ рдЖрдгрд┐ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реНрдерд╛рдкрд┐рдд рдЖрдгрд┐ рддреИрдирд╛рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЬрд╛рджреБрдИ рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЛ. рдбреЙрдХрд░ рдлреНрд░рдВрдЯ-рдПрдВрдб рдбреЗрд╡реНрд╣рд▓рдкрд░рд╕рд╛рдареА рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп рдЖрд╣реЗ рдХрд╛рд░рдг... рдмреЕрдХрдПрдВрдб рдмрд╣реБрддреЗрдХрджрд╛ PHP/Java/Python/C# рд╕реНрдЯреЕрдХрдЪреНрдпрд╛ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реЗрдгреАрдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛ рдЕрд╕рддреЛ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рд╕рд░реНрд╡ рдХрд╛рд╣реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рддреИрдирд╛рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдлреНрд░рдВрдЯрд▓рд╛ рдмреЕрдХрдПрдВрдб рд╡рд┐рдЪрд▓рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рдирд╕рддреЗ. рдлрдХреНрдд рдПрдХрд╛рдЪ рдард┐рдХрд╛рдгреА рдорд▓рд╛ рдкрд╛рд░рджрд░реНрд╢рдХ рдЙрдкрдпреЛрдЬрди, рд▓реЙрдЧ рдЖрдгрд┐ рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рдЪрд╛рдЪрдгреНрдпрд╛рдВрд╕рд╣ рдбреЙрдХрд░-рдЬреЗрдирдХрд┐рдиреНрд╕ рд╕рдВрдпреЛрдЬрди рджрд┐рд╕рд▓реЗ.

рдбреЙрдХрд░рдмрджреНрджрд▓ рдмрд░реЗрдЪ рддрдкрд╢реАрд▓рд╡рд╛рд░ рд▓реЗрдЦ рд▓рд┐рд╣рд┐рд▓реЗ рдЧреЗрд▓реЗ рдЖрд╣реЗрдд. рд╣рд╛ рд▓реЗрдЦ VueJS/Vue рд░рд╛рдЙрдЯрд░ рд╡рд╛рдкрд░реВрди рд╕рд┐рдВрдЧрд▓ рдкреЗрдЬ рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рди рддреИрдирд╛рдд рдХрд░рдгреНрдпрд╛рдмрджреНрджрд▓ рдмреЛрд▓реЗрд▓, рд╕рд░реНрд╡реНрд╣рд░рдЪрд╛ рднрд╛рдЧ NodeJS рд╕рд╣ RESTful API рдЪреНрдпрд╛ рд╕реНрд╡рд░реВрдкрд╛рдд рдЖрд╣реЗ рдЖрдгрд┐ MongoDB рдбреЗрдЯрд╛рдмреЗрд╕ рдореНрд╣рдгреВрди рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рддреЛ. рдбреЙрдХрд░ рдХрдВрдкреЛрдЬрдЪрд╛ рд╡рд╛рдкрд░ рдПрдХрд╛рдзрд┐рдХ рдХрдВрдЯреЗрдирд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдХреЗрд▓рд╛ рдЬрд╛рддреЛ.

рдбреЙрдХрд░ рдХрд╛ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ

рдбреЙрдХрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЙрдкрдпреЛрдЬрд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЛ. рд╡рд┐рдХрд╕рдХрд╛рд▓рд╛ рдпрд╛рдкреБрдвреЗ рд╕реНрд╡рддрдГ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рдорд╢реАрдирд╡рд░ рдЖрд╡реГрддреНрддреА рд╡рд┐рд╕рдВрдЧрддрддреЗрдЪрд╛ рд╕рд╛рдордирд╛ рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА. рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдлрдХреНрдд рдбреЙрдХрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ рдЖрдгрд┐ рдХрдиреНрд╕реЛрд▓рдордзреНрдпреЗ 1-2 рдХрдорд╛рдВрдб рдЯрд╛рдИрдк рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рд╣реЗ рдХрд░рдгреНрдпрд╛рдЪрд╛ рд╕рд░реНрд╡рд╛рдд рд╕реЛрдпреАрд╕реНрдХрд░ рдорд╛рд░реНрдЧ рд▓рд┐рдирдХреНрд╕рд╡рд░ рдЖрд╣реЗ.

рд╕реБрд░реВ рдХрд░рдгреЗ

рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛ рдЧреЛрджреА рдХрд╛рдордЧрд╛рд░ рдЖрдгрд┐ рдбреЙрдХрд░ рд░рдЪрдирд╛

рдлреЛрд▓реНрдбрд░ рд░рдЪрдирд╛

рдЖрдореНрд╣реА рдХреНрд▓рд╛рдпрдВрдЯ рдЖрдгрд┐ рд╕рд░реНрд╡реНрд╣рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдВрд╕рд╛рдареА 2 рдлреЛрд▓реНрдбрд░ рддрдпрд╛рд░ рдХрд░рддреЛ. .yml рд╡рд┐рд╕реНрддрд╛рд░ рдЕрд╕рд▓реЗрд▓реА рдлрд╛рдЗрд▓ рдПрдХ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЖрд╣реЗ рдбреЙрдХрд░ рд▓рд┐рд╣рд┐рдгреЗ, рдЬреЗрдереЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрдВрдЯреЗрдирд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЖрдгрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдЖрд╣реЗрдд.
Docker-compose.yml:

version: "3"
services:
  mongo:
    container_name: mongo
    hostname: mongo
    image: mongo
    ports:
      - "27017:27017"
  server:
    build: server/
    #command: node ./server.js #╨╖╨┤╨╡╤Б╤М ╨╝╨╛╨╢╨╜╨╛ ╨┐╨╡╤А╨╡╨╖╨░╨┐╨╕╤Б╨░╤В╤М CMD ╨╕╨╖ Dockerfile ╨▓ /server
    ports:
      - "3000:3000"
    links:
      - mongo
  client:
    build: client/
    #command: http-server ./dist #╨╖╨┤╨╡╤Б╤М ╨╝╨╛╨╢╨╜╨╛ ╨┐╨╡╤А╨╡╨╖╨░╨┐╨╕╤Б╨░╤В╤М CMD ╨╕╨╖ Dockerfile ╨▓ /client
    network_mode: host
    ports:
      - "8089:8089"
    depends_on:
      - server

рдЖрдореНрд╣реА рдбреЙрдХрд░рдордзреНрдпреЗ 3 рд╕реЗрд╡рд╛ рддрдпрд╛рд░ рдХрд░рддреЛ: NodeJS, MongoDB рдЖрдгрд┐ Vue рдордзреАрд▓ рд╕реНрдерд┐рд░ рд╕реЗрд╡рд╛рдВрд╕рд╛рдареА. рдХреНрд▓рд╛рдпрдВрдЯрд▓рд╛ рд╕рд░реНрд╡реНрд╣рд░рд╢реА рдЬреЛрдбрдгреНрдпрд╛рд╕рд╛рдареА рдЬреЛрдбрд▓реЗ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЖрд╣реЗ. рд╕рд░реНрд╡реНрд╣рд░ API рд╕рд╣ MongoDB рд▓рд┐рдВрдХ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рд╡рд╛рдкрд░рд╛ рдореЛрдВрдЧреЛ рд▓рд┐рдВрдХреНрд╕. рд╕рд░реНрд╡реНрд╣рд░, рдХреНрд▓рд╛рдпрдВрдЯ, рдореЛрдВрдЧреЛ - рд╕реЗрд╡рд╛рдВрдЪреА рдирд╛рд╡реЗ.

VueJS рдХреНрд▓рд╛рдпрдВрдЯ

рдлреЛрд▓реНрдбрд░рдордзреНрдпреЗ /рдХреНрд▓рд╛рдпрдВрдЯ рдЕрд░реНрдЬ VueJS рд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЖрд╣реЗ. рд╡рд╛рдкрд░реВрди рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рди рддрдпрд╛рд░ рдХреЗрд▓реЗ рд╣реЛрддреЗ рд╡реНрд╣реНрдпреВ рдХреНрд▓реА. рдкреНрд░рддрд┐рдорд╛ рддрдпрд╛рд░ рдХрд░рддрд╛рдирд╛, рдХреНрд▓рд╛рдпрдВрдЯ рдНрдкреНрд▓рд┐рдХреЗрд╢рди рдлреЛрд▓реНрдбрд░рдордзреАрд▓ рд╕реНрдерд┐рд░ рдлрд╛рдЗрд▓реНрд╕рдЪреНрдпрд╛ рд╕рдВрдЪрд╛рдордзреНрдпреЗ рддрдпрд╛рд░ рдХреЗрд▓реЗ рдЬрд╛рддреЗ /рдЬрд┐рд▓реНрд╣рд╛. рдбреЙрдХрд░рдлрд╛рдЗрд▓ рдкреНрд░рддрд┐рдорд╛ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрдорд╛рдВрдбрдЪреНрдпрд╛ рд╕рдВрдЪрд╛рдЪреЗ рд╡рд░реНрдгрди рдХрд░рддреЗ:

FROM node:10
WORKDIR /client
COPY ./package*.json ./
RUN npm install
RUN npm install -g http-server
COPY . .
RUN npm run build
EXPOSE 8081
CMD ["npm", "test:dev"]

рдХреГрдкрдпрд╛ рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛ рдХреА package.json рдЪреА рдкреНрд░рдд рддрдпрд╛рд░ рдХреЗрд▓реА рдЖрд╣реЗ рдЖрдгрд┐ рдЙрд░реНрд╡рд░рд┐рдд рдкреНрд░рдХрд▓реНрдк рдлрд╛рдЗрд▓реНрд╕рдордзреВрди рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ рд╕реНрдерд╛рдкрд┐рдд рдХреЗрд▓реА рдЖрд╣реЗ. рд╣реЗ рдХрд╛рд░реНрдпрдкреНрд░рджрд░реНрд╢рдирд╛рд╕рд╛рдареА рдХреЗрд▓реЗ рдЬрд╛рддреЗ, рдЬреЗрдгреЗрдХрд░реВрди /node_modules рдлреЛрд▓реНрдбрд░рдЪреА рд╕рд╛рдордЧреНрд░реА рдкреБрдиреНрд╣рд╛ рддрдпрд╛рд░ рдХрд░рддрд╛рдирд╛ рдХреЕрд╢реЗ рдХреЗрд▓реА рдЬрд╛рддреЗ. рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ рдХреЕрд╢ рдХреЗрд▓реА рдЬрд╛рддреЗ.

рд╢реЗрд╡рдЯреА, рдХрдВрдЯреЗрдирд░ рд╕реБрд░реВ рдЭрд╛рд▓реНрдпрд╛рд╡рд░, рдХрдорд╛рдВрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреЗрд▓реА рдЬрд╛рддреЗ npm run dev. рдпрд╛ рдЖрджреЗрд╢рд╛рдЪреЗ рд╡рд░реНрдгрди package.json рдордзреНрдпреЗ рдХреЗрд▓реЗ рдЖрд╣реЗ:


"scripts": {
	 "test:dev": "http-server dist -p 8081 -c 1 --push-state"
}

рдлреЛрд▓реНрдбрд░рдордзреВрди рдлрд╛рдЗрд▓реНрд╕ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рдареА /рдЬрд┐рд▓реНрд╣рд╛, рдЬрд╛рдЧрддрд┐рдХ рд╕реНрддрд░рд╛рд╡рд░ рд╕реНрдерд╛рдкрд┐рдд http-server, рдЖрдгрд┐ рд╡рд┐рдХрд╛рд╕-рдЕрд╡рд▓рдВрдмрдирд╛рдВрдордзреНрдпреЗ рдкреЕрдХреЗрдЬ spa-http-serverрдЬреЗрдгреЗрдХрд░реВрди Vue рд░рд╛рдЙрдЯрд░ рдпреЛрдЧреНрдпрд░рд┐рддреНрдпрд╛ рдХрд╛рд░реНрдп рдХрд░рддреЗ. --push-state рдзреНрд╡рдЬ index.html рд╡рд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рддреЛ. 1 рд╕реЗрдХрдВрджрд╛рдЪреНрдпрд╛ рдореВрд▓реНрдпрд╛рд╕рд╣ -c рдзреНрд╡рдЬ рдЬреЛрдбрд▓рд╛ рдЧреЗрд▓рд╛ http-рд╕рд░реНрд╡реНрд╣рд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯреНрд╕ рдХреЕрд╢реЗ рдХреЗрд▓реЗ рдирд╛рд╣реАрдд. рд╣реЗ рдПрдХ рдЪрд╛рдЪрдгреА рдЙрджрд╛рд╣рд░рдг рдЖрд╣реЗ; рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдХрд▓реНрдкрд╛рд╡рд░ nginx рд╡рд╛рдкрд░рдгреЗ рдЪрд╛рдВрдЧрд▓реЗ рдЖрд╣реЗ.

Vuex рд╕реНрдЯреЛрдЕрд░рдордзреНрдпреЗ рдЖрдореНрд╣реА рдПрдХ рдлреАрд▓реНрдб рддрдпрд╛рд░ рдХрд░рддреЛ apiHost: 'http://localhost:3000', рдЬреЗрдереЗ NodeJS Api рдкреЛрд░реНрдЯ рдиреЛрдВрджрдгреАрдХреГрдд рдЖрд╣реЗ. рдХреНрд▓рд╛рдпрдВрдЯ рднрд╛рдЧ рддрдпрд╛рд░ рдЖрд╣реЗ. рдЖрддрд╛ рдХреНрд▓рд╛рдпрдВрдЯрдХрдбреВрди рдорд╛рдЧрдЪреНрдпрд╛ рд╕рд░реНрд╡ рд╡рд┐рдирдВрддреНрдпрд╛ рдпрд╛ url рд╡рд░ рдЬрд╛рддрд╛рдд.

NodeJS рд╕рд░реНрд╡реНрд╣рд░ API

рдлреЛрд▓реНрдбрд░рдордзреНрдпреЗ /server рддрдпрд╛рд░ рдХрд░рд╛ рд╕рд░реНрд╡реНрд╣рд░.рдЬреЗ.рдПрд╕. рдЖрдгрд┐ рдбреЙрдХрд░рдлрд╛рдЗрд▓:


FROM node:10
WORKDIR /server
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

╨Т рд╕рд░реНрд╡реНрд╣рд░.рдЬреЗ.рдПрд╕. рдЕрд╕реЗ рд╕реВрдЪрд┐рдд url рдбреЗрдЯрд╛рдмреЗрд╕рд╕рд╛рдареА const url = 'mongodb://mongo:27017/';. рдХреНрд▓рд╛рдпрдВрдЯрдХрдбреВрди рдХреНрд░реЙрд╕-рдбреЛрдореЗрди рд╡рд┐рдирдВрддреНрдпрд╛рдВрдирд╛ рдЕрдиреБрдорддреА рджреЗрдгреЗ:


const clientUrl = 'http://localhost:8081';
const corsOptions = {
  origin: clientUrl,
  optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.use(cors());
app.all('/*', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', clientUrl);
  res.header('Access-Control-Allow-Headers', 'X-Requested-With');
  next();
});
  app.get('/getProducts', cors(corsOptions), (req, res) => {
    products.getContent
      .then(data => res.json(data), err => res.json(err));
  });
  app.get('/getUsers', cors(corsOptions), (req, res) => {
    db.getUsers()
      .then(data => res.json(data), err => res.json(err));
  });

рдирд┐рд╖реНрдХрд░реНрд╖

рдЖрддрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд┐рд░реЗрдХреНрдЯрд░реА рд╡рд░ рдЬрд╛рдКрди рд░рди рдХрд░реВ docker-compose build рдкреНрд░рддрд┐рдорд╛ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ docker-compose up рдХрдВрдЯреЗрдирд░ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рдареА. рд╕рдВрдШ 3 рдХрдВрдЯреЗрдирд░ рдЙрдЪрд▓реЗрд▓: рд╕рд░реНрд╡реНрд╣рд░, рдХреНрд▓рд╛рдпрдВрдЯ, рдореЛрдВрдЧреЛ. NodeJS рд╕рд░реНрд╡реНрд╣рд░рд╕рд╛рдареА, рддреБрдореНрд╣реА рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдлреЛрд▓реНрдбрд░рд╢реА рд▓рд┐рдВрдХ рдХрд░реВрди рд╣реЙрдЯ-рд░реАрд▓реЛрдб рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВ рд╢рдХрддрд╛. рдЖрдгрд┐ рд╡рд┐рдХрд╛рд╕рд╛рдзреАрди рдХреНрд▓рд╛рдпрдВрдЯ рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ рдЪрд╛рд▓рдд, рд╣реЙрдЯ рд░реАрд▓реЛрдбрд╕рд╣ рд╕реНрдерд╛рдирд┐рдХ рдкрд╛рддрд│реАрд╡рд░ рд▓реЙрдиреНрдЪ рдХреЗрд▓реЗ рдЬрд╛рд╡реЗ рд╕рд░реНрд╡реНрд╣рд░ ╨╕ рдореЛрдВрдЧреЛ. рд╕реНрд╡рддрдВрддреНрд░ рд╕реЗрд╡рд╛ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдлрдХреНрдд рддреНрдпрд╛рдЪреЗ рдирд╛рд╡ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рд╛ docker-compose up client. рдХрдзреАрддрд░реА рдХрд░рд╛рдпрд▓рд╛ рд╡рд┐рд╕рд░реВ рдирдХрд╛ prune рдЖрдгрд┐ рд╕рдВрд╕рд╛рдзрдиреЗ рдореЛрдХрд│реА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрдВрдЯреЗрдирд░, рдиреЗрдЯрд╡рд░реНрдХ рдЖрдгрд┐ рдкреНрд░рддрд┐рдорд╛ рд╣рдЯрд╡рдгреЗ.

рддреБрдореНрд╣реА рдкреВрд░реНрдг рдХреЛрдб рдкрд╛рд╣реВ рд╢рдХрддрд╛ рдпреЗрдереЗ. рдкреНрд░рдХрд▓реНрдк рдЕрджреНрдпрд╛рдк рд╡рд┐рдХрд╛рд╕рд╛рдзреАрди рдЖрд╣реЗ.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛