{"id":279193,"date":"2016-04-27T14:35:04","date_gmt":"2016-04-27T10:35:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=279193"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=279193","title":{"rendered":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Webpack \u0432\u043c\u0435\u0441\u0442\u043e Sprockets \u0432 Ruby on Rails"},"content":{"rendered":"\n<p>\u0417\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 frontend \u0447\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Ruby on Rails \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/github.com\/rails\/sprockets\">Sprockets<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0434\u043e\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u0434\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0435 \u0434\u043e\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/www.reinteractive.net\/posts\/213-rails-with-webpack-why-and-how\">\u0437\u0434\u0435\u0441\u044c<\/a> \u0438 <a href=\"https:\/\/forum.shakacode.com\/t\/using-webpack-with-rails\/199\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0425\u043e\u0442\u044f \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0441\u0432\u044f\u0437\u043a\u0438 webpack+rails \u0438 \u0434\u0430\u0436\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/mipearson\/webpack-rails\">\u0433\u0435\u043c<\/a> \u0435\u0441\u0442\u044c, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434, \u0443\u043c\u0435\u044e\u0449\u0438\u0439 \u0442\u0430\u043a\u0436\u0435 \u0434\u0435\u043f\u043b\u043e\u0439 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/46b\/72c\/225\/46b72c225cf54a15aaa4055c07a8ed6b.png\"\/><br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0432\u0441\u0435 frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 <code>#{Rails.root}\/frontend<\/code>. \u0412 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 <code>assets<\/code> \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>image_tag<\/code>.<br \/>  \u0414\u043b\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c Node JS, npm, \u0441\u0430\u043c webpack \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u043a \u043d\u0435\u043c\u0443. \u0422\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 <code>.gitignore<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code>\/node_modules \/public\/assets \/webpack-assets.json \/webpack-assets-deploy.json<\/code><\/pre>\n<p>  <\/p>\n<h1>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f webpack<\/h1>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u044b webpack \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0444\u0430\u0439\u043b <code>webpack.config.js<\/code>.<br \/>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0445 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>NODE_ENV<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ frontend\/webpack.config.js  const webpack = require('webpack'); const merge = require('webpack-merge');  const env = process.env.NODE_ENV || 'development';  module.exports = merge(   require('.\/base.config.js'),   require(`.\/${env}.config.js`) ); <\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u043c\u044b \u0437\u0430\u0434\u0430\u0435\u043c \u043e\u0431\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439, \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u0432, \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <a href=\"https:\/\/webpack.github.io\/docs\/multiple-entry-points.html\">\u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430<\/a> \u0434\u043b\u044f frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<p>  <\/p>\n<pre><code>\/\/ frontend\/base.config.js  const path = require('path'); const webpack = require('webpack');  module.exports = {   context: __dirname,   output: {     \/\/ \u043f\u0443\u0442\u044c \u043a \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c     path: path.join(__dirname, '..', 'public', 'assets'),     filename: 'bundle-[name].js'   },    \/\/  \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 (entry point)   entry: {     \/\/ \u0437\u0434\u0435\u0441\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432: ['.\/app\/base-entry'], \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e     \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043e\u0434\u043d\u0438 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0434\u0440\u0443\u0433\u0438\u0435     \/\/ \u043e\u0431\u0435\u0449\u0430\u044e\u0442 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u0435\u0440\u0441\u0438\u0438 2.0     application: ['.\/app\/base-entry'],     main_page: ['.\/app\/pages\/main'],     admin_panel: ['.\/app\/pages\/admin_panel']   },   resolve: {     \/\/ \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c require \u0431\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f     extensions: ['', '.js', '.coffee'],     modulesDirectories: [ 'node_modules' ],      \/\/ \u0435\u0449\u0435 \u043e\u0434\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f require: \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c     \/\/ require('libs\/some.lib')     alias: {       libs: path.join(__dirname, 'libs')     }   },   module: {     loaders: [       \/\/ \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 ES6       {         test: \/\\.js$\/,         include: [ path.resolve(__dirname + 'frontend\/app') ],         loader: 'babel?presets[]=es2015'       },        \/\/ \u0434\u043b\u044f CoffeeScript       { test: \/\\.coffee$\/, loader: 'coffee-loader' },        \/\/ \u0434\u043b\u044f Vue JS \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432       { test: \/\\.vue$\/, loader: 'vue' },        \/\/ \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 jquery \u043f\u0440\u0438       \/\/ \u043f\u0435\u0440\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c $ \u0438\u043b\u0438       { test: require.resolve('jquery'), loader: 'expose?$!expose?jQuery' }     ],   },   plugins: [     \/\/ \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 RAILS_ENV \u0432 js \u043a\u043e\u0434\u0435     new webpack.DefinePlugin({       __RAILS_ENV__: JSON.stringify(process.env.RAILS_ENV || 'development')       ),     })   ] }; <\/code><\/pre>\n<p>  <\/p>\n<h2>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 development<\/h2>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f development \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c \u0440\u0435\u0436\u0438\u043c\u043e\u043c \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0438 source map. \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e Vue JS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0437\u0434\u0435\u0441\u044c <a href=\"https:\/\/github.com\/vuejs\/vue-loader\/issues\/146\">\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0438\u043a\u0441<\/a> \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<br \/>  \u0422\u0430\u043a\u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u0435\u0439, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0448\u0440\u0438\u0444\u0442\u043e\u0432 (\u0434\u043b\u044f production \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u0438\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f).<\/p>\n<p>  <\/p>\n<pre><code>\/\/ frontend\/development.config.js  const webpack = require('webpack'); const AssetsPlugin = require('assets-webpack-plugin');  module.exports = {   debug: true,   displayErrorDetails: true,   outputPathinfo: true,   \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c source map   devtool: 'eval-source-map',   output: {     \/\/ \u0444\u0438\u043a\u0441 \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f source map \u0443 Vue JS \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432     devtoolModuleFilenameTemplate: info =&gt; {       if (info.resource.match(\/\\.vue$\/)) {         $filename = info.allLoaders.match(\/type=script\/)                   ? info.resourcePath : 'generated';       } else {         $filename = info.resourcePath;       }       return $filename;     },   },   module: {     loaders: [       { test: \/\\.css$\/, loader: 'style!css?sourceMap' },        \/\/ \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d resolve-url,       \/\/ \u0447\u0442\u043e\u0431\u044b \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043a \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c       \/\/ \u0432\u043d\u0443\u0442\u0440\u0438 *.scss \u0444\u0430\u0439\u043b\u043e\u0432       {         test: \/\\.scss$\/,         loader: 'style!css?sourceMap!resolve-url!sass?sourceMap'       },        \/\/ \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f       {         test: \/\\.(png|jpg|gif)$\/,         loader: 'url?name=[path][name].[ext]&amp;limit=8192'       },        \/\/ \u0448\u0440\u0438\u0444\u0442\u044b       {         test: \/\\.(ttf|eot|svg|woff(2)?)(\\?.+)?$\/,         loader: 'file?name=[path][name].[ext]'       }     ]   },   plugins: [     \/\/ \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0444\u0430\u0439\u043b\u0430-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d     \/\/ \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f js \u0438 css     new AssetsPlugin({ prettyPrint: true })   ] }; <\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0435\u0449\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u043a\u0443, \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u041f\u0440\u0438\u044f\u0442\u043d\u044b\u0439 \u0431\u043e\u043d\u0443\u0441 \u2014 hot module replacement \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u0435\u0439 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u0434\u0430, \u0430 Javascript \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Vue JS \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ frontend\/server.js  const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); const config = require('.\/webpack.config'); const hotRailsPort = process.env.HOT_RAILS_PORT || 3550;  config.output.publicPath = `http:\/\/localhost:${hotRailsPort}\/assets\/`; ['application', 'main_page',   'inner_page', 'product_page', 'admin_panel'].forEach(entryName =&gt; {   config.entry[entryName].push(     'webpack-dev-server\/client?http:\/\/localhost:' + hotRailsPort,     'webpack\/hot\/only-dev-server'   ); });  config.plugins.push(   new webpack.optimize.OccurenceOrderPlugin(),   new webpack.HotModuleReplacementPlugin(),   new webpack.NoErrorsPlugin() );  new WebpackDevServer(webpack(config), {   publicPath: config.output.publicPath,   hot: true,   inline: true,   historyApiFallback: true,   quiet: false,   noInfo: false,   lazy: false,   stats: {     colors: true,     hash: false,     version: false,     chunks: false,     children: false,   } }).listen(hotRailsPort, 'localhost', function (err, result) {   if (err) console.log(err)   console.log(     '=&gt; Webpack development server is running on port ' + hotRailsPort   ); })<\/code><\/pre>\n<p>  <\/p>\n<h2>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 production<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f production \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c CSS \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>extract-text-webpack-plugin<\/code>. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ frontend\/production.config.js  const path = require('path') const webpack = require('webpack'); const CleanPlugin = require('clean-webpack-plugin'); const ExtractTextPlugin = require(&quot;extract-text-webpack-plugin&quot;); const CompressionPlugin = require(&quot;compression-webpack-plugin&quot;); const AssetsPlugin = require('assets-webpack-plugin');  module.exports = {   output: {     \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043c \u0445\u0435\u0448 \u0432 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430     filename: '.\/bundle-[name]-[chunkhash].js',     chunkFilename: 'bundle-[name]-[chunkhash].js',     publicPath: '\/assets\/'   },   module: {     loaders: [       \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f CSS \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b       {         test: \/\\.css$\/,         loader: ExtractTextPlugin.extract(&quot;style-loader&quot;, &quot;css?minimize&quot;)       },        \/\/ sourceMap \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437-\u0437\u0430 \u0431\u0430\u0433\u0430       {         test: \/\\.scss$\/,         loader: ExtractTextPlugin.extract(           &quot;style-loader&quot;, &quot;css?minimize!resolve-url!sass?sourceMap&quot;         )       },       { test: \/\\.(png|jpg|gif)$\/, loader: 'url?limit=8192' },       {         test: \/\\.(ttf|eot|svg|woff(2)?)(\\?.+)?$\/,         loader: 'file'       },     ]   },   plugins: [     \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0440\u0435\u043b\u0438\u0437\u0435 \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c     \/\/ developoment \u0432\u0435\u0440\u0441\u0438\u044e     new AssetsPlugin({       prettyPrint: true, filename: 'webpack-assets-deploy.json'     }),      \/\/ \u0444\u0430\u0439\u043b \u0441 \u043e\u0431\u0449\u0438\u043c js-\u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u043e\u0447\u0435\u043a \u0432\u0445\u043e\u0434\u0430     \/\/ Webpack \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c     new webpack.optimize.CommonsChunkPlugin(       'common', 'bundle-[name]-[hash].js'     ),      \/\/ \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c CSS \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b     new ExtractTextPlugin(&quot;bundle-[name]-[chunkhash].css&quot;, {       allChunks: true     }),      \/\/ \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f...     new webpack.optimize.DedupePlugin(),     new webpack.optimize.OccurenceOrderPlugin(),     new webpack.optimize.UglifyJsPlugin({       mangle: true,       compress: {         warnings: false       }     }),      \/\/ \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f gzip \u0432\u0435\u0440\u0441\u0438\u0439     new CompressionPlugin({ test: \/\\.js$|\\.css$\/ }),      \/\/ \u043e\u0447\u0438\u0441\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u0434 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u043e\u0439     new CleanPlugin(       path.join('public', 'assets'),       { root: path.join(process.cwd()) }     )   ] }; <\/code><\/pre>\n<p>  <\/p>\n<h2>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Ruby on Rails<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u043e\u043f\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\/\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 webpack \u0441\u0442\u0430\u0442\u0438\u043a\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u041f\u043e\u043b\u0435\u0437\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u043a\u0443.<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># config\/application.rb  config.use_webpack = true<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"ruby\"># config\/environments\/test.rb  config.use_webpack = false<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 Rails-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># config\/initializers\/webpack.rb  assets_manifest = Rails.root.join('webpack-assets.json') if File.exist?(assets_manifest)   Rails.configuration.webpack = {}   manifest = JSON.parse(File.read assets_manifest).with_indifferent_access   manifest.each do |entry, assets|     assets.each do |kind, asset_path|       if asset_path =~ \/(http[s]?):\\\/\\\/\/i         manifest[entry][kind] = asset_path       else         manifest[entry][kind] = Pathname.new(asset_path).cleanpath.to_s       end     end   end   Rails.configuration.webpack[:assets_manifest] = manifest    # \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e Sprockets \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a;   # \u043f\u043e\u044d\u0442\u043e\u043c\u0443 webpack \u0445\u0435\u043b\u043f\u0435\u0440\u044b (\u0441\u043c. \u043d\u0438\u0436\u0435) \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Sprockets   Rails.application.config.assets.configure do |env|     env.context_class.class_eval do       include Webpack::Helpers     end   end else   raise &quot;File #{assets_manifest} not found&quot; if Rails.configuration.use_webpack end <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 webpack \u0445\u0435\u043b\u043f\u0435\u0440\u044b <code>webpack_bundle_js_tags<\/code> \u0438 <code>webpack_bundle_css_tags<\/code>, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u0438\u0437 \u0441\u0435\u0431\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0434\u043b\u044f <code>javascript_include_tag<\/code> \u0438 <code>stylesheet_link_tag<\/code>. \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0430 webpack<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># lib\/webpack\/helpers.rb  module Webpack   module Helpers     COMMON_ENTRY = 'common'      def webpack_bundle_js_tags(entry)       webpack_tags :js, entry     end      def webpack_bundle_css_tags(entry)       webpack_tags :css, entry     end      def webpack_tags(kind, entry)       common_bundle = asset_tag(kind, COMMON_ENTRY)       page_bundle   = asset_tag(kind, entry)       if common_bundle         common_bundle + page_bundle       else         page_bundle       end     end      def asset_tag(kind, entry)       if Rails.configuration.use_webpack         manifest = Rails.configuration.webpack[:assets_manifest]         if manifest.dig(entry, kind.to_s)           file_name = manifest[entry][kind]           case kind           when :js             javascript_include_tag file_name           when :css             stylesheet_link_tag file_name           else             throw &quot;Unknown asset kind: #{kind}&quot;           end         end       end     end   end end<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0441 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># app\/controllers\/application_controller.rb  class ApplicationController &lt; ActionController::Base    attr_accessor :webpack_entry_name   helper_method :webpack_entry_name    def self.webpack_entry_name(name)     before_action -&gt; (c) { c.webpack_entry_name = name }   end end<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># app\/controllers\/main_controller.rb  class MainController &lt; ApplicationController   webpack_entry_name 'main_page' end<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043e view:<\/p>\n<p>  <\/p>\n<pre><code>&lt;html&gt;   &lt;head&gt;     &lt;%= webpack_bundle_css_tags(webpack_entry_name) %&gt;   &lt;\/head&gt;   &lt;body&gt;      &lt;%= webpack_bundle_js_tags(webpack_entry_name) %&gt;       &lt;\/body&gt; &lt;\/html&gt; <\/code><\/pre>\n<p>  <\/p>\n<h1>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>npm<\/code><\/h1>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 frontend \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code>npm install &lt;package_name&gt; --save<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0439\u043d\u0435 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e &quot;\u0437\u0430\u043c\u043e\u0440\u043e\u0437\u0438\u0442\u044c&quot; \u0442\u043e\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u0441\u0435\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>npm-shrinkwrap.json<\/code> (\u0430\u043d\u0430\u043b\u043e\u0433 <code>Gemfile.lock<\/code>). \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 (\u0445\u043e\u0442\u044f <code>npm<\/code> \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441\u043b\u0435\u0434\u0438\u0442 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e <code>npm-shrinkwrap.json<\/code>, \u043b\u0443\u0447\u0448\u0435 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u0442\u044c\u0441\u044f):<\/p>\n<p>  <\/p>\n<pre><code>npm shrinkwrap --dev<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0432 <code>package.json<\/code> \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u0435\u043a\u0446\u0438\u044e <code>scripts<\/code> webpack-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code>&quot;scripts&quot;: {   &quot;server&quot;: &quot;node frontend\/server.js&quot;,   &quot;build:dev&quot;: &quot;webpack -v --config frontend\/webpack.config.js --display-chunks --debug&quot;,   &quot;build:production&quot;: &quot;NODE_ENV=production webpack -v --config frontend\/webpack.config.js --display-chunks&quot; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c webpack \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code>npm run server<\/code><\/pre>\n<p>  <\/p>\n<h1>\u0414\u0435\u043f\u043b\u043e\u0439: \u0440\u0435\u0446\u0435\u043f\u0442 \u0434\u043b\u044f capistrano<\/h1>\n<p>  <\/p>\n<p>\u042f \u0432\u044b\u0431\u0440\u0430\u043b \u044d\u043a\u043e\u043d\u043e\u043c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442: \u043d\u0435 \u0442\u0430\u0449\u0438\u0442\u044c \u0432\u0435\u0441\u044c JS-\u0437\u043e\u043e\u043f\u0430\u0440\u043a \u043d\u0430 production \u0441\u0435\u0440\u0432\u0435\u0440, \u0430 \u0434\u0435\u043b\u0430\u0442\u044c webpack \u0441\u0431\u043e\u0440\u043a\u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0435\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>rsync<\/code>.<br \/>  \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>deploy:webpack:build<\/code>, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0433\u0435\u043c\u0435 <a href=\"https:\/\/github.com\/capistrano-plugins\/capistrano-faster-assets\">capistrano-faster-assets<\/a>. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u043b\u043e\u0432\u043d\u043e: \u0435\u0441\u043b\u0438 \u0431\u044b\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 fronend \u043a\u043e\u0434\u0435 \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>:webpack_dependencies<\/code>. \u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u043a\u0438 \u0438 \u0444\u0430\u0439\u043b-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># config\/deploy.rb  set :webpack_dependencies, %w(frontend npm-shrinkwrap.json) set :local_assets_dir, proc { File.expand_path(&quot;..\/..\/public\/#{fetch(:assets_prefix)}&quot;, __FILE__) } set :local_webpack_manifest, proc { File.expand_path(&quot;..\/..\/webpack-assets-deploy.json&quot;, __FILE__) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>deploy:webpack:build<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 <code>deploy:compile_assets<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0430\u043c \u043a\u043e\u0434 \u0440\u0435\u0446\u0435\u043f\u0442\u0430 \u0434\u043b\u044f capistrano:<\/p>\n<p>  <\/p>\n<pre><code class=\"ruby\"># lib\/capistrano\/tasks\/webpack_build.rake  class WebpackBuildRequired &lt; StandardError; end  namespace :deploy do   namespace :webpack do     desc &quot;Webpack build assets&quot;     task build: 'deploy:set_rails_env' do       on roles(:all) do         begin           latest_release = capture(:ls, '-xr', releases_path).split[1]           raise WebpackBuildRequired unless latest_release           latest_release_path = releases_path.join(latest_release)           dest_assets_path = shared_path.join('public', fetch(:assets_prefix))            fetch(:webpack_dependencies).each do |dep|             release = release_path.join(dep)             latest = latest_release_path.join(dep)             # skip if both directories\/files do not exist             next if [release, latest].map{ |d| test &quot;test -e #{d}&quot; }.uniq == [false]             # execute raises if there is a diff             execute(:diff, '-Nqr', release, latest) rescue raise(WebpackBuildRequired)           end            info &quot;Skipping webpack build, no diff found&quot;            execute(             :cp,             latest_release_path.join('webpack-assets.json'),             release_path.join('webpack-assets.json')           )         rescue WebpackBuildRequired           invoke 'deploy:webpack:build_force'         end       end     end     before 'deploy:compile_assets', 'deploy:webpack:build'      task :build_force do       run_locally do         info 'Create webpack local build'         %x(RAILS_ENV=#{fetch(:rails_env)} npm run build:production)         invoke 'deploy:webpack:sync'       end     end      desc &quot;Sync locally compiled assets with current release path&quot;     task :sync do       on roles(:all) do         info 'Sync assets...'         upload!(           fetch(:local_webpack_manifest),           release_path.join('webpack-assets.json')         )       end       roles(:all).each do |host|         run_locally do           `rsync -avzr #{fetch(:local_assets_dir)} #{host.user}@#{host.hostname}:#{shared_path.join('public')}`         end       end     end   end  end<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435 \ud83d\ude09<\/p>\n<div class=\"clear\"><\/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:\/\/habrahabr.ru\/post\/282584\/\"> https:\/\/habrahabr.ru\/post\/282584\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<p>\u0417\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 frontend \u0447\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Ruby on Rails \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/github.com\/rails\/sprockets\">Sprockets<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0434\u043e\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u0434\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e frontend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0435 \u0434\u043e\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/www.reinteractive.net\/posts\/213-rails-with-webpack-why-and-how\">\u0437\u0434\u0435\u0441\u044c<\/a> \u0438 <a href=\"https:\/\/forum.shakacode.com\/t\/using-webpack-with-rails\/199\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0425\u043e\u0442\u044f \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0441\u0432\u044f\u0437\u043a\u0438 webpack+rails \u0438 \u0434\u0430\u0436\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/mipearson\/webpack-rails\">\u0433\u0435\u043c<\/a> \u0435\u0441\u0442\u044c, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434, \u0443\u043c\u0435\u044e\u0449\u0438\u0439 \u0442\u0430\u043a\u0436\u0435 \u0434\u0435\u043f\u043b\u043e\u0439 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/46b\/72c\/225\/46b72c225cf54a15aaa4055c07a8ed6b.png\"\/>  <\/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-279193","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/279193","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=279193"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/279193\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=279193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=279193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=279193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}