{"id":305353,"date":"2020-06-15T15:00:39","date_gmt":"2020-06-15T15:00:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=305353"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=305353","title":{"rendered":"Webpack: \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/506636\/\">\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043a\u0430\u0436\u0443\u0449\u0443\u044e\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 \u0442\u0435\u043c\u044b, \u043c\u043d\u0435 \u043d\u0435 \u0434\u043e\u0432\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043d\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0433\u0434\u0435 \u0441\u0431\u043e\u0440\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0435\u0439 \u0431\u044b\u043b\u0430 \u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0443\u0434\u043e\u0431\u043d\u043e, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u043b\u0430\u0434\u0430\u043b\u0430 \u0431\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u044d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e (\u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u0445)<\/li>\n<li>\u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/li>\n<li>\u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/li>\n<li>\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442 \u043e\u0431\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438, \u0430 \u043d\u0435\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e<\/li>\n<li>\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (\u043f\u043e\u0440\u0442 watch-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, https-\u0440\u0435\u0436\u0438\u043c) \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 env-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041a\u043e\u043b\u043b\u0435\u0433\u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043b\u0438 \u043b\u0438\u0448\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u044d\u0442\u0438\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043b\u044e\u0431\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u043e \u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0442.\u043a. \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u043b\u0438\u0431\u043e middleware, \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043b\u0438\u0431\u043e watch-\u0441\u0435\u0440\u0432\u0435\u0440 webpack, \u043d\u043e \u0432\u0438\u0434\u0435\u043b \u0438 \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043c\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439, \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0432\u0441\u0435 \u043f\u043e \u043f\u043e\u043b\u043e\u0447\u043a\u0430\u043c.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432\u044b\u0448\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u043e\u043f\u043b\u043e\u0449\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<h3 id=\"1-opredelit-shemu-podklyucheniya-izmenyaemyh-parametrov\">1. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c .env \u0444\u0430\u0439\u043b\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>.env \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d \u0438\u0437 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f;<\/li>\n<li>example.dev.env \u2014 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438;<\/li>\n<li>example.prod.env \u2014 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f production \u0441\u0431\u043e\u0440\u043a\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043d\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b Webpack, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0440\u0435\u0434\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u043b\u0438 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">HOT_RELOAD=true HOT_RELOAD_PORT=401  # Webpack config # @docs: https:\/\/webpack.js.org\/configuration\/devtool DEV_TOOL= DEV_TOOL_SERVER= DROP_CONSOLE=false FILENAME_HASH=false CIRCULAR_CHECK=true MINIMIZE_CLIENT=false MINIMIZE_SERVER=false AGGREGATION_TIMEOUT=800  NODE_ENV=development NODE_PATH=.\/src EXPRESS_PORT=80 HTTPS_BY_NODE=false<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043c\u0435\u0440\u0434\u0436\u0438\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0435 env-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/motdotla\/dotenv\" rel=\"nofollow\">dotenv<\/a>, \u043d\u043e \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e <a href=\"https:\/\/github.com\/benoror\/better-npm-run\" rel=\"nofollow\">better-npm-run<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043e\u0434\u043d\u043e \u0440\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u0437 \u0440\u0435\u0446\u0435\u043f\u0442\u043e\u0432 package.json. \u0412 \u043a\u043e\u0434 \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u044b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">env.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">type Devtool =   | 'eval'   | 'source-map'   | 'eval-source-map'   | 'cheap-source-map'   | 'inline-source-map'   | 'hidden-source-map'   | 'nosources-source-map'   | 'cheap-eval-source-map'   | 'cheap-module-source-map'   | 'inline-cheap-source-map'   | 'cheap-module-eval-source-map'   | 'inline-cheap-module-source-map'   | boolean;  class Env {   constructor(params: Record&lt;string, any&gt;) {     Object.entries(params).forEach(([envKey, envValue]) =&gt; {       switch (typeof this[envKey]) {         case 'boolean':           this[envKey] = envValue === true || envValue === 'true';           break;         case 'string':           this[envKey] = (envValue || '').replace(\/&quot;\/g, '').trim();           break;         case 'number':           this[envKey] = Number(envValue || 0);           break;         default:           break;       }     });   }    HOT_RELOAD = false;   HOT_RELOAD_PORT = 0;    DEV_TOOL: Devtool = 'cheap-module-eval-source-map';   DEV_TOOL_SERVER: Devtool = 'cheap-module-eval-source-map';    DROP_CONSOLE = false;   FILENAME_HASH = false;   CIRCULAR_CHECK = false;   MINIMIZE_CLIENT = false;   MINIMIZE_SERVER = false;   AGGREGATION_TIMEOUT = 0;   START_SERVER_AFTER_BUILD = false;    NODE_ENV: `development` | `production` = `development`;   NODE_PATH = '';   EXPRESS_PORT = 0;   HTTPS_BY_NODE = false; }  \/\/ eslint-disable-next-line no-process-env export const env = new Env(process.env);<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0437\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0445 .env-\u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>  <\/p>\n<h3 id=\"2-sozdat-webpack-konfigi-dlya-servernoy-i-frontovoy-sborki\">2. \u0421\u043e\u0437\u0434\u0430\u0442\u044c webpack-\u043a\u043e\u043d\u0444\u0438\u0433\u0438 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0438 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438<\/h3>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0432 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Node.js. \u041f\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b, \u043a\u0440\u043e\u043c\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 (F \u2014 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433, B \u2014 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u0432\u044b\u0439):<\/p>\n<p>  <\/p>\n<p>F: <code>target: 'web'<\/code><br \/>  B: <code>target: 'node'<\/code><\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p>F: <code>entry: { client: path.resolve(paths.sourcePath, 'client.js') }<\/code><br \/>  B: <code>entry: { server: path.resolve(paths.serverPath, 'server.js') }<\/code><\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">F: webpack-custom\/loaders\/loaderBabel.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @docs: https:\/\/github.com\/babel\/babel-loader  *  *\/  import webpack from 'webpack';  import { env } from '..\/..\/env'; import babelConfigServer from '..\/..\/babel.config';  const presetEnvOptions = env.POLYFILLING   ? {       corejs: 3,       useBuiltIns: 'usage',     }   : undefined;  export const loaderBabel: webpack.RuleSetLoader = {   loader: 'babel-loader',   options: {     presets: [['@babel\/preset-env', presetEnvOptions]],     plugins: [...babelConfigServer.plugins, '@babel\/plugin-transform-react-jsx', 'lodash'],   }, };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">B: webpack-custom\/loaders\/loaderBabelServer.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @docs: https:\/\/github.com\/babel\/babel-loader  *  *\/  import webpack from 'webpack';  import babelConfigServer from '..\/..\/babel.config';  export const loaderBabelServer: webpack.RuleSetLoader = {   loader: 'babel-loader',   options: {     presets: [       [         '@babel\/preset-env',         {           targets: {             node: 'current',           },         },       ],     ],     plugins: [...babelConfigServer.plugins, '@babel\/plugin-transform-react-jsx'],   }, };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u0434, \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u043c \u0438\u0437 <code>browserslist<\/code> \u0432 <em>package.json<\/em> \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u0438\u0444\u0438\u043b\u043b\u043e\u0432, \u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u2014 \u0432 \u043a\u043e\u0434, \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Node.js.<\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">F: webpack-custom\/loaders\/loaderFiles.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @docs: https:\/\/github.com\/webpack-contrib\/file-loader  *  *\/  import webpack from 'webpack';  export const loaderFiles: webpack.RuleSetLoader = {   loader: 'file-loader',   options: {     name: '[contenthash].[ext]',     outputPath: 'images',     emitFile: true,   }, };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">B: webpack-custom\/loaders\/loaderFilesServer.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @docs: https:\/\/github.com\/webpack-contrib\/file-loader  *  *\/  import webpack from 'webpack';  export const loaderFilesServer: webpack.RuleSetLoader = {   loader: 'file-loader',   options: {     name: '[contenthash].[ext]',     outputPath: 'images',     emitFile: false,   }, }; <\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 src \u0432 build \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u044d\u0442\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u0430\u044f. <\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">F: webpack-custom\/rules\/ruleSass.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">const loaderCss: webpack.RuleSetLoader = {   loader: 'css-loader',   options: {     importLoaders: 1,     modules: {       localIdentName: '[folder]__[local]',     },   }, };  export const ruleSass: webpack.Rule = {   test: \/\\.s?css$\/,   include: [paths.sourcePath],   use: [loaderExtractCss, loaderCss, loaderPostcss], };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">B: webpack-custom\/rules\/loaderCssServer.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">const loaderCssServer: webpack.RuleSetLoader = {   loader: 'css-loader',   options: {     importLoaders: 1,     onlyLocals: true,     modules: {       localIdentName: '[folder]__[local]',     },   }, };  export const ruleSassServer: webpack.Rule = {   test: \/\\.s?css$\/,   include: [paths.sourcePath],   use: [loaderCssServer, loaderPostcss], };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0441\u0431\u043e\u0440\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0438\u043b\u0438 \u0432 css-\u0444\u0430\u0439\u043b\u044b, \u0430 \u0431\u044d\u043a\u0435\u043d\u0434-\u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0438\u0445 \u0432 js-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u0438\u0434\u0430 <code>{ myClass: &quot;FolderName__myClass&quot; }<\/code> \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 <code>onlyLocals: true<\/code>.<\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u2014 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0411\u044d\u043a\u0435\u043d\u0434\u043e\u0432\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u043a\u0435\u0442\u0430\u043c \u0438\u0437 <em>node_modules<\/em> \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432 \u0441\u0435\u0431\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0443\u0436\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 <code>externals: [nodeExternals()]<\/code>. \u0412\u043e \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0444\u0430\u0439\u043b\u043e\u0432 (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0447\u0430\u043d\u043a\u0438 + \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u0437 <code>cacheGroups<\/code>).<\/p>\n<p>  <\/p>\n<h3 id=\"3-sozdat-recept-dlya-parallelnoy-sborki\">3. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0435\u0446\u0435\u043f\u0442 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0438\u0441\u044c \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437. \u0421 \u044d\u0442\u0438\u043c \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <a href=\"https:\/\/github.com\/rvagg\/node-worker-farm\" rel=\"nofollow\">node-worker-farm<\/a> \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/github.com\/trivago\/parallel-webpack\" rel=\"nofollow\">parallel-webpack<\/a>. \u042d\u0442\u043e\u0442 \u043f\u0430\u043a\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u043e\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 <code>node-ipc<\/code> \u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u043b\u043b\u0431\u044d\u043a. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0438 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <em>webpackParallel.config.ts<\/em> \u0441 \u0440\u0435\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u043e\u043c:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">webpack-custom\/webpackParallel.config.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import webpackClientConfig from '.\/webpackClient.config'; import webpackServerConfig from '.\/webpackServer.config';  export default [webpackClientConfig, webpackServerConfig];<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"pgsql\">. |-- webpack-custom |   |-- configs |   |-- loaders |   |-- plugins |   |-- rules |   |-- utils |   `-- package.json |   `-- webpackBuider.ts |   `-- webpackClient.config.ts |   `-- webpackParallel.config.ts |   `-- webpackServer.config.ts<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0431\u0438\u043b\u0434\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043e\u0447\u0438\u0449\u0435\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u0431\u0438\u043b\u0434\u0430 (\u044d\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c Webpack \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u043e\u0432 \u0432\u0432\u0438\u0434\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438);<\/li>\n<li>\u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438;<\/li>\n<li>\u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0437\u0430\u043f\u0443\u0441\u043a \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 node.js \u0441\u0435\u0440\u0432\u0435\u0440\u0430 + \u0437\u0430\u043f\u0443\u0441\u043a \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0449\u0435\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u0441 \u0432\u044b\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0432 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0434\u043b\u044f \u043e\u0431\u043e\u0438\u0445.\n<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"4-sozdat-recepty-dlya-zapuska\">4. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0435\u0446\u0435\u043f\u0442\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430<\/h3>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">package.json<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"json\">{   &quot;scripts&quot;: {     &quot;dev&quot;: &quot;better-npm-run -s dev&quot;,     &quot;build&quot;: &quot;better-npm-run build&quot;,     &quot;start&quot;: &quot;better-npm-run start&quot;   },   &quot;betterScripts&quot;: {     &quot;dev&quot;: {       &quot;command&quot;: &quot;better-npm-run -s build&quot;,       &quot;env&quot;: {         &quot;START_SERVER_AFTER_BUILD&quot;: true       }     },     &quot;build&quot;: {       &quot;command&quot;: &quot;babel-node --extensions .ts,.tsx .\/webpack-custom\/webpackBuider.ts&quot;     },     &quot;reload-browser&quot;: {       &quot;command&quot;: &quot;babel-node --extensions .ts,.tsx .\/server\/watchServer.ts&quot;     },     &quot;start&quot;: {       &quot;command&quot;: &quot;nodemon -q .\/build\/server.js&quot;     }   } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0444\u0430\u0439\u043b\u0430, dev-\u0440\u0435\u0436\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 (\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 -s \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445) \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>START_SERVER_AFTER_BUILD<\/code>, \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f env-\u0444\u0430\u0439\u043b\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b babel-node \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Typescript \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433 \u0434\u043b\u044f \u0431\u0430\u0431\u0435\u043b\u044f \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434 \u0432 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 node.js:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">babel.config.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">module.exports = {   presets: [     [       '@babel\/preset-env',       {         targets: {           node: 'current',         },       },     ],   ],   plugins: [     [       '@babel\/plugin-transform-typescript',       { isTSX: true, allExtensions: true, allowDeclareFields: true },     ],     ['@babel\/plugin-proposal-decorators', { legacy: true }],     ['@babel\/plugin-proposal-class-properties', { loose: true }],   ], };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d\u044b \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 (\u043a\u0440\u043e\u043c\u0435 <code>@babel\/plugin-transform-typescript<\/code>) \u043d\u0435 \u043d\u0443\u0436\u043d\u044b, \u043d\u043e \u044f \u0432\u044b\u043d\u0435\u0441 \u0438\u0445 \u0432 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 babel-loader&#8217;\u0430\u0445 (\u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438).<\/p>\n<p>  <\/p>\n<h3 id=\"5-nastroit-perezapusk-servera\">5. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0436\u0435\u043d\u0438\u044f \u0437\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u0430 server.js \u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/remy\/nodemon\" rel=\"nofollow\">nodemon<\/a>, \u043a\u0430\u043a \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432\u044b\u0448\u0435 \u0432 \u0440\u0435\u0446\u0435\u043f\u0442\u0435 <code>&quot;start&quot;: &quot;nodemon -q .\/build\/server.js&quot;<\/code>. \u0414\u043b\u044f watch-\u0440\u0435\u0436\u0438\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">nodemon.json<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"json\">{   &quot;verbose&quot;: false,   &quot;watch&quot;: [&quot;build\/server.js&quot;] }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"6-nastroit-obnovlenie-brauzera\">6. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/h3>\n<p>  <\/p>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432 node.js \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043b\u043e\u0436\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0445 \u0432\u0432\u0438\u0434\u0443 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0431\u0438\u043b\u0434\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0434\u0435\u043b\u0430\u043b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0446\u0435\u043f\u0442 <code>&quot;reload-browser&quot;: &quot;babel-node --extensions .ts,.tsx .\/server\/watchServer.ts&quot;<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. \u0426\u0435\u043b\u044c \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u2014 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c WebSocket \u0441\u0435\u0440\u0432\u0435\u0440 + file watcher \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 \u0431\u0438\u043b\u0434\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">server\/watchServer.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @docs: https:\/\/github.com\/websockets\/ws  * @docs: https:\/\/github.com\/yuanchuan\/node-watch  *  *\/  import fs from 'fs'; import path from 'path'; import http from 'http'; import https from 'https';  import ws from 'ws'; import watch from 'node-watch'; import express from 'express';  import { env } from '..\/env'; import { paths } from '..\/paths'; import { configEntryServer } from '..\/webpack-custom\/configs\/configEntryServer';  function startReloadServer() {   const sslOptions = {     key: fs.readFileSync(path.resolve(paths.rootPath, 'ssl-local\/cert.key')),     cert: fs.readFileSync(path.resolve(paths.rootPath, 'ssl-local\/cert.pem')),   };    const app = express();    app.get('\/reload\/reload.js', (req, res) =&gt; {     res.type('text\/javascript');     res.send(` (function refresh() {   let socketUrl = window.location.origin;   if (!socketUrl.match(\/:[0-9]+\/)) {     socketUrl = socketUrl + ':80';   }   socketUrl = socketUrl.replace(\/(^http(s?):\\\\\/\\\\\/)(.*:)(.*)\/,${`'ws$2:\/\/$3${env.HOT_RELOAD_PORT}`}');    function websocketWaiter() {     const socket = new WebSocket(socketUrl);      socket.onmessage = function socketOnMessage(msg) {       if (msg.data === 'reload') {         socket.close();         window.location.reload();       }     };      socket.onclose = function socketOnClose() {       setTimeout(function reconnectSocketDelayed() {         websocketWaiter();       }, 1000);     };   }    window.addEventListener('load', websocketWaiter); })(); `);   });    const server = env.HTTPS_BY_NODE ? https.createServer(sslOptions, app) : http.createServer(app);    return new ws.Server({ server: server.listen(env.HOT_RELOAD_PORT) }); }  function startFileWatcher({ onFilesChanged }: { onFilesChanged: () =&gt; void }) {   const excludedFilenames = Object.keys(configEntryServer);   let changedFiles = [];   let watchDebounceTimeout = null;    const watchOptions = {     recursive: false,     filter: filePath =&gt; !excludedFilenames.some(fileName =&gt; filePath.indexOf(fileName) !== -1),   };    watch(paths.buildPath, watchOptions, function fileChanged(event, filePath) {     const { base: fileName } = path.parse(filePath);      changedFiles.push(fileName);      clearTimeout(watchDebounceTimeout);     watchDebounceTimeout = setTimeout(() =&gt; {       console.log(`triggered by`, changedFiles);        changedFiles = [];        onFilesChanged();     }, 50);   }); }  const wss = startReloadServer();  startFileWatcher({   onFilesChanged() {     wss.clients.forEach(client =&gt; {       if (client.readyState === ws.OPEN) client.send('reload');     });   }, });<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c <code>HOT_RELOAD_URL\/reload\/reload.js<\/code>, \u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u044b. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0440\u0435\u0440\u0432\u0430\u043d, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u2014 \u0438 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u043e \u0431\u0435\u0441\u0448\u043e\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u0440\u0438 \u043d\u043e\u0432\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445. \u0422\u0430\u043a \u043a\u0430\u043a \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0433\u0440\u0430\u0434\u0430\u0446\u0438\u0439 \u0434\u043e long polling \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0441\u043b\u0435\u0436\u0435\u043d\u0438\u0438 \u0437\u0430 \u043f\u0430\u043f\u043a\u043e\u0439 build \u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u043b \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0438 \u0444\u0430\u0439\u043b server.js, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0447\u0438\u0441\u0442\u043e \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0443\u0442 \u043b\u0438\u0448\u044c \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e. \u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e <code>filePath.indexOf(fileName) !== -1<\/code> \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442 \u2014 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0444\u0430\u0439\u043b\u044b, \u0432 \u0447\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d\u0438 \u0438\u043b\u0438 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u043f\u0430\u043f\u043a\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0430 &quot;server&quot;. \u041e\u0441\u0442\u0430\u0432\u0438\u043b \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043f\u0438\u0448\u0443\u0442 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430\u0445.<\/p>\n<p>  <\/p>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u0435\u0431\u0430\u0443\u043d\u0441 \u0441\u0434\u0435\u043b\u0430\u043d \u0434\u043b\u044f \u0435\u0434\u0438\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0432\u0435\u0431\u043f\u0430\u043a\u043e\u043c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u043c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0446\u0438\u0444\u0440\u0430 50 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0441\u0430\u043a\u0440\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043c\u044b\u0441\u043b\u0430, \u0434\u0443\u043c\u0430\u044e, \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044c\u0448\u0430\u044f, \u043d\u043e \u043d\u0435 0 \u0432\u0432\u0438\u0434\u0443 \u0437\u0430\u0434\u0435\u0440\u0436\u0435\u043a \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f <code>node-watch<\/code> \u0438 \u043d\u0435\u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432\u0435\u0431\u043f\u0430\u043a\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u0435\u0441\u0442\u0438\u0441\u044c \u043d\u0430 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u043e\u0439 \u043a \u0441\u0442\u0435\u043d\u0434\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u0442\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u043b \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e HTTPS, \u0447\u0442\u043e\u0431\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u043d\u0435 \u0432\u044b\u0434\u0430\u0432\u0430\u043b\u0438\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0438\u0437 \u0440\u0430\u0437\u0440\u044f\u0434\u0430 mixed content.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">server\/routeMiddlewares\/handlePageRoutes.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import fs from 'fs'; import path from 'path';  import { injectAppMarkup } from 'serverUtils';  import { env } from '..\/..\/env'; import { paths } from '..\/..\/paths';  const template = fs.readFileSync(path.resolve(paths.buildPath, 'template.html'), 'utf-8');  export function handlePageRoutes(app) {   app.get('*', (req, res) =&gt; {     Promise.resolve()       .then(() =&gt; injectAppMarkup(template))       .then(modTemplate =&gt; injectBrowserReload(modTemplate))       .then(modTemplate =&gt; res.send(modTemplate))       .catch(error =&gt; {         console.error(error);          res.status(500);         res.send('Unpredictable error');       });   }); }  const hotReloadUrl = `${env.HTTPS_BY_NODE ? 'https' : 'http'}:\/\/localhost:${   env.HOT_RELOAD_PORT }\/reload\/reload.js`;  export function injectBrowserReload(str) {   if (!env.HOT_RELOAD) return str;    return str.replace('&lt;\/body&gt;', `&lt;script src=&quot;${hotReloadUrl}&quot;&gt;&lt;\/script&gt;&lt;\/body&gt;`); }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412\u0441\u0435, \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0443 \u0441 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c, \u043b\u0438\u0431\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0438\u043b\u044f\u043c\u0438 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u0443\u044e \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0443 (\u043d\u043e \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 js-\u043e\u0431\u044a\u0435\u043a\u0442, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043e\u0431\u0435\u0438\u043c \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0430\u043c). \u041f\u0440\u0438 \u044d\u0442\u043e\u043c file watcher \u0433\u0438\u0431\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u043d\u0430 \u0447\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u2014 \u0447\u0442\u043e parallel-webpack \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438, \u0430 \u044d\u0442\u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 (\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u043c\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u0441\u0442\u0430\u0442\u044c\u044e), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. <\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439: <a href=\"https:\/\/github.com\/dkazakov8\/habr_webpack-isomorphic\" rel=\"nofollow\">https:\/\/github.com\/dkazakov8\/habr_webpack-isomorphic<\/a><\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u0434\u0438\u043d\u0433\u0430.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/506636\/\"> https:\/\/habr.com\/ru\/post\/506636\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/506636\/\">\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043a\u0430\u0436\u0443\u0449\u0443\u044e\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 \u0442\u0435\u043c\u044b, \u043c\u043d\u0435 \u043d\u0435 \u0434\u043e\u0432\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043d\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0433\u0434\u0435 \u0441\u0431\u043e\u0440\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0435\u0439 \u0431\u044b\u043b\u0430 \u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0443\u0434\u043e\u0431\u043d\u043e, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u043b\u0430\u0434\u0430\u043b\u0430 \u0431\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u044d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e (\u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u0445)<\/li>\n<li>\u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/li>\n<li>\u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/li>\n<li>\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442 \u043e\u0431\u0435 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438, \u0430 \u043d\u0435\u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e<\/li>\n<li>\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (\u043f\u043e\u0440\u0442 watch-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, https-\u0440\u0435\u0436\u0438\u043c) \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 env-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041a\u043e\u043b\u043b\u0435\u0433\u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043b\u0438 \u043b\u0438\u0448\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u044d\u0442\u0438\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043b\u044e\u0431\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u043e \u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0442.\u043a. \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u043b\u0438\u0431\u043e middleware, \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043b\u0438\u0431\u043e watch-\u0441\u0435\u0440\u0432\u0435\u0440 webpack, \u043d\u043e \u0432\u0438\u0434\u0435\u043b \u0438 \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043c\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439, \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0432\u0441\u0435 \u043f\u043e \u043f\u043e\u043b\u043e\u0447\u043a\u0430\u043c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-305353","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/305353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=305353"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/305353\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=305353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=305353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=305353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}