React рдФрд░ Node.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрддрд┐рд╢реАрд▓ PDF рдмрдирд╛рдПрдБ

рд╕рд╛рдордЧреНрд░реА, рдЬрд┐рд╕рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдЖрдЬ рд╣рдо рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, HTML-рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЧрддрд┐рд╢реАрд▓ рдкреАрдбреАрдПрдл-рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИред рдЕрд░реНрдерд╛рддреН, рд╣рдо рдХреБрдЫ рд╡рд╕реНрддреБрдУрдВ рдпрд╛ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рднреБрдЧрддрд╛рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЗрдирд╡реЙрдЗрд╕ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рд╕рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдбрд╛рдпрдирд╛рдорд┐рдХ рдбреЗрдЯрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрдерд┐рддрд┐ рдХреЗ рд░рд╛рдЬреНрдп рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЖрдзрд╛рд░ create-react-app рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рд╕рд░реНрд╡рд░ рд╣рд┐рд╕реНрд╕рд╛ Node.js рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред



рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд▓реЗрдЦрдХ рдиреЗ рдиреЛрдЯ рдХрд┐рдпрд╛ рдХрд┐ рдЙрдиреНрд╣реЛрдВрдиреЗ рдПрдХ рд╡реАрдбрд┐рдпреЛ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╡реАрдбрд┐рдпреЛ рджреЗрдЦрдиреЗ рдФрд░ рд▓реЗрдЦ рдкрдврд╝рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд▓реЗрдЦ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХрд┐рдо рдХрд░реЗрдВ, рдлрд┐рд░ рд╡реАрдбрд┐рдпреЛ рдЪрд╛рд▓реВ рдХрд░реЗрдВ рдФрд░ рдЙрд╕ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдПрдВ рдЬреЛ рдЖрдк рд╡рд╣рд╛рдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдмрд╕ рд▓реЗрдЦ рдкрдврд╝реЗрдВред

рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрдорд╛рдг


рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ рдФрд░ рдЙрд╕ рдкрд░ рдЬрд╛рдПрдВ:

mkdir pdfGenerator && cd pdfGenerator 

рдПрдХ рдирдпрд╛ рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдПрдВ:

 create-react-app client 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдирд┐рд░реНрдорд╛рдг рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:

 cd client && npm i -S axios file-saver 

рдПрдХ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдмрдирд╛рдПрдБред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ server рдлрд╝реЛрд▓реНрдбрд░ рдмрдирд╛рдПрдБ рдФрд░ рдЙрд╕ рдкрд░ рдЬрд╛рдПрдБред рдЗрд╕рдореЗрдВ, index.js рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ рдФрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╢реБрд░реВ рдХрд░реЗрдВ:

 mkdir server && cd server && touch index.js && npm init 

рдпрд╣рд╛рдБ, package.json , рдмрд╕ рдХрдИ рдмрд╛рд░ Enter рджрдмрд╛рдПрдБред рдЙрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд░реНрд╡рд░ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

 npm i -S express body-parser cors html-pdf 

рдЕрдм, client/package.json рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рд╡рд░рдг рдЕрдиреБрднрд╛рдЧ рдХреЗ рдКрдкрд░, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝реЗрдВ:

 "proxy": "http://localhost:5000/" 

рдпрд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рд╕реЗ рд╕реНрдерд╛рдиреАрдп рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред

рдЕрдм рдЖрдкрдХреЛ рдЯрд░реНрдорд┐рдирд▓ рдХреА рджреЛ рд╡рд┐рдВрдбреЛ рдЦреЛрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдкрд╣рд▓реА рд╡рд┐рдВрдбреЛ рдореЗрдВ, client рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

 npm start 

рджреВрд╕рд░реА рд╡рд┐рдВрдбреЛ рдореЗрдВ, server рдлрд╝реЛрд▓реНрдбрд░ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

 nodemon index.js 

рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЧреНрд░рд╛рд╣рдХ рд╕реЗрдЯрдЕрдк


рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдЧреНрд░рд╛рд╣рдХ рд╣рд┐рд╕реНрд╕рд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд▓рдЧреЗрдЧрд╛ред

рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрд╡реЗрджрди src/App.js рдЧреНрд░рд╛рд╣рдХ рднрд╛рдЧ рдХреЗ src/App.js , рд╣рдо рдХреЛрдб рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ:

 import axios from 'axios'; import { saveAs } from 'file-saver'; 

рдЙрд╕рдХреЗ рдмрд╛рдж, рдШрдЯрдХ рд╡рд┐рд╡рд░рдг рдХреЗ рд╢реАрд░реНрд╖ рдкрд░, рд░рд╛рдЬреНрдп рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВ:

 state = {   name: 'Adrian',   receiptId: 0,   price1: 0,   price2: 0, } 

рдЖрдЗрдП, рдПрдкреНрд▓рд┐рдХреЗрд╢рди create-react-app рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдореЗрдВ рдмрдирд╛рдП рдЧрдП рдорд╛рдирдХ JSX рдорд╛рд░реНрдХрдЕрдк рдХреЛ рд╣рдЯрд╛рдПрдВ рдФрд░ render() рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯрд╛рдПрдВред рдЗрд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбрд╛рд▓реЗрдВ:

 <div className="App">   <input type="text" placeholder="Name" name="name" onChange {this.handleChange}/>   <input type="number" placeholder="Receipt ID" name="receiptId"  onChange={this.handleChange}/>   <input type="number" placeholder="Price 1" name="price1" onChange={this.handleChange}/>   <input type="number" placeholder="Price 2" name="price2" onChange={this.handleChange}/>   <button onClick={this.createAndDownloadPdf}>Download PDF</button></div> 

рдЪрд▓рд┐рдП handleChange рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдЗрдирдкреБрдЯ рдлреАрд▓реНрдб рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯреЗрдЯ рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛:

 handleChange = ({ target: { value, name }}) => this.setState({ [name]: value }) 

рдЕрдм рд╣рдо рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ POST рдЕрдиреБрд░реЛрдз рдмрдирд╛рдирд╛ рд╣реИред рдЕрдиреБрд░реЛрдз рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реНрдерд┐рддрд┐ рднреЗрдЬрддрд╛ рд╣реИ:

 createAndDownloadPdf = () => {   axios.post('/create-pdf', this.state) } 

рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрдХреНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВ, рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рдкрд░ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕рд░реНрд╡рд░ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ, рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рд╡рд╛рдкрд╕ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред

рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рд░реНрд╡рд░ рд╕реЗрдЯрдЕрдк


рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд░реНрд╡рд░ рднрд╛рдЧ рдореЗрдВ рдХреЗрд╡рд▓ рджреЛ рдорд╛рд░реНрдЧ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗред рдкреАрдбреАрдПрдл рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреА рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИред рджреВрд╕рд░рд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдлрд╛рдЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, index.js рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдЖрдпрд╛рдд рдХрд░реЗрдВ:

 const express = require('express'); const bodyParser = require('body-parser'); const pdf = require('html-pdf'); const cors = require('cors'); 

рд╣рдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреЛрд░реНрдЯ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВ:

 const app = express(); const port = process.env.PORT || 5000; 

рдХреНрд╡реЗрд░реА рдкрд╛рд░реНрд╕рд░ рд╕реЗрдЯ рдХрд░реЗрдВред рд╣рдореЗрдВ рдЬреЛ рдЪрд╛рд╣рд┐рдП рд╡рд╣ req.body рд░реВрдк рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред рд╣рдо CORS рдХреЛ рднреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рд╣рдорд╛рд░реА Cross-Origin Request Blocked рддреНрд░реБрдЯрд┐ рд╣рдорд╛рд░реЗ рдХрд╛рдо рдореЗрдВ рд╣рд╕реНрддрдХреНрд╖реЗрдк рди рдХрд░реЗ:

 app.use(cors()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); 

рдЙрд╕рдХреЗ рдмрд╛рдж, рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░реЗрдВ:

 app.listen(port, () => console.log(`Listening on port ${port}`)); 

