рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!
рдмрд╣реБрдд рдкрд╣рд▓реЗ рдирд╣реАрдВ, рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ рдореЗрд░реЗ рд╕рднреА рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рд╕реАрдПрд╕рдПрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдбреЗрд╡рд▓рдкрд░ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рджрд░реНрдж рд╣реИред
рдХрдЯреМрддреА рдХреЗ рддрд╣рдд рдореЗрд░реА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ, рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдкрд░ рдЕрдЬреАрдм рдХреЛрдб рдФрд░ рдиреБрдХрд╕рд╛рди рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ред
рд╕реАрдПрд╕рдПрд╕ рд╕рдорд╕реНрдпрд╛
рдореИрдВрдиреЗ рдЬреЛ рд░рд┐рдПрдХреНрдЯ рдФрд░ рд╡реАрдпреВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд┐рдП, рдЙрдирдореЗрдВ рд╢реИрд▓рд┐рдпреЛрдВ рдХрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓рдЧрднрдЧ рдПрдХ рдЬреИрд╕рд╛ рдерд╛ред рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╡реЗрдмрдкреИрдХ рджреНрд╡рд╛рд░рд╛ рдЗрдХрдЯреНрдард╛ рдХреА рдЬрд╛рддреА рд╣реИ, рдПрдХ рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓ рдореБрдЦреНрдп рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рд╕реЗ рдЖрдпрд╛рдд рдХреА рдЬрд╛рддреА рд╣реИред рдпрд╣ рдлрд╝рд╛рдЗрд▓ рд╢реЗрд╖ рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдЕрдВрджрд░ рд╣реА рдЖрдпрд╛рдд рдХрд░рддреА рд╣реИ рдЬреЛ рдмреАрдИрдПрдо рд╕реЗ рдирд╛рдо рд╡рд░реНрдЧреЛрдВ рддрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред
styles/ indes.css blocks/ apps-banner.css smart-list.css ...
рдХреНрдпрд╛ рд╡рд╣ рдкрд░рд┐рдЪрд┐рдд рд╣реИ? рдореИрдВрдиреЗ рд▓рдЧрднрдЧ рд╣рд░ рдЬрдЧрд╣ рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдФрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рдерд╛ рдЬрдм рддрдХ рдХрд┐ рд╕рд╛рдЗрдЯреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рддрдХ рдирд╣реАрдВ рдмрдврд╝реА рдХрд┐ рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдПрдВ рдореЗрд░реА рдЖрдВрдЦреЛрдВ рдХреЛ рдмрд╣реБрдд рдкрд░реЗрд╢рд╛рди рдХрд░рдиреЗ рд▓рдЧреАрдВред
1. рд╣реЙрдЯ-рд░реАрд▓реЛрдб рдХреА рд╕рдорд╕реНрдпрд╛рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╢реИрд▓рд┐рдпреЛрдВ рдХрд╛ рдЖрдпрд╛рдд рдкреЛрд╕реНрдЯрд╕реНрдХреЙрд▓реНрд╕ рдкреНрд▓рдЧрдЗрди рдпрд╛ рд╕реНрдЯрд╛рдЗрд▓рд╕-рд▓реЛрдбрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реБрдЖред
рдкрдХрдбрд╝ рдпрд╣ рд╣реИ:
рдЬрдм рд╣рдо рдбрд╛рдХ рдпрд╛ рд╕реНрдЯрд╛рдЗрд▓рд╕-рд▓реЛрдбрд░ рдкреНрд▓рдЧрдЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдпрд╛рдд рдХреЛ рд╣рд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдЙрдЯрдкреБрдЯ рдПрдХ рдмрдбрд╝реА рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓ рд╣реЛрддреА рд╣реИред рдЕрдм, рд╕реНрдЯрд╛рдЗрд▓рд╢реАрдЯ рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдореЗрдВ рдереЛрдбрд╝реЗ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде, рд╕рднреА рд╕реАрдПрд╕рдПрд╕ рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЧрд░реНрдо-рдкреБрдирдГ рд▓реЛрдб рдХреА рдЧрддрд┐ рдХреЛ рдорд╛рд░рддрд╛ рд╣реИ: ~ 950 Kbytes рд╕реНрдЯрд╛рдЗрд▓рд╕ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд▓рдЧрднрдЧ 4 рд╕реЗрдХрдВрдб рд▓рдЧрддреЗ рд╣реИрдВред
рд╕реАрдПрд╕рдПрд╕-рд▓реЛрдбрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдзреНрдпрд╛рди рджреЗрдВрдЕрдЧрд░ CSS рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдЖрдпрд╛рдд рдХрд░рдирд╛ css-loader рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛, рддреЛ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддреА:
css-loader CSS рдХреЛ JavaScript рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд╕рд╛рде рд╕рднреА рд╢реИрд▓реА рдХреЗ рдЖрдпрд╛рдд рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдЧрд╛ред рдлрд┐рд░ рдПрдХ рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓ рдмрджрд▓рдиреЗ рд╕реЗ рдЕрдиреНрдп рдлрд╛рдЗрд▓реЗрдВ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рд╣реЛрдВрдЧреА рдФрд░ рд╣реЙрдЯ-рд░реАрд▓реЛрдб рдЬрд▓реНрджреА рд╣реЛрдЧрд╛ред
рд╕реАрдПрд╕рдПрд╕ рд▓реЛрдбрд░ рдХреЗ рд▓рд┐рдП
@import './test.css'; html, body { margin: 0; padding: 0; width: 100%; height: 100%; } body { background-color: red; }
рдХреЗ рдмрд╛рдж
2. рдХреЛрдб-рд╡рд┐рднрд╛рдЬрди рдХреА рд╕рдорд╕реНрдпрд╛рдЬрдм рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╝реЛрд▓реНрдбрд░ рд╕реЗ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рд╕реАрдПрд╕рдПрд╕ рдХреЛ рдХрдИ рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ рддреЛрдбрд╝рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рд▓реЛрдб рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред
3. рдорд╣рд╛рди рд╕реАрдПрд╕рдПрд╕ рд╡рд░реНрдЧ рдХреЗ рдирд╛рдордкреНрд░рддреНрдпреЗрдХ BEM рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ: block-name__element-nameред рдРрд╕рд╛ рд▓рдВрдмрд╛ рдирд╛рдо рдЕрдВрддрд┐рдо рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓ рдЖрдХрд╛рд░ рдХреЛ рджреГрдврд╝рддрд╛ рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ: рд╣реИрдмрд░ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реАрдПрд╕рдПрд╕ рд╡рд░реНрдЧ рдХреЗ рдирд╛рдо рд╢реИрд▓реА рдлрд╝рд╛рдЗрд▓ рдЖрдХрд╛рд░ рдХреЗ 36% рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рддреЗ рд╣реИрдВред
Google рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рд╕реЗ рдЕрд╡рдЧрдд рд╣реИ рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЕрдкрдиреА рд╕рднреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ:
Google.com рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛рдЗрди рд╕рднреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдиреЗ рдореБрдЭреЗ рдЖрджреЗрд╢ рджрд┐рдпрд╛, рдореИрдВрдиреЗ рдЖрдЦрд┐рд░рдХрд╛рд░ рдЙрдиреНрд╣реЗрдВ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдкреВрд░реНрдг рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред
рдирд┐рд░реНрдгрдп рд▓реЗрдирд╛
рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рджреЛ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓реЗ: CSS In JS (рд╕реНрдЯрд╛рдЗрд▓ рд╡рд╛рд▓реЗ рдШрдЯрдХ) рдФрд░ CSS рдореЙрдбреНрдпреВрд▓ред
рдореИрдВрдиреЗ рдЗрди рд╕рдорд╛рдзрд╛рдиреЛрдВ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЦрд╛рдорд┐рдпрд╛рдВ рдирд╣реАрдВ рджреЗрдЦреАрдВ, рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ рдореЗрд░реА рдкрд╕рдВрдж рдХрдИ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рд╕реАрдПрд╕рдПрд╕ рдореЙрдбреНрдпреВрд▓ рдкрд░ рдЧрд┐рд░ рдЧрдИ:
- рдЖрдк рдЬреЗрдПрд╕ рдФрд░ рд╕реАрдПрд╕рдПрд╕ рдХреЗ рдЕрд▓рдЧ рдХреИрд╢рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реАрдПрд╕рдПрд╕ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╛рдЗрд▓ рдореЗрдВ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред
- рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╡рд┐рдХрд▓реНрдкред
- CSS рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЕрдзрд┐рдХ рдЖрдо рд╣реИред
рдкрд╕рдВрдж рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдЦрд╛рдирд╛ рдкрдХрд╛рдиреЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ!
рдореВрд▓ рд╕реЗрдЯрд┐рдВрдЧ
рд╡реЗрдмрдкреИрдХ рдХреЛ рдереЛрдбрд╝рд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВред рд╕реАрдПрд╕рдПрд╕-рд▓реЛрдбрд░ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЗрд╕рдореЗрдВ рд╕реАрдПрд╕рдПрд╕ рдореЙрдбреНрдпреВрд▓ рд╕рдХреНрд╖рдо рдХрд░реЗрдВ:
module.exports = { module: { rules: [ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, } }, ], }, ], }, };
рдЕрдм рд╣рдо CSS рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рдлрд╝реЛрд▓реНрдбрд░реЛрдВ рдореЗрдВ рдлреИрд▓рд╛рдПрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдХреЗ рдЕрдВрджрд░ рд╣рдо рдЖрд╡рд╢реНрдпрдХ рд╢реИрд▓рд┐рдпреЛрдВ рдХрд╛ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВред
project/ components/ CoolComponent/ index.js index.css
.contentWrapper { padding: 8px 16px; background-color: rgba(45, 45, 45, .3); } .title { font-size: 14px; font-weight: bold; } .text { font-size: 12px; }
import React from 'react'; import styles from './index.css'; export default ({ text }) => ( <div className={styles.contentWrapper}> <div className={styles.title}> Weird title </div> <div className={styles.text}> {text} </div> </div> );
рдЕрдм рдЬрдм рд╣рдордиреЗ CSS рдлрд╛рдЗрд▓реЗрдВ рддреЛрдбрд╝ рджреА рд╣реИрдВ, рддреЛ рд╣реЙрдЯ-рд░реАрд▓реЛрдб рдХреЗрд╡рд▓ рдПрдХ рдлрд╛рдЗрд▓ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдЧрд╛ред рд╕рдорд╕реНрдпрд╛ рдирдВрдмрд░ 1 рд╣рд▓, рдЪреАрдпрд░реНрд╕!
рд╕реАрдПрд╕рдПрд╕ рдХреЛ рд╡рд┐рдЦрдВрдбреВ рдореЗрдВ рддреЛрдбрд╝ рджреЗрдВ
рдЬрдм рдХрд┐рд╕реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХрдИ рдкреГрд╖реНрда рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЙрдирдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдпрд╣ рд╕рднреА рдбреЗрдЯрд╛ рдХреЛ рдкрдВрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╣рд╛рди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рд▓реЛрдб рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдПрдХ рдШрдЯрдХ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЙрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдПред
import Loadable from 'react-loadable'; import Loading from 'path/to/Loading'; export default Loadable({ loader: () => import('path/to/CoolComponent'), loading: Loading, });
рд╡реЗрдмрдкреИрдХ CoolComponent рдШрдЯрдХ рдХреЛ рдПрдХ рдЕрд▓рдЧ JS рдлрд╝рд╛рдЗрд▓ (рдЪрдВрдХ) рдореЗрдВ рдмрджрд▓ рджреЗрдЧрд╛, рдЬрд┐рд╕реЗ AsyncCoolComponent рдХреЗ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╡рд╣реАрдВ, CoolComponent рдХреА рдЕрдкрдиреА рд╢реИрд▓реА рд╣реИред CSS рдЗрд╕рдореЗрдВ JS рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдм рддрдХ рдирд┐рд╣рд┐рдд рд╣реИ рдФрд░ рд╕реНрдЯрд╛рдЗрд▓-рд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдЯрд╛рдЗрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд╛рдЯрддреЗ рд╣реИрдВ?
рд╣рдо рджреЛрдиреЛрдВ рдореБрдЦреНрдп рдлрд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рдЦрдВрдбреВ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рд╕реНрд╡рдпрдВ рдХреА CSS рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВрдЧреЗред
рдорд┐рдиреА-рд╕реАрдПрд╕рдПрд╕-рдПрдХреНрд╕рдЯреНрд░реЗрдХреНрдЯ-рдкреНрд▓рдЧрдЗрди рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рд╡реЗрдмрдкреИрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рд╕рдВрдпреБрдЧреНрдорди рдХрд░реЗрдВ:
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const isDev = process.env.NODE_ENV === 'development'; module.exports = { module: { rules: [ { test: /\.css$/, use: [ (isDev ? 'style-loader' : MiniCssExtractPlugin.loader), { loader: 'css-loader', options: { modules: true, }, }, ], }, ], }, plugins: [ ...(isDev ? [] : [ new MiniCssExtractPlugin({ filename: '[name].[contenthash].css', chunkFilename: '[name].[contenthash].css', }), ]), ], };
рд╡рд╣ рд╕рдм рд╣реИ! рдЖрдЗрдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдЙрддреНрдкрд╛рджрди рдореЛрдб рдореЗрдВ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВ, рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЦреЛрд▓реЗрдВ рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдЯреИрдм рджреЗрдЦреЗрдВ:
// GET /main.aff4f72df3711744eabe.css GET /main.43ed5fc03ceb844eab53.js // CoolComponent , JS CSS GET /CoolComponent.3eaa4773dca4fffe0956.css GET /CoolComponent.2462bbdbafd820781fae.js
рд╕рдорд╕реНрдпрд╛ рд╕рдВрдЦреНрдпрд╛ 2 рдЦрддреНрдо рд╣реЛ рдЧрдИ рд╣реИред
рд╣рдо рд╕реАрдПрд╕рдПрд╕ рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рдЫреЛрдЯрд╛ рдХрд░рддреЗ рд╣реИрдВ
рд╕реАрдПрд╕рдПрд╕-рд▓реЛрдбрд░ рд╡рд░реНрдЧ рдХреЗ рдирд╛рдореЛрдВ рдХреЛ рдЕрдВрджрд░ рдмрджрд▓рддрд╛ рд╣реИ рдФрд░ рд╕реНрдерд╛рдиреАрдп рд╡рд░реНрдЧ рдХреЗ рдирд╛рдореЛрдВ рдХреА рдореИрдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдЪрд░ рдХреЛ рд╡реИрд╢реНрд╡рд┐рдХ рдореЗрдВ рд▓реМрдЯрд╛рддрд╛ рд╣реИред
рд╣рдорд╛рд░реЗ рдореВрд▓ рд╕реЗрдЯрдЕрдк рдХреЗ рдмрд╛рдж, css-loader рдлрд╝рд╛рдЗрд▓ рдХреЗ рдирд╛рдо рдФрд░ рд╕реНрдерд╛рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рд▓рдВрдмрд╛ рд╣реИрд╢ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред
рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ, рд╣рдорд╛рд░рд╛ CoolComponent рдЕрдм рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
<div class="rs2inRqijrGnbl0txTQ8v"> <div class="_2AU-QBWt5K2v7J1vRT0hgn"> Weird title </div> <div class="_1DaTAH8Hgn0BQ4H13yRwQ0"> Lorem ipsum dolor sit amet consectetur. </div> </div>
рдмреЗрд╢рдХ, рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред
рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рдореВрд▓ рд╢реИрд▓реА рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╛рдо рд╣реЛрдВред рдФрд░ рдЙрддреНрдкрд╛рджрди рдореЛрдб рдореЗрдВ, рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЛ рдЫреЛрдЯрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╕реАрдПрд╕рдПрд╕-рд▓реЛрдбрд░ рдЖрдкрдХреЛ рд╕реНрдерд╛рдиреАрдп рдирд╛рдо рд╡рд┐рдХрд▓реНрдк рдФрд░ getLocalIdent рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЗ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╡рд┐рдХрд╛рд╕ рдореЛрдб рдореЗрдВ, рд╣рдо рд╡рд░реНрдгрдирд╛рддреНрдордХ localIdentName - '[рдкрде] _ [рдирд╛рдо] _ [рд╕реНрдерд╛рдиреАрдп]' рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЙрддреНрдкрд╛рджрди рдореЛрдб рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЛ рдЫреЛрдЯрд╛ рдХрд░реЗрдЧрд╛:
const getScopedName = require('path/to/getScopedName'); const isDev = process.env.NODE_ENV === 'development'; module.exports = { module: { rules: [ { test: /\.css$/, use: [ (isDev ? 'style-loader' : MiniCssExtractPlugin.loader), { loader: 'css-loader', options: { modules: true, ...(isDev ? { localIdentName: '[path]_[name]_[local]', } : { getLocalIdent: (context, localIdentName, localName) => ( getScopedName(localName, context.resourcePath) ), }), }, }, ], }, ], }, };
рдФрд░ рдпрд╣рд╛рдБ рд╣рдо рд╕реБрдВрджрд░ рджреГрд╢реНрдп рдирд╛рдореЛрдВ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рд╣реИрдВ:
<div class="src-components-ErrorNotification-_index_content-wrapper"> <div class="src-components-ErrorNotification-_index_title"> Weird title </div> <div class="src-components-ErrorNotification-_index_text"> Lorem ipsum dolor sit amet consectetur. </div> </div>
рдФрд░ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рд▓рдШреБ рд╢реНрд░реЗрдгреА:
<div class="e_f"> <div class="e_g"> Weird title </div> <div class="e_h"> Lorem ipsum dolor sit amet consectetur. </div> </div>
рддреАрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рджреВрд░ рд╣реЛ рдЬрд╛рддреА рд╣реИред
рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреИрд╢ рдЕрдорд╛рдиреНрдп рдирд┐рдХрд╛рд▓реЗрдВ
рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдХреНрд▓рд╛рд╕ рдорд┐рдирд┐рдлрд┐рдХреЗрд╢рди рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдХрдИ рдмрд╛рд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВред рдХреИрд╢ рджрд░реНрдЬ рдХрд░рдиреЗ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ:
/* */ app.bf70bcf8d769b1a17df1.js app.db3d0bd894d38d036117.css /* */ app.1f296b75295ada5a7223.js app.eb2519491a5121158bd2.css
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдирдП рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рдж рд╣рдордиреЗ рдХреИрд╢ рдХреЛ рдЕрдорд╛рдиреНрдп рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдРрд╕рд╛ рдХреИрд╕реЗ?
рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╡реЗрдмрдкреИрдХ рдЙрд╕ рдЖрджреЗрд╢ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдлрд╛рдЗрд▓реЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИрдВред рдпрд╣реА рд╣реИ, рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдПрдХ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдХреНрд░рдо рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдзрд╛рдирд╕рднрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рд╡рд░реНрдЧ рдХреЗ рдирд╛рдо рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдирд╛рдорд╛рдВрдХрд┐рдд рдирд╛рдо рдЙрддреНрдкрдиреНрди рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗред
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрд╕реЗрдВрдмрд▓реА рдХреЗ рдмреАрдЪ рдЙрддреНрдкрдиреНрди рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред GetScopedName.js рдлрд╝рд╛рдЗрд▓ рдХреЛ рдереЛрдбрд╝рд╛ рдЕрджреНрдпрддрди рдХрд░реЗрдВ:
const incstr = require('incstr');
рдЬреЗрдирд░реЗрдЯрд░ рд╣реЗрд▓реНрдкрд░реНрд╕.рдЬреЗрдПрд╕ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорд╛рдпрдиреЗ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣рд╛рдВ рдореЗрд░рд╛ рд╣реИ:
generatorHelpers.js const fs = require('fs'); const path = require('path'); const getGeneratorDataPath = generatorIdentifier => ( path.resolve(__dirname, `meta/${generatorIdentifier}.json`) ); const getGeneratorData = (generatorIdentifier) => { const path = getGeneratorDataPath(generatorIdentifier); if (fs.existsSync(path)) { return require(path); } return {}; }; const saveGeneratorData = (generatorIdentifier, uniqIds) => { const path = getGeneratorDataPath(generatorIdentifier); const data = JSON.stringify(uniqIds, null, 2); fs.writeFileSync(path, data, 'utf-8'); }; module.exports = { getGeneratorData, saveGeneratorData, };
рдХреИрд╢ рдмрд┐рд▓реНрдб рдХреЗ рдмреАрдЪ рд╕рдорд╛рди рд╣реЛ рдЧрдП рд╣реИрдВ, рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИред рд╣рдорд╛рд░реЗ рдкрдХреНрд╖ рдореЗрдВ рдПрдХ рдФрд░ рдмрд┐рдВрджреБ!
рд░рдирдЯрд╛рдЗрдо рдЪрд░ рдирд┐рдХрд╛рд▓реЗрдВ
рдЪреВрдВрдХрд┐ рдореИрдВрдиреЗ рдПрдХ рдмреЗрд╣рддрд░ рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдорд╛рдирдЪрд┐рддреНрд░рдг рдХреЗ рд╕рд╛рде рдЗрд╕ рдЪрд░ рдХреЛ рдирд┐рдХрд╛рд▓рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рд╣реИрдВред
рдмреИрдмрд▓-рдкреНрд▓рдЧрдЗрди-рд░рд┐рдПрдХреНрд╢рди-рд╕реАрдПрд╕рдПрд╕-рдореЙрдбреНрдпреВрд▓ рд╣рдореЗрдВ рдЗрд╕рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред рд╕рдВрдХрд▓рди рдХреЗ рд╕рдордп, рдпрд╣:
- рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реАрдПрд╕рдПрд╕ рдЖрдпрд╛рдд рдорд┐рд▓реЗрдЧрд╛ред
- рдпрд╣ рд╕реАрдПрд╕рдПрд╕ рдлрд╛рдЗрд▓ рдХреЛ рдЦреЛрд▓реЗрдЧрд╛ рдФрд░ рд╕реАрдПрд╕рдПрд╕-рд▓реЛрдбрд░ рдХреА рддрд░рд╣ рд╣реА рд╕реАрдПрд╕рдПрд╕ рд╢реНрд░реЗрдгреА рдХреЗ рдирд╛рдо рдмрджрд▓реЗрдЧрд╛ред
- рдпрд╣ рд╕реНрдЯрд╛рдЗрд▓ рдирд╛рдо рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдЬреЗрдПрд╕рдПрдХреНрд╕ рдиреЛрдбреНрд╕ рдкрд╛рдПрдЧрд╛ред
- рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдиреАрдп рд╡рд░реНрдЧ рдХреЗ рдирд╛рдореЛрдВ рдХреА рдЬрдЧрд╣ рд▓реЗрддрд╛ рд╣реИред
рдЗрд╕ рдкреНрд▓рдЧрдЗрди рдХреЛ рд╕реЗрдЯ рдХрд░реЗрдВред рдЖрдЗрдП рдмрдмрд▓ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд╕рд╛рде рдЦреЗрд▓реЗрдВ:
рд╣рдорд╛рд░реА JSX рдлрд╛рдЗрд▓реЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:
import React from 'react'; import './index.css'; export default ({ text }) => ( <div styleName="content-wrapper"> <div styleName="title"> Weird title </div> <div styleName="text"> {text} </div> </div> );
рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рд╢реИрд▓реА рдирд╛рдореЛрдВ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд╕рд╛рде рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рдирд╣реАрдВ рд╣реИ!
... рдпрд╛ рд╣реИ?
рд╣рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдПрдХрддреНрд░ рдХрд░реЗрдВрдЧреЗ рдФрд░ рд╕реНрд░реЛрддреЛрдВ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░реЗрдВрдЧреЗ:
function(e, t, n) { e.exports = { "content-wrapper": "e_f", title: "e_g", text: "e_h" } }
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЪрд░ рдЕрднреА рднреА рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╣реАрдВ рднреА рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реБрдЖ?
рд╡реЗрдмрдкреИрдХ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдореЙрдбреНрдпреВрд▓рд░ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реИрдВ ES2015 (рдЖрдпрд╛рдд) рдФрд░ рдЖрдордЬреЗрдПрд╕рдПрд╕ (рдЖрд╡рд╢реНрдпрдХрддрд╛)ред
ESJ5 рдореЙрдбреНрдпреВрд▓, рдЖрдоJS рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЙрдирдХреА рд╕реНрдерд┐рд░ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдХрд╛рд░рдг
рдкреЗрдбрд╝-рдЭрдЯрдХреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред
рд▓реЗрдХрд┐рди css-loader рдФрд░ mini-css-extract-plugin рджреЛрдиреЛрдВ рд▓реЛрдбрд░ рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП commonJS рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдирд┐рд░реНрдорд┐рдд рдбреЗрдЯрд╛ рдХреЛ рдмрд┐рд▓реНрдб рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдирд╣реАрдВ рдЬрд╛рддрд╛ рд╣реИред
рд╣рдо рдЕрдкрдиреЗ рдЫреЛрдЯреЗ рд▓реЛрдбрд░ рдХреЛ рд▓рд┐рдЦреЗрдВрдЧреЗ рдФрд░ рдЙрддреНрдкрд╛рджрди рдореЛрдб рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдбреЗрдЯрд╛ рдХреЛ рд╣рдЯрд╛ рджреЗрдВрдЧреЗ:
const path = require('path'); const resolve = relativePath => path.resolve(__dirname, relativePath); const isDev = process.env.NODE_ENV === 'development'; module.exports = { module: { rules: [ { test: /\.css$/, use: [ ...(isDev ? ['style-loader'] : [ resolve('path/to/webpack-loaders/nullLoader'), MiniCssExtractPlugin.loader, ]), { loader: 'css-loader', }, ], }, ], }, };
рдЗрдХрдЯреНрдареА рд╣реБрдИ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬрд╛рдВрдЪреЗрдВ:
function(e, t, n) {}
рдЖрдк рд░рд╛рд╣рдд рдХреЗ рд╕рд╛рде рд╕рд╛рдБрд╕ рдЫреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рд╡рд░реНрдЧ рдореИрдкрд┐рдВрдЧ рдЪрд░ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж
рдирд▓-рд▓реЛрдбрд░ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд▓рдЧ рд░рд╣рд╛ рдерд╛ред
рд▓реЗрдХрд┐рди рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рдирд┐рдХрд▓рд╛:
export default function() { return '// empty (null-loader)'; } export function pitch() { return '// empty (null-loader)'; }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдирд▓-рд▓реЛрдбрд░ рднреА рдкрд┐рдЪ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ
рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рд╕реАрдЦрд╛ рдХрд┐ рдкрд┐рдЪ рдХреЗ рддрд░реАрдХреЗ рджреВрд╕рд░реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдкрд╣рд▓реЗ рдХрд╣реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рдж рдХреЗ рд╕рднреА рд▓реЛрдбрд░ рдХреЛ рд░рджреНрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реЗ рдЗрд╕ рд╡рд┐рдзрд┐ рд╕реЗ рдХреБрдЫ рдбреЗрдЯрд╛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред
рдирд▓-рд▓реЛрдбрд░ рдХреЗ рд╕рд╛рде, рд╕реАрдПрд╕рдПрд╕ рдЙрддреНрдкрд╛рджрди рдЕрдиреБрдХреНрд░рдо рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд▓рдЧрддрд╛ рд╣реИ:
- рдирд▓-рд▓реЛрдбрд░ рдХреА рдкрд┐рдЪ рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реМрдЯрд╛рддрд╛ рд╣реИред
- рдкрд┐рдЪ рд╡рд┐рдзрд┐ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХреЗ рдХрд╛рд░рдг, рдмрд╛рдж рдХреЗ рд╕рднреА рд▓реЛрдбрд░ рдХреЛ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдЕрдм рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рджреЗрдЦрд╛ рдФрд░ рдЕрдкрдирд╛ рд▓реЛрдбрд░ рдмрдирд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред
Vue.js рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВрдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдкрдиреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рдкрд░ рдХреЗрд╡рд▓ рдПрдХ Vue.js рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рдирд╛ рдФрд░ рд░рдирдЯрд╛рдЗрдо рдЪрд░ рдХреЛ рд╣рдЯрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдорд╣рд╛рди рд╣реИрдХ рд╣реИ!
рд╣рдореЗрдВ рдХреЗрд╡рд▓ рджреЛ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдмреЗрдмрд▓-рдкреНрд▓рдЧрдЗрди-рдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдо-рд╡реНрдпреВ-рдЬреЗрдПрдХреНрд╕ рдФрд░ рдмреИрдмрд▓-рдкреНрд▓рдЧрдЗрди-рд░рд┐рдПрдХреНрд╢рди-рд╕реАрдПрд╕рдПрд╕-рдореЙрдбреНрдпреВрд▓ред рд╣рдореЗрдВ рдЬреЗрдПрд╕рдПрдХреНрд╕ рдХреЛ рд░реЗрдВрдбрд░ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдФрд░ рджреВрд╕рд░рд╛, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдирд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
module.exports = { plugins: [ 'transform-vue-jsx', ['react-css-modules', {
import './index.css'; const TextComponent = { render(h) { return( <div styleName="text"> Lorem ipsum dolor. </div> ); }, mounted() { console.log('I\'m mounted!'); }, }; export default TextComponent;
рд╕реАрдПрд╕рдПрд╕ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░реЗрдВ
рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реАрдПрд╕рдПрд╕ рдХреА рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП:
.component1__title { color: red; } .component2__title { color: green; } .component2__title_red { color: red; }
рдЖрдк рдПрдХ рд╕реАрдПрд╕рдПрд╕ рдорд┐рдирд┐рдлрд╝рд╛рдпрд░ рд╣реИрдВред рдЖрдк рдЗрд╕реЗ рдХреИрд╕реЗ рдирд┐рдЪреЛрдбрд╝реЗрдВрдЧреЗ?
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рдЬрд╡рд╛рдм рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реИ:
.component2__title{color:green} .component2__title_red, .component1__title{color:red}
рдЕрдм рд╣рдо рдЬрд╛рдБрдЪреЗрдВрдЧреЗ рдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рдорд┐рдирд┐рд╕реНрдЯрд░ рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗред рдХреБрдЫ
рдСрдирд▓рд╛рдЗрди рдорд┐рдиреАрдлрд╝рд╛рдпрд░ рдореЗрдВ рд╣рдорд╛рд░реЗ рдХреЛрдб рдХрд╛ рдЯреБрдХрдбрд╝рд╛
рдбрд╛рд▓реЗрдВ :
.component1__title{color:red} .component2__title{color:green} .component2__title_red{color:red}
рд╡рд╣ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛?
рдорд┐рдирд┐рдлрд╝рд╛рдпрд░ рдбрд░рддрд╛ рд╣реИ рдХрд┐ рд╢реИрд▓рд┐рдпреЛрдВ рдХреА рдШреЛрд╖рдгрд╛ рдХреЗ рдХреНрд░рдо рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ рдХрд╛рд░рдг рдХреБрдЫ рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдпрд╣ рдХреЛрдб рд╣реИ:
<div class="component1__title component2__title">Some weird title</div>
рдЖрдкрдХреА рд╡рдЬрд╣ рд╕реЗ, рд╢реАрд░реНрд╖рдХ рд▓рд╛рд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдСрдирд▓рд╛рдЗрди рдорд┐рдирд┐рдлрд╝рд╛рдпрд░ рд╕рд╣реА рд╢реИрд▓реА рдШреЛрд╖рдгрд╛ рдХреНрд░рдо рдЫреЛрдбрд╝ рджреЗрдЧрд╛ рдФрд░ рдпрд╣ рд╣рд░рд╛ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдмреЗрд╢рдХ, рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдШрдЯрдХ 1__title рдФрд░ рдШрдЯрдХ2__title рдХрд╛ рдЪреМрд░рд╛рд╣рд╛ рдХрднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╡рд┐рднрд┐рдиреНрди рдШрдЯрдХреЛрдВ рдореЗрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╣рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ?
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЦреЛрдЬрдиреЗ рдХреЗ рдмрд╛рдж, рдореБрдЭреЗ рдХреЗрд╡рд▓
csso рдХреЗ рд╕рд╛рде рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛
рдорд┐рд▓реА ред рдФрд░ рдЙрд╕рдХреЗ рдкрд╛рд╕ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╡реЗрдмрдкреИрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИред рдЖрдЧреЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рдмрд╛рдЗрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдХреЗ рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдФрд░ рдЗрд╕реЗ csso рдХреЗ рдЕрдВрджрд░ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рд╣рдордиреЗ рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЫреЛрдЯрд╛ рд╡рд░реНрдЧ рдирд╛рдо рдЙрддреНрдкрдиреНрди рдХрд┐рдпрд╛ рдерд╛: '[ComponentsId] _ [classNameId]'ред рдЗрд╕рд▓рд┐рдП, рдирд╛рдо рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рд╕реЗ рд╡рд░реНрдЧ рдХреЗ рдирд╛рдореЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ!
рдЕрдкрдиреА рд╕реАрдЯ рдмреЗрд▓реНрдЯ рдмрд╛рдВрдзреЗрдВ рдФрд░ рдЕрдкрдирд╛ рдкреНрд▓рдЧрдЗрди рд▓рд┐рдЦреЗрдВ:
const cssoLoader = require('path/to/cssoLoader'); module.exports = { plugins: [ new cssoLoader(), ], };
const csso = require('csso'); const RawSource = require('webpack-sources/lib/RawSource'); const getScopes = require('./helpers/getScopes'); const isCssFilename = filename => /\.css$/.test(filename); module.exports = class cssoPlugin { apply(compiler) { compiler.hooks.compilation.tap('csso-plugin', (compilation) => { compilation.hooks.optimizeChunkAssets.tapAsync('csso-plugin', (chunks, callback) => { chunks.forEach((chunk) => {
const csso = require('csso'); const getComponentId = (className) => { const tokens = className.split('_');
рдФрд░ рдпрд╣ рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рдерд╛, рд╣реИ рдирд╛? рдЖрдорддреМрд░ рдкрд░, рдпрд╣ рдиреНрдпреВрдирддрдо рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ CSS рдХреЛ 3-6% рддрдХ рдХрдо рдХрд░ рджреЗрддрд╛ рд╣реИред
рдХреНрдпрд╛ рдпрд╣ рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдерд╛?
рдмреЗрд╢рдХред
рдореЗрд░реЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ, рдПрдХ рддреНрд╡рд░рд┐рдд рд╣реЙрдЯ-рд░реАрд▓реЛрдб рдЕрдВрдд рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛, рдФрд░ рд╕реАрдПрд╕рдПрд╕ рдиреЗ рд╡рд┐рдЦрдВрдбреВ рдореЗрдВ рддреЛрдбрд╝рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рдФрд░ рдФрд╕рддрди 40% рдХрдо рд╡рдЬрдиред
рдпрд╣ рд╕рд╛рдЗрдЯ рдХреА рд▓реЛрдбрд┐рдВрдЧ рдХреЛ рдЧрддрд┐ рджреЗрдЧрд╛ рдФрд░ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдордп рдХрдо рдХрд░реЗрдЧрд╛, рдЬреЛ рди рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ, рдмрд▓реНрдХрд┐ рд╕реАрдИрдУ рдХреЛ рднреА рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░реЗрдЧрд╛ред
рд▓реЗрдЦ рдмрд╣реБрдд рдмрдврд╝ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЦреБрд╢реА рд╣реИ рдХрд┐ рдХреЛрдИ рдЗрд╕реЗ рдЕрдВрдд рддрдХ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ред рдЖрдкрдХреЗ рд╕рдордп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!
рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