webpacker-legacy 0.1.0

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