рдЕрдм рд╣рдо рдкреАрдбреАрдПрдл рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдХреЛрдб рд╕реЗ рдирд┐рдкрдЯ рд╕рдХрддреЗ рд╣реИрдВред

PDF рдХреЗ рд▓рд┐рдП HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛рдПрдВ


рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рддреЗ рд╕рдордп рд╣рдореЗрдВ рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХрд╛ рдЦрд╛рдХрд╛ рдмрдирд╛рдиреЗ рдореЗрдВ, рдЕрдирдВрдд рд╕рдВрднрд╛рд╡рдирд╛рдПрдВ рд╣рдорд╛рд░реЗ рд╕рд╛рдордиреЗ рдЦреБрд▓ рдЬрд╛рддреА рд╣реИрдВред рд╢реБрджреНрдз рдПрдЪрдЯреАрдПрдордПрд▓ рдФрд░ рд╕реАрдПрд╕рдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдИ рдЬрд╛ рд╕рдХрдиреЗ рд╡рд╛рд▓реА рд╣рд░ рдЪреАрдЬ рдХреЛ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред server рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ documents рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ, рдЙрд╕ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдЗрд╕рдореЗрдВ index.js рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ:

 mkdir documents && cd documents && touch index.js 

рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рд╕реЗ, рд╣рдо рдПрдХ рддреАрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ HTML рдХреЛрдб рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧрд╛ред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рд╡рд░реНрдгрди рд╣рдо рдпрд╣рд╛рдВ рднреА рдХрд░реЗрдВрдЧреЗред

 module.exports = ({ name, price1, price2, receiptId }) => { ... } 

рдпрд╣рд╛рдБ рдореИрдВ рдЖрдкрдХреЛ рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛, рдФрд░ рдЖрдк рдЗрд╕реЗ рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХреЙрдкреА рдХрд░ рд▓реЗрдВред рд▓реЗрдХрд┐рди рдЖрдк рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред

server/documents рдлреЛрд▓реНрдбрд░ рд╕реЗ index.js рдХреЛрдб рдХреЛ рдирд┐рдореНрди рдлреЙрд░реНрдо рдореЗрдВ index.js :

 module.exports = ({ name, price1, price2, receiptId }) => {    const today = new Date(); return `    <!doctype html>    <html>       <head>          <meta charset="utf-8">          <title>PDF Result Template</title>          <style>             .invoice-box {             max-width: 800px;             margin: auto;             padding: 30px;             border: 1px solid #eee;             box-shadow: 0 0 10px rgba(0, 0, 0, .15);             font-size: 16px;             line-height: 24px;             font-family: 'Helvetica Neue', 'Helvetica',             color: #555;             }             .margin-top {             margin-top: 50px;             }             .justify-center {             text-align: center;             }             .invoice-box table {             width: 100%;             line-height: inherit;             text-align: left;             }             .invoice-box table td {             padding: 5px;             vertical-align: top;             }             .invoice-box table tr td:nth-child(2) {             text-align: right;             }             .invoice-box table tr.top table td {             padding-bottom: 20px;             }             .invoice-box table tr.top table td.title {             font-size: 45px;             line-height: 45px;             color: #333;             }             .invoice-box table tr.information table td {             padding-bottom: 40px;             }             .invoice-box table tr.heading td {             background: #eee;             border-bottom: 1px solid #ddd;             font-weight: bold;             }             .invoice-box table tr.details td {             padding-bottom: 20px;             }             .invoice-box table tr.item td {             border-bottom: 1px solid #eee;             }             .invoice-box table tr.item.last td {             border-bottom: none;             }             .invoice-box table tr.total td:nth-child(2) {             border-top: 2px solid #eee;             font-weight: bold;             }             @media only screen and (max-width: 600px) {             .invoice-box table tr.top table td {             width: 100%;             display: block;             text-align: center;             }             .invoice-box table tr.information table td {             width: 100%;             display: block;             text-align: center;             }             }          </style>       </head>       <body>          <div class="invoice-box">             <table cellpadding="0" cellspacing="0">                <tr class="top">                   <td colspan="2">                      <table>                         <tr>                            <td class="title"><img src="https://i2.wp.com/cleverlogos.co/wp-content/uploads/2018/05/reciepthound_1.jpg?fit=800%2C600&ssl=1"                               style="width:100%; max-width:156px;"></td>                            <td>                               Datum: ${`${today.getDate()}. ${today.getMonth() + 1}. ${today.getFullYear()}.`}                            </td>                         </tr>                      </table>                   </td>                </tr>                <tr class="information">                   <td colspan="2">                      <table>                         <tr>                            <td>                               Customer name: ${name}                            </td>                            <td>                               Receipt number: ${receiptId}                            </td>                         </tr>                      </table>                   </td>                </tr>                <tr class="heading">                   <td>Bought items:</td>                   <td>Price</td>                </tr>                <tr class="item">                   <td>First item:</td>                   <td>${price1}$</td>                </tr>                <tr class="item">                   <td>Second item:</td>                   <td>${price2}$</td>                </tr>             </table>             <br />             <h1 class="justify-center">Total price: ${parseInt(price1) + parseInt(price2)}$</h1>          </div>       </body>    </html>    `; }; 

