{"componentChunkName":"component---src-templates-post-tsx","path":"/posts/2018/04/04/rails-webpack-webpacker","webpackCompilationHash":"eebfa071629ad42c48b3","result":{"data":{"markdownRemark":{"html":"<p>Rails is great, webpack is great, abstractions are not always great.</p>\n<p>I'm going to start this from a pretty vanilla Rails 5 setup, I started with <code class=\"language-text\">rails new webpacked --webpack</code>.</p>\n<p>Also, for this to work, you'll need webpack > 4.3.0.</p>\n<h2>Remove the webpacker things</h2>\n<p>Remove <code class=\"language-text\">sass-rails</code>, <code class=\"language-text\">uglifier</code>, <code class=\"language-text\">coffee-rails</code>, <code class=\"language-text\">turbolinks</code>, <code class=\"language-text\">webpacker</code> from Gemfile.</p>\n<p>Remove <code class=\"language-text\">config.webpacker.check_yarn_integrity</code> settings in config/envronments.</p>\n<p>Change <code class=\"language-text\">javascript_pack_tag</code> and <code class=\"language-text\">stylesheet_pack_tag</code> to <code class=\"language-text\">javascript_include_tag</code> and <code class=\"language-text\">stylesheet_link_tag</code>.</p>\n<p>Then:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">rm</span> -r bin/webpack config/webpack* public/packs\n$ bundle\n$ <span class=\"token function\">yarn</span> uninstall @rails/webpacker webpack-dev-server</code></pre></div>\n<h2>Disable sprockets</h2>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># config/environments/development.rb</span>\n<span class=\"token constant\">Rails</span><span class=\"token punctuation\">.</span>application<span class=\"token punctuation\">.</span>configure <span class=\"token keyword\">do</span>\n  …\n<span class=\"gatsby-highlight-code-line\">  config<span class=\"token punctuation\">.</span>assets<span class=\"token punctuation\">.</span>compile <span class=\"token operator\">=</span> <span class=\"token keyword\">false</span></span>  …\n<span class=\"token keyword\">end</span></code></pre></div>\n<h2>Install dependencies</h2>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">mkdir</span> public/assets\n$ <span class=\"token function\">touch</span> public/assets/.keep\n$ <span class=\"token function\">yarn</span> <span class=\"token function\">add</span> --dev webpack webpack-<span class=\"token punctuation\">{</span>cli,dev-server<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Check <code class=\"language-text\">/public/assets</code> into git, then Add <code class=\"language-text\">/public/assets</code> to your <code class=\"language-text\">.gitignore</code>. This is where we're going to build assets to for production.</p>\n<h2>Add build scripts</h2>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token comment\">// package.json</span>\n<span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpacked\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"private\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token property\">\"server\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpack-dev-server\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token property\">\"precompile\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"rm -r public/assets/* &amp;&amp; NODE_ENV=production webpack\"</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span>  <span class=\"token property\">\"dependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"devDependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"webpack\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^4.5.0\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"webpack-cli\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^2.0.13\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"webpack-dev-server\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^3.1.1\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2>Add a simple webpack config</h2>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">DIR</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"path\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>__dirname<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PROD</span> <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">NODE_ENV</span> <span class=\"token operator\">===</span> <span class=\"token string\">\"production\"</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  entry<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    application<span class=\"token punctuation\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">DIR</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/app/assets/javascripts/application.js</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  mode<span class=\"token punctuation\">:</span> <span class=\"token constant\">PROD</span> <span class=\"token operator\">?</span> <span class=\"token string\">\"production\"</span> <span class=\"token punctuation\">:</span> <span class=\"token string\">\"development\"</span><span class=\"token punctuation\">,</span>\n  output<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    chunkFilename<span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].js\"</span><span class=\"token punctuation\">,</span>\n    filename<span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].js\"</span><span class=\"token punctuation\">,</span>\n    path<span class=\"token punctuation\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">DIR</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">public/assets/</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  resolve<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    extensions<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\".js\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".json\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".css\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    modules<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"node_modules\"</span><span class=\"token punctuation\">,</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">DIR</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/app/assets</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now start the wepback dev server:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">yarn</span> server\nℹ ｢wds｣: Project is running at http://localhost:8080/\nℹ ｢wds｣: webpack output is served from /\nℹ ｢wdm｣: Hash: ee01dba8920628636a4e\nℹ ｢wdm｣: Compiled successfully.</code></pre></div>\n<p>Go to <a href=\"http://localhost:8080/application.js\">http://localhost:8080/application.js</a> and you should be able to see the compiled webpack bundle.</p>\n<h2>Compile CSS</h2>\n<p>Add the necessary webpack loaders:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">yarn</span> <span class=\"token function\">add</span> -D <span class=\"token punctuation\">{</span>file,extract,css,postcss<span class=\"token punctuation\">}</span>-loader cssnano</code></pre></div>\n<p>And then set up a rule for them:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  …\n<span class=\"gatsby-highlight-code-line\">  module<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    rules<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">        test<span class=\"token punctuation\">:</span> <span class=\"token regex\">/\\.css/</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">        use<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">            loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"file-loader\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">            options<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">              name<span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].css\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">{</span> loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"extract-loader\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">{</span> loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"css-loader\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">            loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"postcss-loader\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">            options<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">              ident<span class=\"token punctuation\">:</span> <span class=\"token string\">\"postcss\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">              <span class=\"token function-variable function\">plugins</span><span class=\"token punctuation\">:</span> <span class=\"token parameter\">loader</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">[</span></span><span class=\"gatsby-highlight-code-line\">                <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"cssnano\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">                  discardComments<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span> removeAll<span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">              <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span>  …\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now, in your JavaScript files, you can require stylesheets like so:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// app/assets/javascripts/application.js</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"stylesheets/application.css\"</span><span class=\"token punctuation\">)</span></span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello from application.js!\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h2>Tell Rails where to find assets from webpack-dev-server</h2>\n<p>Now if you load up your site, you're probably seeing something like:\n<code class=\"language-text\">Sprockets::Rails::Helper::AssetNotFound in Welcome#index</code></p>\n<p>Add this helper to <code class=\"language-text\">app/helpers/application_helper.rb</code>:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># app/helpers/application_helper.rb</span>\n<span class=\"token keyword\">module</span> <span class=\"token constant\">ApplicationHelper</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">webpack_asset_url</span></span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token string\">\"http://localhost:8080/<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>name<span class=\"token delimiter tag\">}</span></span>\"</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">end</span></span><span class=\"token keyword\">end</span></code></pre></div>\n<p>Then wrap the paths of any assets you're including in that helper, and don't forget the extensions:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token comment\">&lt;!-- app/views/layouts/application.html.erb --></span>\n<span class=\"token doctype\">&lt;!DOCTYPE html></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Webpacked<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n    &lt;%= csrf_meta_tags %> &lt;%= stylesheet_link_tag\n    webpack_asset_url('application.css'), media: 'all' %> &lt;%=\n<span class=\"gatsby-highlight-code-line\">    javascript_include_tag webpack_asset_url('application.js') %></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n    &lt;%= yield %>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2>Building for production</h2>\n<p>But wait, production! We need to tell Rails to serve the static assets in production:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># app/helpers/application_helper.rb</span>\n<span class=\"token keyword\">module</span> <span class=\"token constant\">ApplicationHelper</span>\n  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">webpack_asset_url</span></span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token constant\">Rails</span><span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span>production<span class=\"token operator\">?</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token string\">\"/assets/<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>name<span class=\"token delimiter tag\">}</span></span>\"</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">else</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token string\">\"http://localhost:8080/<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>name<span class=\"token delimiter tag\">}</span></span>\"</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">end</span></span>  <span class=\"token keyword\">end</span>\n<span class=\"token keyword\">end</span></code></pre></div>\n<p>You can test this by precompiling the assets and then restarting your Rails server in production mode:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">yarn</span> precompile <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token assign-left variable\">RAILS_ENV</span><span class=\"token operator\">=</span>production <span class=\"token punctuation\">\\</span>\n  <span class=\"token assign-left variable\">RAILS_SERVE_STATIC_FILES</span><span class=\"token operator\">=</span>true <span class=\"token punctuation\">\\</span>\n  <span class=\"token assign-left variable\">SECRET_KEY_BASE</span><span class=\"token operator\">=</span>hi <span class=\"token punctuation\">\\</span>\n  bin/rails server</code></pre></div>\n<h2>Fingerprinting assets</h2>\n<p>But wait, asset fingerprinting! Change the output filename for CSS and entrypoints:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  …\n  module<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    rules<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token punctuation\">{</span>\n        test<span class=\"token punctuation\">:</span> <span class=\"token regex\">/\\.css/</span><span class=\"token punctuation\">,</span>\n        use<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n          <span class=\"token punctuation\">{</span>\n            loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"file-loader\"</span><span class=\"token punctuation\">,</span>\n            options<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">              name<span class=\"token punctuation\">:</span> <span class=\"token constant\">PROD</span> <span class=\"token operator\">?</span> <span class=\"token string\">\"[name]-[hash].css\"</span> <span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].css\"</span><span class=\"token punctuation\">,</span></span>            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">{</span> loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"extract-loader\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">{</span> loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"css-loader\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">{</span>\n            loader<span class=\"token punctuation\">:</span> <span class=\"token string\">\"postcss-loader\"</span><span class=\"token punctuation\">,</span>\n            options<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n              ident<span class=\"token punctuation\">:</span> <span class=\"token string\">\"postcss\"</span><span class=\"token punctuation\">,</span>\n              <span class=\"token function-variable function\">plugins</span><span class=\"token punctuation\">:</span> <span class=\"token parameter\">loader</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">[</span>\n                <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"cssnano\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n                  discardComments<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span> removeAll<span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n              <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  output<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    chunkFilename<span class=\"token punctuation\">:</span> <span class=\"token constant\">PROD</span> <span class=\"token operator\">?</span> <span class=\"token string\">\"[name]-[contenthash].js\"</span> <span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].js\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    filename<span class=\"token punctuation\">:</span> <span class=\"token constant\">PROD</span> <span class=\"token operator\">?</span> <span class=\"token string\">\"[name]-[contenthash].js\"</span> <span class=\"token punctuation\">:</span> <span class=\"token string\">\"[name].js\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    hashDigestLength<span class=\"token punctuation\">:</span> <span class=\"token number\">32</span><span class=\"token punctuation\">,</span></span>    path<span class=\"token punctuation\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">DIR</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">public/assets/</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  …\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now we need to tell Rails about these hashes somehow. First, we'll add the webpack-manifest-plugin (when building for production) to output a JSON map of the names of chunks to their hashed names:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  …\n<span class=\"gatsby-highlight-code-line\">  plugins<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token constant\">PROD</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">new</span> <span class=\"token punctuation\">(</span><span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"webpack-manifest-plugin\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>Boolean<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></span>  …\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>If you <code class=\"language-text\">yarn precompile</code> again, you should see it output a file like this, in addition to the other chunks:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token comment\">// public/assets/manifest.json</span>\n<span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"application.css\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application-4cf6c42fe4e9a27ee5a758dcf37091f7.css\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"application.js\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application-5689a742f9b3cb6758a6b35164a98ade.js\"</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now let's update the Rails helper to get everything sorted out:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"ruby\"><pre class=\"language-ruby\"><code class=\"language-ruby\"><span class=\"token comment\"># app/helpers/application_helper.rb</span>\n<span class=\"token keyword\">module</span> <span class=\"token constant\">ApplicationHelper</span>\n  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">webpack_asset_url</span></span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token constant\">Rails</span><span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span>production<span class=\"token operator\">?</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token string\">\"/assets/<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>webpack_fingerprint_for<span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token delimiter tag\">}</span></span>\"</span></span>    <span class=\"token keyword\">else</span>\n      <span class=\"token string\">\"http://localhost:8080/<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>name<span class=\"token delimiter tag\">}</span></span>\"</span>\n    <span class=\"token keyword\">end</span>\n  <span class=\"token keyword\">end</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">webpack_fingerprint_for</span></span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token variable\">@chunk_manifest</span> <span class=\"token operator\">||</span><span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">(</span><span class=\"token builtin\">File</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token string\">'public/assets/manifest.json'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token variable\">@chunk_manifest</span><span class=\"token punctuation\">[</span>name<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">nil</span><span class=\"token operator\">?</span></span><span class=\"gatsby-highlight-code-line\">      logger<span class=\"token punctuation\">.</span>error <span class=\"token string\">\"chunk_manifest_missing name=<span class=\"token interpolation\"><span class=\"token delimiter tag\">#{</span>name<span class=\"token delimiter tag\">}</span></span>\"</span></span><span class=\"gatsby-highlight-code-line\">      logger<span class=\"token punctuation\">.</span>error <span class=\"token variable\">@chunk_manifest</span><span class=\"token punctuation\">.</span>inspect</span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">end</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token variable\">@chunk_manifest</span><span class=\"token punctuation\">[</span>name<span class=\"token punctuation\">]</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">end</span></span><span class=\"token keyword\">end</span></code></pre></div>\n<p>You might have to restart the Rails server again, but now you should see it loading the fingerprinted assets! Now wherever you run <code class=\"language-text\">rake assets:precompile</code> during your deployment process, replace it with <code class=\"language-text\">yarn precompile</code>.</p>\n<h2>Separate the webpack runtime</h2>\n<p>For better caching, it's smart to separate the webpack runtime from your application's JavaScript:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  …\n<span class=\"gatsby-highlight-code-line\">  optimization<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    runtimeChunk<span class=\"token punctuation\">:</span> <span class=\"token string\">\"single\"</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span>  …\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Then just include that <code class=\"language-text\">runtime</code> chunk before any other JavaScript:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token comment\">&lt;!-- app/views/layouts/application.html.erb --></span>\n<span class=\"token doctype\">&lt;!DOCTYPE html></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Webpacked<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n    &lt;%= csrf_meta_tags %> &lt;%= stylesheet_link_tag\n    webpack_asset_url('application.css'), media: 'all' %> &lt;%=\n    javascript_include_tag webpack_asset_url('runtime.js') %> &lt;%=\n<span class=\"gatsby-highlight-code-line\">    javascript_include_tag webpack_asset_url('application.js') %></span>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n    &lt;%= yield %>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span></code></pre></div>","timeToRead":5,"frontmatter":{"date":"2018-04-04T21:06:50.000Z","link":null,"path":"/rails-webpack-webpacker","tags":["webpack","javascript","rails"],"title":"Rails + webpack - webpacker"}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"id":"afe916b1-1136-5ffd-8533-c35514e9e4aa"}}}