webpacker-react-on-rails 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintrc.js +14 -0
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +124 -0
  5. data/.travis.yml +22 -0
  6. data/CHANGELOG.md +208 -0
  7. data/Gemfile +21 -0
  8. data/Gemfile.lock +137 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +1244 -0
  11. data/Rakefile +12 -0
  12. data/lib/install/angular.rb +18 -0
  13. data/lib/install/bin/webpack-dev-server.tt +71 -0
  14. data/lib/install/bin/webpack.tt +32 -0
  15. data/lib/install/config/.babelrc +18 -0
  16. data/lib/install/config/.postcssrc.yml +3 -0
  17. data/lib/install/config/loaders/core/assets.js +12 -0
  18. data/lib/install/config/loaders/core/babel.js +5 -0
  19. data/lib/install/config/loaders/core/coffee.js +4 -0
  20. data/lib/install/config/loaders/core/erb.js +9 -0
  21. data/lib/install/config/loaders/core/sass.js +18 -0
  22. data/lib/install/config/loaders/installers/angular.js +4 -0
  23. data/lib/install/config/loaders/installers/elm.js +20 -0
  24. data/lib/install/config/loaders/installers/react.js +5 -0
  25. data/lib/install/config/loaders/installers/vue.js +41 -0
  26. data/lib/install/config/webpack/configuration.js +45 -0
  27. data/lib/install/config/webpack/development.js +31 -0
  28. data/lib/install/config/webpack/production.js +35 -0
  29. data/lib/install/config/webpack/shared.js +53 -0
  30. data/lib/install/config/webpack/test.js +6 -0
  31. data/lib/install/config/webpacker.yml +47 -0
  32. data/lib/install/elm.rb +29 -0
  33. data/lib/install/examples/angular/hello_angular.js +7 -0
  34. data/lib/install/examples/angular/hello_angular/app/app.component.ts +9 -0
  35. data/lib/install/examples/angular/hello_angular/app/app.module.ts +16 -0
  36. data/lib/install/examples/angular/hello_angular/index.ts +6 -0
  37. data/lib/install/examples/angular/hello_angular/polyfills.ts +19 -0
  38. data/lib/install/examples/angular/tsconfig.json +19 -0
  39. data/lib/install/examples/elm/Main.elm +54 -0
  40. data/lib/install/examples/elm/hello_elm.js +11 -0
  41. data/lib/install/examples/react/.babelrc +6 -0
  42. data/lib/install/examples/react/hello_react.jsx +26 -0
  43. data/lib/install/examples/vue/app.vue +22 -0
  44. data/lib/install/examples/vue/hello_vue.js +43 -0
  45. data/lib/install/javascript/packs/application.js +10 -0
  46. data/lib/install/react.rb +31 -0
  47. data/lib/install/template.rb +42 -0
  48. data/lib/install/vue.rb +15 -0
  49. data/lib/tasks/installers.rake +22 -0
  50. data/lib/tasks/webpacker.rake +19 -0
  51. data/lib/tasks/webpacker/check_binstubs.rake +12 -0
  52. data/lib/tasks/webpacker/check_node.rake +20 -0
  53. data/lib/tasks/webpacker/check_yarn.rake +15 -0
  54. data/lib/tasks/webpacker/clobber.rake +17 -0
  55. data/lib/tasks/webpacker/compile.rake +38 -0
  56. data/lib/tasks/webpacker/install.rake +12 -0
  57. data/lib/tasks/webpacker/verify_install.rake +16 -0
  58. data/lib/tasks/webpacker/yarn_install.rake +6 -0
  59. data/lib/webpacker.rb +26 -0
  60. data/lib/webpacker/compiler.rb +59 -0
  61. data/lib/webpacker/configuration.rb +83 -0
  62. data/lib/webpacker/dev_server.rb +78 -0
  63. data/lib/webpacker/env.rb +23 -0
  64. data/lib/webpacker/file_loader.rb +47 -0
  65. data/lib/webpacker/helper.rb +69 -0
  66. data/lib/webpacker/manifest.rb +101 -0
  67. data/lib/webpacker/railtie.rb +18 -0
  68. data/lib/webpacker/version.rb +3 -0
  69. data/package.json +31 -0
  70. data/test/compiler_test.rb +25 -0
  71. data/test/configuration_test.rb +36 -0
  72. data/test/dev_server_test.rb +56 -0
  73. data/test/env_test.rb +14 -0
  74. data/test/helper_test.rb +45 -0
  75. data/test/manifest_test.rb +77 -0
  76. data/test/test_app/config/secrets.yml +5 -0
  77. data/test/test_app/public/packs/manifest.json +6 -0
  78. data/test/webpacker_test.rb +20 -0
  79. data/webpacker.gemspec +23 -0
  80. data/yarn.lock +1014 -0
  81. metadata +192 -0
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 David Heinemeier Hansson, Basecamp
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,1244 @@
1
+ # Webpacker
2
+
3
+ ![travis-ci status](https://api.travis-ci.org/rails/webpacker.svg?branch=master)
4
+ [![node.js](https://img.shields.io/badge/node-%3E%3D%206.4.0-brightgreen.svg)](https://nodejs.org/en/)
5
+ [![Gem](https://img.shields.io/gem/v/webpacker.svg)](https://github.com/rails/webpacker)
6
+
7
+ Webpacker makes it easy to use the JavaScript pre-processor and bundler
8
+ [Webpack 2.x.x+](https://webpack.js.org/)
9
+ to manage application-like JavaScript in Rails. It coexists with the asset pipeline,
10
+ as the primary purpose for Webpack is app-like JavaScript, not images, CSS, or
11
+ even JavaScript Sprinkles (that all continues to live in app/assets).
12
+
13
+ However, it is possible to use Webpacker for CSS, images and fonts assets as well,
14
+ in which case you may not even need the asset pipeline. This is mostly relevant when exclusively using component-based JavaScript frameworks.
15
+
16
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
17
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
18
+ ## Table of Contents
19
+
20
+ - [Prerequisites](#prerequisites)
21
+ - [Features](#features)
22
+ - [Installation](#installation)
23
+ - [Integrations](#integrations)
24
+ - [React](#react)
25
+ - [Angular with TypeScript](#angular-with-typescript)
26
+ - [Vue](#vue)
27
+ - [Using Rails helpers in .vue files](#using-rails-helpers-in-vue-files)
28
+ - [Elm](#elm)
29
+ - [Binstubs](#binstubs)
30
+ - [Webpack dev server](#webpack-dev-server)
31
+ - [Webpack](#webpack)
32
+ - [Configuration](#configuration)
33
+ - [Webpack](#webpack-1)
34
+ - [Loaders](#loaders)
35
+ - [Paths](#paths)
36
+ - [Resolved Paths](#resolved-paths)
37
+ - [Babel](#babel)
38
+ - [Post-Processing CSS](#post-processing-css)
39
+ - [CDN](#cdn)
40
+ - [HTTPS in development](#https-in-development)
41
+ - [Hot module replacement](#hot-module-replacement)
42
+ - [Linking Styles, Images and Fonts](#linking-styles-images-and-fonts)
43
+ - [Within your JS app](#within-your-js-app)
44
+ - [Inside views](#inside-views)
45
+ - [From node modules folder](#from-node-modules-folder)
46
+ - [How-tos](#how-tos)
47
+ - [App structure](#app-structure)
48
+ - [Namespacing](#namespacing)
49
+ - [Pass data from view](#pass-data-from-view)
50
+ - [React](#react-1)
51
+ - [Vue](#vue-1)
52
+ - [Add common chunks](#add-common-chunks)
53
+ - [Module import() vs require()](#module-import-vs-require)
54
+ - [Add a new npm module](#add-a-new-npm-module)
55
+ - [Add bootstrap](#add-bootstrap)
56
+ - [Use Typescript with React](#use-typescript-with-react)
57
+ - [Use HTML templates with Typescript and Angular](#use-html-templates-with-typescript-and-angular)
58
+ - [CSS modules](#css-modules)
59
+ - [CSS-Next](#css-next)
60
+ - [Ignoring swap files](#ignoring-swap-files)
61
+ - [Link sprocket assets](#link-sprocket-assets)
62
+ - [Using helpers](#using-helpers)
63
+ - [Using babel module resolver](#using-babel-module-resolver)
64
+ - [Extending](#extending)
65
+ - [Deployment](#deployment)
66
+ - [Heroku](#heroku)
67
+ - [Testing](#testing)
68
+ - [Lazy compilation](#lazy-compilation)
69
+ - [Caching](#caching)
70
+ - [Troubleshooting](#troubleshooting)
71
+ - [ENOENT: no such file or directory - node-sass](#enoent-no-such-file-or-directory---node-sass)
72
+ - [Can't find hello_react.js in manifest.json](#cant-find-hello_reactjs-in-manifestjson)
73
+ - [Error: listen EADDRINUSE 0.0.0.0:8080](#error-listen-eaddrinuse-00008080)
74
+ - [throw er; // Unhandled 'error' event](#throw-er--unhandled-error-event)
75
+ - [webpack or webpack-dev-server not found](#webpack-or-webpack-dev-server-not-found)
76
+ - [Running Webpack on Windows](#running-webpack-on-windows)
77
+ - [Wishlist](#wishlist)
78
+ - [License](#license)
79
+
80
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
81
+
82
+
83
+ ## Prerequisites
84
+
85
+ * Ruby 2.2+
86
+ * Rails 4.2+
87
+ * Node.js 6.4.0+
88
+ * Yarn 0.20.1+
89
+
90
+
91
+ ## Features
92
+
93
+ * [Webpack 2](https://webpack.js.org/)
94
+ * ES6 with [babel](https://babeljs.io/)
95
+ * Automatic code splitting using multiple entry points
96
+ * Stylesheets - SASS and CSS
97
+ * Images and fonts
98
+ * PostCSS - Auto-Prefixer
99
+ * Asset compression, source-maps, and minification
100
+ * CDN support
101
+ * React, Angular, Elm and Vue support out-of-the-box
102
+ * Rails view helpers
103
+ * Extensible and configurable
104
+
105
+
106
+ ## Installation
107
+
108
+ You can either add Webpacker during setup of a new Rails 5.1+ application
109
+ using new `--webpack` option:
110
+
111
+ ```bash
112
+ # Available Rails 5.1+
113
+ rails new myapp --webpack
114
+ ```
115
+
116
+ Or add it to your `Gemfile`, run bundle and `./bin/rails webpacker:install` or `bundle exec rake webpacker:install` (on rails version < 5.0):
117
+
118
+ ```ruby
119
+ # Gemfile
120
+ gem 'webpacker', '~> 2.0'
121
+
122
+ # OR if you prefer to use master
123
+ gem 'webpacker', git: 'https://github.com/rails/webpacker.git'
124
+ ```
125
+
126
+ **Note:** Use `rake` instead of `rails` if you are using webpacker
127
+ with rails version < 5.0
128
+
129
+
130
+ ## Integrations
131
+
132
+ Webpacker by default ships with basic out-of-the-box integration
133
+ for React, Angular, Vue and Elm. You can see a list of available
134
+ commands/tasks by running:
135
+
136
+ ```bash
137
+ # Within rails app
138
+ ./bin/rails webpacker
139
+ ```
140
+
141
+ or in rails version < 5.0
142
+
143
+ ```bash
144
+ # Within rails app
145
+ ./bin/rake webpacker
146
+ ```
147
+
148
+
149
+ ### React
150
+
151
+ To use Webpacker with [React](https://facebook.github.io/react/), create a
152
+ new Rails 5.1+ app using `--webpack=react` option:
153
+
154
+ ```bash
155
+ # Rails 5.1+
156
+ rails new myapp --webpack=react
157
+ ```
158
+
159
+ (or run `./bin/rails webpacker:install:react` in a existing Rails app already
160
+ setup with webpacker).
161
+
162
+ The installer will add all relevant dependencies using yarn, any changes
163
+ to the configuration files and an example React component to your
164
+ project in `app/javascript/packs` so that you can experiment with React right away.
165
+
166
+
167
+ ### Angular with TypeScript
168
+
169
+ To use Webpacker with [Angular](https://angularjs.org/), create a
170
+ new Rails 5.1+ app using `--webpack=angular` option:
171
+
172
+ ```bash
173
+ # Rails 5.1+
174
+ rails new myapp --webpack=angular
175
+ ```
176
+
177
+ (or run `./bin/rails webpacker:install:angular` on a Rails app already
178
+ setup with webpacker).
179
+
180
+ The installer will add TypeScript and Angular core libraries using yarn plus
181
+ any changes to the configuration files. An example component is written in
182
+ TypeScript will also be added to your project in `app/javascript` so that
183
+ you can experiment with Angular right away.
184
+
185
+
186
+ ### Vue
187
+
188
+ To use Webpacker with [Vue](https://vuejs.org/), create a
189
+ new Rails 5.1+ app using `--webpack=vue` option:
190
+
191
+ ```bash
192
+ # Rails 5.1+
193
+ rails new myapp --webpack=vue
194
+ ```
195
+ (or run `./bin/rails webpacker:install:vue` on a Rails app already setup with webpacker).
196
+
197
+ The installer will add Vue and required libraries using yarn plus
198
+ any changes to the configuration files. An example component will
199
+ also be added to your project in `app/javascript` so that you can
200
+ experiment Vue right away.
201
+
202
+ #### Using Rails helpers in .vue files
203
+
204
+ Rails helpers cannot be used in `.vue` files by default. To enable them, change
205
+ the extension to `.vue.erb` and additionally amend the `test` in
206
+ `config/webpack/loaders/vue.js` to also include `.vue.erb` files:
207
+
208
+ ```js
209
+ # config/webpack/loaders/vue.js
210
+
211
+ module.exports = {
212
+ test: /\.vue(\.erb)?$/,
213
+ ...
214
+ }
215
+ ```
216
+
217
+ ### Elm
218
+
219
+ To use Webpacker with [Elm](http://elm-lang.org), create a
220
+ new Rails 5.1+ app using `--webpack=elm` option:
221
+
222
+ ```
223
+ # Rails 5.1+
224
+ rails new myapp --webpack=elm
225
+ ```
226
+
227
+ (or run `./bin/rails webpacker:install:elm` on a Rails app already setup with webpacker).
228
+
229
+ The Elm library and core packages will be added via Yarn and Elm itself.
230
+ An example `Main.elm` app will also be added to your project in `app/javascript`
231
+ so that you can experiment with Elm right away.
232
+
233
+
234
+ ## Binstubs
235
+
236
+ Webpacker ships with two binstubs: `./bin/webpack` and `./bin/webpack-dev-server`.
237
+ Both are thin wrappers around the standard `webpack.js` and `webpack-dev-server.js`
238
+ executable to ensure that the right configuration file and environment variables
239
+ are loaded depending on your environment.
240
+
241
+
242
+ ### Webpack dev server
243
+
244
+ In development, you'll need to run `./bin/webpack-dev-server` in a separate terminal
245
+ from `./bin/rails server` to have your `app/javascript/packs/*.js` files compiled
246
+ as you make changes.
247
+
248
+ `./bin/webpack-dev-server` launches the [Webpack Dev Server](https://webpack.js.org/configuration/dev-server/), which serves your pack files
249
+ on `http://localhost:8080/` by default and supports live code reloading in the development environment. You will need to install additional plugins for Webpack if you want
250
+ features like [Hot Module Replacement](https://webpack.js.org/guides/hot-module-replacement/).
251
+
252
+ If you'd rather not have to run the two processes separately by hand, you can use [Foreman](https://ddollar.github.io/foreman):
253
+
254
+ ```bash
255
+ gem install foreman
256
+ ```
257
+
258
+ ```yml
259
+ # Procfile
260
+ web: bundle exec rails s
261
+ webpacker: ./bin/webpack-dev-server
262
+ ```
263
+
264
+ ```bash
265
+ foreman start
266
+ ```
267
+
268
+ By default, `webpack-dev-server` listens on `0.0.0.0` that means listening
269
+ on all IP addresses available on your system: LAN IP address, localhost, 127.0.0.1 etc. However, we use `localhost` as default hostname for serving assets in browser
270
+ and if you want to change that, for example on cloud9 you can do so
271
+ by changing host set in `config/webpacker.yml`.
272
+
273
+ ```bash
274
+ dev_server:
275
+ host: example.com
276
+ ```
277
+
278
+ You can also pass CLI options supported by [webpack-dev-server](https://webpack.js.org/configuration/dev-server/). Please note that inline options will always take
279
+ precedence over the ones already set in the configuration file.
280
+
281
+ ```bash
282
+ ./bin/webpack-dev-server --host example.com --inline true --hot false
283
+ ```
284
+
285
+ ### Webpack
286
+
287
+ We recommend using `webpack-dev-server` during development for a better experience.
288
+ However, if you don't want that for some reason you can always use `webpack` binstub with
289
+ watch option, which uses webpack Command Line Interface (CLI). This will use `public_output_path` from `config/webpacker.yml`
290
+ directory to serve your packs using configured rails server.
291
+
292
+ You can pass cli options available with [Webpack](https://webpack.js.org/api/cli/):
293
+
294
+ ```bash
295
+ ./bin/webpack --watch --progress --colors
296
+ ```
297
+
298
+
299
+ ## Configuration
300
+
301
+
302
+ ### Webpack
303
+
304
+ Webpacker gives you a default set of configuration files for test, development and
305
+ production environments. They all live together with the shared
306
+ points in `config/webpack/*.js`.
307
+
308
+ ![screen shot 2017-05-23 at 19 56 18](https://cloud.githubusercontent.com/assets/771039/26371229/0983add2-3ff2-11e7-9dc3-d9c2c1094032.png)
309
+
310
+ By default, you shouldn't have to make any changes to `config/webpack/*.js`
311
+ files since it's all standard production-ready configuration. However,
312
+ if you do need to customize or add a new loader, this is where you would go.
313
+
314
+
315
+ ### Loaders
316
+
317
+ Webpack enables the use of loaders to preprocess files. This allows you to
318
+ bundle any static resource way beyond JavaScript. All base loaders
319
+ that ships with webpacker are located inside `config/webpack/loaders`.
320
+
321
+ If you want to add a new loader, for example, to process `json` files via webpack:
322
+
323
+ ```
324
+ yarn add json-loader
325
+ ```
326
+
327
+ And create a `json.js` file inside `loaders` directory:
328
+
329
+ ```js
330
+ module.exports = {
331
+ test: /\.json$/,
332
+ use: 'json-loader'
333
+ }
334
+ ```
335
+
336
+ Finally add `.json` to the list of extensions in `config/webpacker.yml`. Now if you `import()` any `.json` files inside your javascript
337
+ they will be processed using `json-loader`. Voila!
338
+
339
+
340
+ ### Paths
341
+
342
+ By default, webpacker ships with simple conventions for where the javascript
343
+ app files and compiled webpack bundles will go in your rails app,
344
+ but all these options are configurable from `config/webpacker.yml` file.
345
+
346
+ The configuration for what Webpack is supposed to compile by default rests
347
+ on the convention that every file in `app/javascript/packs/*`**(default)**
348
+ or whatever path you set for `source_entry_path` in the `webpacker.yml` configuration
349
+ is turned into their own output files (or entry points, as Webpack calls it).
350
+
351
+ Suppose you want to change the source directory from `app/javascript`
352
+ to `frontend` and output to `assets/packs` this is how you would do it:
353
+
354
+ ```yml
355
+ # config/webpacker.yml
356
+ source_path: frontend
357
+ source_entry_path: packs
358
+ public_output_path: assets/packs # outputs to => public/assets/packs
359
+ ```
360
+
361
+ Similary you can also control and configure `webpack-dev-server` settings from `config/webpacker.yml` file:
362
+
363
+ ```yml
364
+ # config/webpacker.yml
365
+ development:
366
+ dev_server:
367
+ host: 0.0.0.0
368
+ port: 8080
369
+ https: false
370
+ hot: false
371
+ ```
372
+
373
+ If you have hot turned to `true`, then the `stylesheet_pack_tag` generates no output, as you will want
374
+ to configure your styles to be inlined in your JavaScript for hot reloading. During production and testing, the
375
+ `stylesheet_pack_tag` will create the appropriate HTML tags.
376
+
377
+
378
+ #### Resolved Paths
379
+
380
+ If you are adding webpacker to an existing app that has most of the assets inside
381
+ `app/assets` or inside an engine and you want to share that
382
+ with webpack modules then you can use `resolved_paths`
383
+ option available in `config/webpacker.yml`, which lets you
384
+ add additional paths webpack should lookup when resolving modules:
385
+
386
+ ```yml
387
+ resolved_paths: ['app/assets']
388
+ ```
389
+
390
+ You can then import them inside your modules like so:
391
+
392
+ ```js
393
+ // Note it's relative to parent directory i.e. app/assets
394
+ import 'stylesheets/main'
395
+ import 'images/rails.png'
396
+ ```
397
+
398
+ **Note:** Please be careful when adding paths here otherwise it
399
+ will make the compilation slow, consider adding specific paths instead of
400
+ whole parent directory if you just need to reference one or two modules
401
+
402
+
403
+ ### Babel
404
+
405
+ Webpacker ships with [babel](https://babeljs.io/) - a JavaScript compiler so
406
+ you can use next generation JavaScript, today. The Webpacker installer sets up a
407
+ standard `.babelrc` file in your app root, which will work great in most cases
408
+ because of [babel-env-preset](https://github.com/babel/babel-preset-env).
409
+
410
+ Following ES6/7 features are supported out of the box:
411
+
412
+ * Async/await.
413
+ * Object Rest/Spread Properties.
414
+ * Exponentiation Operator.
415
+ * Dynamic import() - useful for route level code-splitting
416
+ * Class Fields and Static Properties.
417
+
418
+ We have also included [babel polyfill](https://babeljs.io/docs/usage/polyfill/)
419
+ that includes a custom regenerator runtime and core-js.
420
+
421
+
422
+ ### Post-Processing CSS
423
+
424
+ Webpacker out-of-the-box provides CSS post-processing using
425
+ [postcss-loader](https://github.com/postcss/postcss-loader)
426
+ and the installer sets up a standard `.postcssrc.yml`
427
+ file in your app root with standard plugins.
428
+
429
+ ```yml
430
+ plugins:
431
+ postcss-smart-import: {}
432
+ postcss-cssnext: {}
433
+ ```
434
+
435
+
436
+ ### CDN
437
+
438
+ Webpacker out-of-the-box provides CDN support using your Rails app `config.action_controller.asset_host` setting. If you already have [CDN](http://guides.rubyonrails.org/asset_pipeline.html#cdns) added in your rails app
439
+ you don't need to do anything extra for webpacker, it just works.
440
+
441
+ ### HTTPS in development
442
+
443
+ You may require the `webpack-dev-server` to serve views over HTTPS in development.
444
+ To do this, set the `https` option for `webpack-dev-server`
445
+ to `true` in `config/webpacker.yml`, then start the dev server as usual
446
+ with `./bin/webpack-dev-server`.
447
+
448
+ Please note that the `webpack-dev-server` will use a self-signed certificate,
449
+ so your web browser will display a warning upon accessing the page.
450
+
451
+
452
+ ### Hot module replacement
453
+
454
+ Webpacker out-of-the-box doesn't ship with HMR just yet. You will need to
455
+ install additional plugins for Webpack if you want to add HMR support.
456
+
457
+ You can checkout these links on this subject:
458
+
459
+ - https://webpack.js.org/configuration/dev-server/#devserver-hot
460
+ - https://webpack.js.org/guides/hmr-react/
461
+
462
+
463
+ ## Linking Styles, Images and Fonts
464
+
465
+ Static assets like images, fonts and stylesheets support is enabled out-of-box
466
+ and you can link them into your javascript app code and have them
467
+ compiled automatically.
468
+
469
+
470
+ ### Within your JS app
471
+
472
+ ```sass
473
+ // app/javascript/hello_react/styles/hello-react.sass
474
+
475
+ .hello-react
476
+ padding: 20px
477
+ font-size: 12px
478
+ ```
479
+
480
+ ```js
481
+ // React component example
482
+ // app/javascripts/packs/hello_react.jsx
483
+
484
+ import React from 'react'
485
+ import helloIcon from '../hello_react/images/icon.png'
486
+ import '../hello_react/styles/hello-react'
487
+
488
+ const Hello = props => (
489
+ <div className="hello-react">
490
+ <img src={helloIcon} alt="hello-icon" />
491
+ <p>Hello {props.name}!</p>
492
+ </div>
493
+ )
494
+ ```
495
+
496
+
497
+ ### Inside views
498
+
499
+ Under the hood webpack uses
500
+ [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) plugin to extract all the referenced styles within your app and compile it into
501
+ a separate `[pack_name].css` bundle so that in your view you can use the
502
+ `stylesheet_pack_tag` helper.
503
+
504
+ ```erb
505
+ <%= stylesheet_pack_tag 'hello_react' %>
506
+ ```
507
+
508
+ You can also link js/images/styles used within your js app in views using
509
+ `asset_pack_path` helper. This helper is useful in cases where you just want to
510
+ create a `<link rel="prefetch">` or `<img />` for an asset.
511
+
512
+ ```erb
513
+ <%= asset_pack_path 'hello_react.css' %>
514
+ <%# => "/packs/hello_react.css" %>
515
+
516
+ <img src="<%= asset_pack_path 'calendar.png' %>" />
517
+ <% # => <img src="/packs/calendar.png" /> %>
518
+ ```
519
+
520
+
521
+ ### From node modules folder
522
+
523
+ You can also import styles from `node_modules` using the following syntax.
524
+ Please note that your styles will always be extracted into `[pack_name].css`:
525
+
526
+ ```sass
527
+ // app/javascript/app-styles.sass
528
+ // ~ to tell webpack that this is not a relative import:
529
+
530
+ @import '~@material/animation/mdc-animation'
531
+ @import '~bootstrap/dist/css/bootstrap'
532
+ ```
533
+
534
+ ```js
535
+ // Your main app pack
536
+ // app/javascript/packs/app.js
537
+
538
+ import '../app-styles'
539
+ ```
540
+
541
+ ```erb
542
+ <%# In your views %>
543
+
544
+ <%= javascript_pack_tag 'app' %>
545
+ <%= stylesheet_pack_tag 'app' %>
546
+ ```
547
+
548
+
549
+ ## How-tos
550
+
551
+
552
+ ### App structure
553
+
554
+ Let's say you're building a calendar app. Your JS app structure could look like this:
555
+
556
+ ```js
557
+ // app/javascript/packs/calendar.js
558
+
559
+ import 'calendar'
560
+ ```
561
+
562
+ ```
563
+ app/javascript/calendar/index.js // gets loaded by import 'calendar'
564
+ app/javascript/calendar/components/grid.jsx
565
+ app/javascript/calendar/styles/grid.sass
566
+ app/javascript/calendar/models/month.js
567
+ ```
568
+
569
+ ```erb
570
+ <%# app/views/layouts/application.html.erb %>
571
+
572
+ <%= javascript_pack_tag 'calendar' %>
573
+ <%= stylesheet_pack_tag 'calendar' %>
574
+ ```
575
+
576
+ But it could also look a million other ways.
577
+
578
+
579
+ #### Namespacing
580
+
581
+ You can also namespace your packs using directories similar to a Rails app.
582
+
583
+ ```
584
+ app/javascript/packs/admin/orders.js
585
+ app/javascript/packs/shop/orders.js
586
+ ```
587
+
588
+ and reference them in your views like this:
589
+
590
+ ```erb
591
+ <%# app/views/admin/orders/index.html.erb %>
592
+
593
+ <%= javascript_pack_tag 'admin/orders' %>
594
+ ```
595
+
596
+ and
597
+
598
+ ```erb
599
+ <%# app/views/shop/orders/index.html.erb %>
600
+
601
+ <%= javascript_pack_tag 'shop/orders' %>
602
+ ```
603
+
604
+
605
+ ### Pass data from view
606
+
607
+
608
+ #### React
609
+
610
+ The most widely used React integration is [shakacode/react_on_rails](https://github.com/shakacode/react_on_rails) which includes support for server rendering, redux and react-router.
611
+
612
+ Other alternatives include [react-rails](https://github.com/reactjs/react-rails) and
613
+ [webpacker-react](https://github.com/renchap/webpacker-react) for more advanced react integration.
614
+
615
+ If you're not concerned with view helpers to pass props or server rendering, can do it yourself:
616
+
617
+ ```erb
618
+ <%# views/layouts/application.html.erb %>
619
+
620
+ <%= content_tag :div,
621
+ id: "hello-react",
622
+ data: {
623
+ message: 'Hello!',
624
+ name: 'David'
625
+ }.to_json do %>
626
+ <% end %>
627
+ ```
628
+
629
+ ```js
630
+ // app/javascript/packs/hello_react.js
631
+
632
+ const Hello = props => (
633
+ <div className='react-app-wrapper'>
634
+ <img src={clockIcon} alt="clock" />
635
+ <h5 className='hello-react'>
636
+ {props.message} {props.name}!
637
+ </h5>
638
+ </div>
639
+ )
640
+
641
+ // Render component with data
642
+ document.addEventListener('DOMContentLoaded', () => {
643
+ const node = document.getElementById('hello-react')
644
+ const data = JSON.parse(node.getAttribute('data'))
645
+
646
+ ReactDOM.render(<Hello {...data} />, node)
647
+ })
648
+ ```
649
+
650
+
651
+ #### Vue
652
+
653
+ ```erb
654
+ <%= content_tag :div,
655
+ id: "hello-vue",
656
+ data: {
657
+ message: "Hello!",
658
+ name: "David"
659
+ }.to_json do %>
660
+ <% end %>
661
+ ```
662
+
663
+ ```html
664
+ <div id="hello-vue" data-name="David" data-message="Hello!"></div>
665
+ ```
666
+
667
+ ```js
668
+ // Render component with props
669
+
670
+ document.addEventListener('DOMContentLoaded', () => {
671
+ const node = document.getElementById('hello-vue')
672
+ const props = JSON.parse(node.getAttribute('data'))
673
+
674
+ new Vue({
675
+ render: h => h(App, { props })
676
+ }).$mount('#hello-vue');
677
+ })
678
+ ```
679
+
680
+ You can follow same steps for Angular too.
681
+
682
+
683
+ ### Add common chunks
684
+
685
+ The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in the cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from the cache, rather than being forced to load a larger bundle whenever a new page is visited.
686
+
687
+ Create a `app-config.js` file inside `config/webpack` and in that file add:
688
+
689
+ ```js
690
+ module.exports = {
691
+ plugins: [
692
+ // Creates a common vendor.js with all shared modules
693
+ new webpack.optimize.CommonsChunkPlugin({
694
+ name: 'vendor',
695
+ minChunks: (module) => {
696
+ // this assumes your vendor imports exist in the node_modules directory
697
+ return module.context && module.context.indexOf('node_modules') !== -1;
698
+ }
699
+ }),
700
+ // Webpack code chunk - manifest.js
701
+ new webpack.optimize.CommonsChunkPlugin({
702
+ name: 'manifest',
703
+ minChunks: Infinity
704
+ })
705
+ ]
706
+ }
707
+ ```
708
+
709
+ You can add this in `shared.js` too but we are doing this to ensure smoother upgrades.
710
+
711
+ ```js
712
+ // config/webpack/shared.js
713
+ // .... rest of the config
714
+
715
+ const appConfig = require('./app-config.js')
716
+
717
+ plugins: appConfig.plugins.concat([
718
+
719
+ // ...existing plugins
720
+
721
+ ])
722
+ ```
723
+
724
+ Now, add these files to your `layouts/application.html.erb`:
725
+
726
+ ```erb
727
+ <%# Head %>
728
+
729
+ <%= javascript_pack_tag 'manifest' %>
730
+ <%= javascript_pack_tag 'vendor' %>
731
+
732
+ <%# If importing any styles from node_modules in your JS app %>
733
+
734
+ <%= stylesheet_pack_tag 'vendor' %>
735
+ ```
736
+
737
+
738
+ ### Module import() vs require()
739
+
740
+ While you are free to use `require()` and `module.exports`, we encourage you
741
+ to use `import` and `export` instead since it reads and looks much better.
742
+
743
+ ```js
744
+ import Button from 'react-bootstrap/lib/Button'
745
+
746
+ // or
747
+ import { Button } from 'react-bootstrap'
748
+
749
+ class Foo {
750
+ // code...
751
+ }
752
+
753
+ export default Foo
754
+ import Foo from './foo'
755
+ ```
756
+
757
+ You can also use named export and import
758
+
759
+ ```js
760
+ export const foo = () => console.log('hello world')
761
+ import { foo } from './foo'
762
+ ```
763
+
764
+
765
+ ### Add a new npm module
766
+
767
+ To add any new JS module you can use `yarn`:
768
+
769
+ ```bash
770
+ yarn add bootstrap material-ui
771
+ ```
772
+
773
+
774
+ ### Add bootstrap
775
+
776
+ You can use yarn to add bootstrap or any other modules available on npm:
777
+
778
+ ```bash
779
+ yarn add bootstrap
780
+ ```
781
+
782
+ Import Bootstrap and theme(optional) CSS in your app/javascript/packs/app.js file:
783
+
784
+ ```js
785
+ import 'bootstrap/dist/css/bootstrap'
786
+ import 'bootstrap/dist/css/bootstrap-theme'
787
+ ```
788
+
789
+ Or in your app/javascript/app.sass file:
790
+
791
+ ```sass
792
+ // ~ to tell that this is not a relative import
793
+
794
+ @import '~bootstrap/dist/css/bootstrap'
795
+ @import '~bootstrap/dist/css/bootstrap-theme'
796
+ ```
797
+
798
+
799
+ ### Use Typescript with React
800
+
801
+ 1. Setup react using webpacker [react installer](#react). Then add required depedencies
802
+ for using typescript with React:
803
+
804
+ ```bash
805
+ yarn add ts-loader typescript @types/react @types/react-dom
806
+
807
+ # You don't need this with typescript
808
+ yarn remove prop-types
809
+ ```
810
+
811
+ 2. Add a `tsconfig.json` to project root:
812
+
813
+ ``` json
814
+ {
815
+ "compilerOptions": {
816
+ "declaration": false,
817
+ "emitDecoratorMetadata": true,
818
+ "experimentalDecorators": true,
819
+ "lib": ["es6", "dom"],
820
+ "module": "es6",
821
+ "moduleResolution": "node",
822
+ "sourceMap": true,
823
+ "jsx": "react",
824
+ "target": "es5"
825
+ },
826
+ "exclude": [
827
+ "**/*.spec.ts",
828
+ "node_modules",
829
+ "public"
830
+ ],
831
+ "compileOnSave": false
832
+ }
833
+ ```
834
+
835
+ 3. Add a new loader `config/webpack/loaders/typescript.js`:
836
+
837
+ ``` js
838
+ module.exports = {
839
+ test: /.(ts|tsx)$/,
840
+ loader: 'ts-loader'
841
+ }
842
+ ```
843
+
844
+ 4. Finally add `.tsx` to the list of extensions in `config/webpacker.yml`
845
+ and rename your generated `hello_react.js` using react installer
846
+ to `hello_react.tsx` and make it valid typescript and now you can use
847
+ typescript, JSX with React.
848
+
849
+
850
+ ### Use HTML templates with Typescript and Angular
851
+
852
+ After you have installed angular using [angular installer](#angular-with-typescript)
853
+ you would need to follow these steps to add HTML templates support:
854
+
855
+ 1. Use `yarn` to add html-loader
856
+
857
+ ```bash
858
+ yarn add html-loader
859
+ ```
860
+
861
+ 2. Add html-loader to `config/webpacker/loaders/html.js`
862
+
863
+ ```js
864
+ module.exports = {
865
+ test: /\.html$/,
866
+ use: [{
867
+ loader: 'html-loader',
868
+ options: {
869
+ minimize: true,
870
+ removeAttributeQuotes: false,
871
+ caseSensitive: true,
872
+ customAttrSurround: [ [/#/, /(?:)/], [/\*/, /(?:)/], [/\[?\(?/, /(?:)/] ],
873
+ customAttrAssign: [ /\)?\]?=/ ]
874
+ }
875
+ }]
876
+ }
877
+ ```
878
+
879
+ 3. Add `.html` to `config/webpacker.yml`
880
+
881
+ ```yml
882
+ extensions:
883
+ - .elm
884
+ - .coffee
885
+ - .html
886
+ ```
887
+
888
+ 4. Setup a custom `d.ts` definition
889
+
890
+ ```ts
891
+ // app/javascript/hello_angular/html.d.ts
892
+
893
+ declare module "*.html" {
894
+ const content: string
895
+ export default content
896
+ }
897
+ ```
898
+
899
+ 5. Add a template.html file relative to `app.component.ts`
900
+
901
+ ```html
902
+ <h1>Hello {{name}}</h1>
903
+ ```
904
+
905
+ 6. Import template into `app.component.ts`
906
+
907
+ ```ts
908
+ import { Component } from '@angular/core'
909
+ import templateString from './template.html'
910
+
911
+ @Component({
912
+ selector: 'hello-angular',
913
+ template: templateString
914
+ })
915
+
916
+ export class AppComponent {
917
+ name = 'Angular!'
918
+ }
919
+ ```
920
+
921
+ That's all. Voila!
922
+
923
+
924
+ ### CSS modules
925
+
926
+ To enable CSS modules, you would need to update `config/webpack/loaders/sass.js`
927
+ file, particularly `css-loader`:
928
+
929
+ ```js
930
+ // Add css-modules
931
+
932
+ {
933
+ loader: 'css-loader',
934
+ options: {
935
+ minimize: env.NODE_ENV === 'production',
936
+ modules: true,
937
+ localIdentName: '[path][name]__[local]--[hash:base64:5]'
938
+ }
939
+ }
940
+ ```
941
+
942
+ That's all. Now, you can use CSS modules within your JS app:
943
+
944
+ ```js
945
+ import React from 'react'
946
+ import styles from './styles'
947
+
948
+ const Hello = props => (
949
+ <div className={styles.wrapper}>
950
+ <img src={clockIcon} alt="clock" className={styles.img} />
951
+ <h5 className={styles.name}>
952
+ {props.message} {props.name}!
953
+ </h5>
954
+ </div>
955
+ )
956
+ ```
957
+
958
+
959
+ ### CSS-Next
960
+
961
+ [css-next](http://cssnext.io/) is supported out-of-box in Webpacker allowing the use of
962
+ latest CSS features, today.
963
+
964
+
965
+ ### Ignoring swap files
966
+
967
+ If you are using vim or emacs and want to ignore certain files you can add `ignore-loader`:
968
+
969
+ ```
970
+ yarn add ignore-loader
971
+ ```
972
+
973
+ and create a new loader file inside `config/webpack/loaders`:
974
+
975
+ ```js
976
+ // config/webpack/loaders/ignores.js
977
+ // ignores vue~ swap files
978
+
979
+ module.exports = {
980
+ test: /.vue~$/,
981
+ loader: 'ignore-loader'
982
+ }
983
+ ```
984
+
985
+ And now all files with `.vue~` will be ignored by the webpack compiler.
986
+
987
+
988
+ ### Link sprocket assets
989
+
990
+
991
+ #### Using helpers
992
+
993
+ It's possible to link to assets that have been precompiled by sprockets. Add the `.erb` extension to your javascript file, then you can use Sprockets' asset helpers:
994
+
995
+ ```erb
996
+ <%# app/javascript/my_pack/example.js.erb %>
997
+
998
+ <% helpers = ActionController::Base.helpers %>
999
+ var railsImagePath = "<%= helpers.image_path('rails.png') %>"
1000
+ ```
1001
+
1002
+ This is enabled by the `rails-erb-loader` loader rule in `config/webpack/loaders/erb.js`.
1003
+
1004
+
1005
+ #### Using babel module resolver
1006
+
1007
+ You can also use [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver) to reference assets directly from `app/assets/**`
1008
+
1009
+ ```bash
1010
+ yarn add babel-plugin-module-resolver
1011
+ ```
1012
+
1013
+ Specify the plugin in your `.babelrc` with the custom root or alias. Here's an example:
1014
+
1015
+ ```json
1016
+ {
1017
+ "plugins": [
1018
+ ["module-resolver", {
1019
+ "root": ["./app"],
1020
+ "alias": {
1021
+ "assets": "./assets"
1022
+ }
1023
+ }]
1024
+ ]
1025
+ }
1026
+ ```
1027
+
1028
+ And then within your javascript app code:
1029
+
1030
+ ```js
1031
+ // Note: we don't have do any ../../ jazz
1032
+
1033
+ import FooImage from 'assets/images/foo-image.png'
1034
+ import 'assets/stylesheets/bar'
1035
+ ```
1036
+
1037
+ ## Extending
1038
+
1039
+ We suggest you don't directly overwrite the provided configuration files
1040
+ and extend instead for smoother upgrades. Here is one way to do it:
1041
+
1042
+ Create a `app-config.js` file inside `config/webpack`, and in that add:
1043
+
1044
+ ```js
1045
+ module.exports = {
1046
+ production: {
1047
+ plugins: [
1048
+ // ... Add plugins
1049
+ ]
1050
+ },
1051
+
1052
+ development: {
1053
+ output: {
1054
+ // ... Custom output path
1055
+ }
1056
+ }
1057
+ }
1058
+ ```
1059
+
1060
+ ```js
1061
+ // config/webpack/production.js
1062
+
1063
+ const { plugins } = require('./app-config.js')
1064
+
1065
+ plugins: appConfig.plugins.concat([
1066
+
1067
+ // ...existing plugins
1068
+
1069
+ ])
1070
+ ```
1071
+
1072
+ But this could be done million other ways.
1073
+
1074
+
1075
+ ## Deployment
1076
+
1077
+ Webpacker hooks up a new `webpacker:compile` task to `assets:precompile`, which gets run whenever you run `assets:precompile`. If you are not using sprockets you
1078
+ can manually trigger `bundle exec rails webpacker:compile` during your app deploy.
1079
+
1080
+ The `javascript_pack_tag` and `stylesheet_pack_tag` helper method will automatically insert the correct HTML tag for compiled pack. Just like the asset pipeline does it.
1081
+
1082
+ By default the output will look like this in different environments:
1083
+
1084
+ ```html
1085
+ <!-- In development mode with webpack-dev-server -->
1086
+ <script src="http://localhost:8080/calendar.js"></script>
1087
+ <link rel="stylesheet" media="screen" href="http://localhost:8080/calendar.css">
1088
+ <!-- In development mode -->
1089
+ <script src="/packs/calendar.js"></script>
1090
+ <link rel="stylesheet" media="screen" href="/packs/calendar.css">
1091
+ <!-- In production mode -->
1092
+ <script src="/packs/calendar-0bd141f6d9360cf4a7f5.js"></script>
1093
+ <link rel="stylesheet" media="screen" href="/packs/calendar-dc02976b5f94b507e3b6.css">
1094
+ ```
1095
+
1096
+
1097
+ ### Heroku
1098
+
1099
+ Heroku installs yarn and node by default if you deploy a rails app with
1100
+ Webpacker so all you would need to do:
1101
+
1102
+ ```bash
1103
+ heroku create shiny-webpacker-app
1104
+ heroku addons:create heroku-postgresql:hobby-dev
1105
+ git push heroku master
1106
+ ```
1107
+
1108
+
1109
+ ## Testing
1110
+
1111
+ ### Lazy compilation
1112
+
1113
+ Webpacker lazily compiles assets in test env so you can write your tests without any extra
1114
+ setup and everything will just work out of the box.
1115
+
1116
+ Note, [React on Rails] users should set configuration value `compile` to false, as React on Rails
1117
+ handle compilation for test and production environments.
1118
+
1119
+ Here is a sample system test case with hello_react example component:
1120
+
1121
+ ```js
1122
+ // Example react component
1123
+
1124
+ import React from 'react'
1125
+ import ReactDOM from 'react-dom'
1126
+ import PropTypes from 'prop-types'
1127
+
1128
+ const Hello = props => (
1129
+ <div>Hello David</div>
1130
+ )
1131
+
1132
+ document.addEventListener('DOMContentLoaded', () => {
1133
+ ReactDOM.render(
1134
+ <Hello />,
1135
+ document.body.appendChild(document.createElement('div')),
1136
+ )
1137
+ })
1138
+ ```
1139
+
1140
+ ```erb
1141
+ <%# views/pages/home.html.erb %>
1142
+
1143
+ <%= javascript_pack_tag "hello_react" %>
1144
+ ```
1145
+
1146
+ ```rb
1147
+ # Tests example react component
1148
+ require "application_system_test_case"
1149
+ class HomesTest < ApplicationSystemTestCase
1150
+ test "can see the hello message" do
1151
+ visit root_url
1152
+ assert_selector "h5", text: "Hello! David"
1153
+ end
1154
+ end
1155
+ ```
1156
+
1157
+ #### Caching
1158
+
1159
+ By default, the lazy compilation is cached until a file is changed under
1160
+ tracked paths. You can configure the paths tracked
1161
+ by adding new paths to `watched_paths` array, much like rails `autoload_paths`:
1162
+
1163
+ ```rb
1164
+ # config/initializers/webpacker.rb
1165
+ # or config/application.rb
1166
+ Webpacker::Compiler.watched_paths << 'bower_components'
1167
+ ```
1168
+
1169
+ Compiler stores a timestamp under `tmp/webpacker/` directory to keep track of
1170
+ changes and you can configure that by overriding compiler `cache_dir`:
1171
+
1172
+ ```rb
1173
+ Webpacker::Compiler.cache_dir = "tmp/foo"
1174
+ ```
1175
+
1176
+ ## Troubleshooting
1177
+
1178
+ ##### ENOENT: no such file or directory - node-sass
1179
+
1180
+ * If you get this error `ENOENT: no such file or directory - node-sass` on Heroku
1181
+ or elsewhere during `assets:precompile` or `bundle exec rails webpacker:compile`
1182
+ then you would need to rebuild node-sass. It's a bit of a weird error;
1183
+ basically, it can't find the `node-sass` binary.
1184
+ An easy solution is to create a postinstall hook - `npm rebuild node-sass` in
1185
+ `package.json` and that will ensure `node-sass` is rebuilt whenever
1186
+ you install any new modules.
1187
+
1188
+ ##### Can't find hello_react.js in manifest.json
1189
+
1190
+ * If you get this error `Can't find hello_react.js in manifest.json`
1191
+ when loading a view in the browser it's because Webpack is still compiling packs.
1192
+ Webpacker uses a `manifest.json` file to keep track of packs in all environments,
1193
+ however since this file is generated after packs are compiled by webpack. So,
1194
+ if you load a view in browser whilst webpack is compiling you will get this error.
1195
+ Therefore, make sure webpack
1196
+ (i.e `./bin/webpack-dev-server`) is running and has
1197
+ completed the compilation successfully before loading a view.
1198
+
1199
+ ##### Error: listen EADDRINUSE 0.0.0.0:8080
1200
+
1201
+ * Do you have any process running on port 8080? Since only one process can occupy each port, you can change the port number of webpack-dev-server at `config/webpacker.yml` under dev_server's port. Alternatively, you can stop the process from occupying port 8080. To do so, simply find the process id (PID) using `lsof -i :8080` and kill the process with its PID using `kill -9 PID`.
1202
+
1203
+
1204
+ ##### throw er; // Unhandled 'error' event
1205
+
1206
+ * If you get this error while trying to use Elm, try rebuilding Elm. You can do
1207
+ so with a postinstall hook in your `package.json`:
1208
+
1209
+ ```
1210
+ "scripts": {
1211
+ "postinstall": "npm rebuild elm"
1212
+ }
1213
+ ```
1214
+
1215
+ ##### webpack or webpack-dev-server not found
1216
+
1217
+ * This could happen if `webpacker:install` step is skipped. Please run `bundle exec rails webpacker:install` to fix the issue.
1218
+
1219
+ * If you encounter the above error on heroku after upgrading from Rails 4.x to 5.1.x, then the problem might be related to missing `yarn` binstub. Please run following commands to update/add binstubs:
1220
+
1221
+ ```bash
1222
+ bundle config --delete bin
1223
+ ./bin/rails app:update:bin # or rails app:update:bin
1224
+ ```
1225
+
1226
+ ##### Running Webpack on Windows
1227
+
1228
+ If you are running Webpack on Windows, your command shell may not be able to interpret the preferred interpreter
1229
+ for the scripts generated in `bin/webpack` and `bin/webpack-dev-server`. Instead you'll want to run the scripts
1230
+ manually with Ruby:
1231
+
1232
+ ```
1233
+ C:\path>ruby bin\webpack
1234
+ C:\path>ruby bin\webpack-dev-server
1235
+ ```
1236
+
1237
+ ## Wishlist
1238
+
1239
+ - HMR - [#188](https://github.com/rails/webpacker/issues/188)
1240
+ - Support rails engines - [#348](https://github.com/rails/webpacker/issues/348)
1241
+
1242
+
1243
+ ## License
1244
+ Webpacker is released under the [MIT License](https://opensource.org/licenses/MIT).