server/index.js рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ server/index.js :

 const pdfTemplate = require('./documents'); 

PDF рдмрдирд╛рдПрдБ


рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╕рд░реНрд╡рд░ рдкрд░ рд╣рдо рджреЛ рд░реВрдЯ рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред POST рдорд╛рд░реНрдЧ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдЬреАрдИрдЯреА рдорд╛рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рддреИрдпрд╛рд░ рдлрд╝рд╛рдЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

тЦН create-pdf рдорд╛рд░реНрдЧ


pdf.create() html-pdf рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдЖрдпрд╛рдд рдХреА рдЧрдИ рд╡рд╕реНрддреБ рдХрд╛ рдЬрд┐рдХреНрд░ рдХрд░рддреЗ рд╣реБрдП, create-pdf POST рд░реВрдЯ рдореЗрдВ, рд╣рдо pdf.create() рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

pdf.create() рд╡рд┐рдзрд┐ рдХреЗ рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рднреАред

pdf.create() рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо toFile() рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рд╡рд╣ рдирд╛рдо рджреЗрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдо рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рд╕рд╛рде рддреАрд░ рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рдиред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди, рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, res.send(Promise.reject()) рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред рдЗрд╕ рдШрдЯрдирд╛ рдореЗрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛ рдЧрдпрд╛, рд╡рд╣ res.send(Promise.resolve()) рдХрдорд╛рдВрдб res.send(Promise.resolve()) рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред

 app.post('/create-pdf', (req, res) => {    pdf.create(pdfTemplate(req.body), {}).toFile('result.pdf', (err) => {        if(err) {            res.send(Promise.reject());        }        res.send(Promise.resolve());    }); }); 

тЦНрдлреЗрдЯ-рдкреАрдбреАрдПрдл рд░реВрдЯ


рдЙрд╕реА рд╕рдордп, рд╣рдо рдПрдХ рдорд╛рд░реНрдЧ рдмрдирд╛рдПрдВрдЧреЗ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдЕрдиреБрд░реЛрдз рдкрд░, рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣рд╛рдВ рд╣рдо рдХреЗрд╡рд▓ рддреИрдпрд╛рд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ res.sendFile() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рднреЗрдЬрддреЗ рд╣реИрдВ:

 app.get('/fetch-pdf', (req, res) => {    res.sendFile(`${__dirname}/result.pdf`) }) 

рдХреНрд▓рд╛рдЗрдВрдЯ рдлрд╝рдВрдХреНрд╢рди createAndDownloadPdf


рдЕрдм рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рдкрд░ рд▓реМрдЯ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ createAndDownloadPdf рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд╣рдо axios рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдПрдХ POST рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВред рдЕрдм рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

 createAndDownloadPdf = () => {   axios.post('/create-pdf', this.state) } 

рдпрджрд┐ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ POST рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рд╣рдореЗрдВ рдПрдХ GET рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ рд╕рд░реНрд╡рд░ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рддреИрдпрд╛рд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рднреЗрдЬреЗрдЧрд╛ред

рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдпреЛрдЬрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо axios.post() рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред then() ред рдпрд╣ рд╣рдореЗрдВ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рдЧреНрд░рд╛рд╣рдХ рдХреЗ POST рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ, рд╣рдо рдЙрд╕ рд╕рд░реНрд╡рд░ рд╕реЗ рдПрдХ рд╡рд╛рджрд╛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдпрд╛ рддреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкреВрд░рдХ рдХрд░рддреЗ рд╣реИрдВ:

 .then(() => axios.get('/fetch-pdf', { responseType: 'blob' })) .then(( res) => {}) 

рдпрд╣рд╛рдВ рдЖрдк рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ blob рдЙрдкрдпреЛрдЧ responseType рд░реВрдк blob рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЖрдЧреЗ рдмрдврд╝реЗрдВ, рдЖрдЗрдП рд╣рдо рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред

рдмреВрдБрдж рд╡рд╕реНрддреБрдУрдВ


рдмреВрдБрдж рдХреБрдЫ рдЕрдкрд░рд┐рд╖реНрдХреГрдд рдбреЗрдЯрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╡рд╕реНрддреБ рд╣реИред рдРрд╕реА рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдХреНрд╕рд░ рдЙрди рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рджреЗрд╢реА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдЕрдиреБрдХреНрд░рдо рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдЯреЛрд░ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝рд╛рдЗрд▓ рдбреЗрдЯрд╛ред рдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ Blob рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдирд╣реАрдВ рд╣реИред рдпреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рдирдХреЗ рд╕рд╛рде рдЖрдк рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП - рдЙрдиреНрд╣реЗрдВ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреВрд░рд╛ рд╣реЛрдирд╛


рдЕрдм рдЬрдм рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ Blob рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреНрдпрд╛ рд╣реИрдВ, рддреЛ рд╣рдо res.data рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЗрд╕рдореЗрдВ res.data рдирдИ Blob рдСрдмреНрдЬреЗрдХреНрдЯ res.data .then .then() рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдмрдирд╛рддреЗ рд╕рдордп, рд╣рдо рдЗрд╕рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд╕ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдпрд╣ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛ рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдЧрд╛, рд╡рд╣ application/pdf рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо saveAs() рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ file-saver рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВред рдирддреАрдЬрддрди, createAndDowndloadPdf рд╡рд┐рдзрд┐ рдХрд╛ рдХреЛрдб рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЧрдП рдЬреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛:

   createAndDownloadPdf = () => {    axios.post('/create-pdf', this.state)      .then(() => axios.get('fetch-pdf', { responseType: 'blob' }))      .then((res) => {        const pdfBlob = new Blob([res.data], { type: 'application/pdf' });        saveAs(pdfBlob, 'newPdf.pdf');      })  } 

рдпрд╣ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред


рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧ

рдЦреЗрддреЛрдВ рдореЗрдВ рднрд░рдиреЗ рдФрд░ Download PDF рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдбреЗрдЯрд╛ рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЗрд╕рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдкреАрдбреАрдПрдл рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

рдФрд░ рдпрд╣рд╛рдБ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реА рд╣реИред


рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдЙрддреНрдкрдиреНрди рдкреАрдбреАрдПрдл

рдкрд░рд┐рдгрд╛рдо


рд╣рдордиреЗ рдПрдХ рдРрд╕рд╛ рддрдВрддреНрд░ рджреЗрдЦрд╛, рдЬреЛ рдЖрдкрдХреЛ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХ GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╣реИред рд╣рдореЗрдВ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдорд┐рд▓реЗ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдЖрдкрдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдЖрд╡реЗрджрди рдорд┐рд▓реЗрдЧрд╛ред

рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ! рдЖрдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ Node.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ PDF рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдЬрд╛рдПрдВрдЧреЗ?

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


All Articles