webpacker 5.2.1 → 6.0.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +1 -1
  3. data/.gitignore +2 -0
  4. data/.node-version +1 -1
  5. data/.rubocop.yml +11 -16
  6. data/CHANGELOG.md +15 -4
  7. data/CONTRIBUTING.md +1 -1
  8. data/Gemfile.lock +17 -11
  9. data/README.md +8 -4
  10. data/docs/assets.md +21 -5
  11. data/docs/css.md +24 -29
  12. data/docs/deployment.md +18 -0
  13. data/docs/docker.md +2 -2
  14. data/docs/engines.md +1 -1
  15. data/docs/env.md +5 -0
  16. data/docs/es6.md +1 -1
  17. data/docs/integrations.md +1 -1
  18. data/docs/props.md +2 -38
  19. data/docs/react.md +183 -0
  20. data/docs/testing.md +11 -0
  21. data/docs/typescript.md +2 -2
  22. data/docs/webpack-dev-server.md +17 -15
  23. data/docs/webpack.md +58 -107
  24. data/lib/install/config/webpack/base.js +3 -0
  25. data/lib/install/config/webpack/development.js +2 -2
  26. data/lib/install/config/webpack/production.js +2 -2
  27. data/lib/install/config/webpack/test.js +2 -2
  28. data/lib/install/config/webpacker.yml +8 -37
  29. data/lib/install/examples/{vue → vue3}/app.vue +10 -5
  30. data/lib/install/examples/vue3/hello_vue.js +15 -0
  31. data/lib/install/javascript/packs/application.css +9 -0
  32. data/lib/install/template.rb +33 -19
  33. data/lib/tasks/webpacker.rake +2 -11
  34. data/lib/tasks/webpacker/binstubs.rake +6 -4
  35. data/lib/tasks/webpacker/check_binstubs.rake +4 -4
  36. data/lib/tasks/webpacker/check_yarn.rake +1 -2
  37. data/lib/tasks/webpacker/compile.rake +4 -2
  38. data/lib/tasks/webpacker/info.rake +12 -10
  39. data/lib/tasks/webpacker/install.rake +6 -4
  40. data/lib/tasks/webpacker/verify_install.rake +2 -1
  41. data/lib/tasks/webpacker/yarn_install.rake +9 -1
  42. data/lib/webpacker/commands.rb +1 -1
  43. data/lib/webpacker/compiler.rb +7 -6
  44. data/lib/webpacker/configuration.rb +6 -30
  45. data/lib/webpacker/dev_server_runner.rb +21 -2
  46. data/lib/webpacker/helper.rb +22 -32
  47. data/lib/webpacker/manifest.rb +1 -1
  48. data/lib/webpacker/version.rb +1 -1
  49. data/lib/webpacker/webpack_runner.rb +5 -0
  50. data/package.json +23 -39
  51. data/package/__tests__/config.js +5 -37
  52. data/package/__tests__/development.js +9 -11
  53. data/package/__tests__/env.js +12 -4
  54. data/package/__tests__/production.js +6 -6
  55. data/package/__tests__/staging.js +7 -6
  56. data/package/__tests__/test.js +4 -5
  57. data/package/babel/preset-react.js +62 -0
  58. data/package/babel/preset.js +44 -0
  59. data/package/config.js +3 -11
  60. data/package/env.js +8 -2
  61. data/package/environments/__tests__/base.js +15 -47
  62. data/package/environments/base.js +66 -126
  63. data/package/environments/development.js +45 -44
  64. data/package/environments/production.js +69 -65
  65. data/package/environments/test.js +2 -2
  66. data/package/index.js +6 -6
  67. data/package/rules/babel.js +9 -7
  68. data/package/rules/coffee.js +6 -0
  69. data/package/rules/erb.js +13 -0
  70. data/package/rules/file.js +19 -19
  71. data/package/rules/index.js +24 -18
  72. data/package/rules/less.js +18 -0
  73. data/package/rules/sass.js +5 -6
  74. data/package/rules/svg.js +23 -0
  75. data/package/utils/get_style_rule.js +22 -28
  76. data/package/utils/helpers.js +3 -35
  77. data/test/compiler_test.rb +0 -12
  78. data/test/configuration_test.rb +1 -32
  79. data/test/dev_server_runner_test.rb +24 -5
  80. data/test/engine_rake_tasks_test.rb +39 -0
  81. data/test/helper_test.rb +15 -9
  82. data/test/mounted_app/Rakefile +4 -0
  83. data/test/mounted_app/test/dummy/Rakefile +3 -0
  84. data/test/mounted_app/test/dummy/bin/rails +3 -0
  85. data/test/mounted_app/test/dummy/bin/rake +3 -0
  86. data/test/mounted_app/test/dummy/config.ru +5 -0
  87. data/test/mounted_app/test/dummy/config/application.rb +10 -0
  88. data/test/mounted_app/test/dummy/config/environment.rb +3 -0
  89. data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
  90. data/test/mounted_app/test/dummy/package.json +7 -0
  91. data/test/rake_tasks_test.rb +1 -10
  92. data/test/test_app/config/webpacker.yml +1 -25
  93. data/test/test_app/config/webpacker_public_root.yml +0 -1
  94. data/test/test_app/public/packs/manifest.json +17 -13
  95. data/test/test_app/some.config.js +0 -0
  96. data/test/webpack_runner_test.rb +9 -3
  97. data/webpacker.gemspec +1 -1
  98. data/yarn.lock +1858 -4915
  99. metadata +47 -70
  100. data/.travis.yml +0 -43
  101. data/lib/install/angular.rb +0 -23
  102. data/lib/install/coffee.rb +0 -25
  103. data/lib/install/config/.browserslistrc +0 -1
  104. data/lib/install/config/babel.config.js +0 -70
  105. data/lib/install/config/postcss.config.js +0 -12
  106. data/lib/install/config/webpack/environment.js +0 -3
  107. data/lib/install/elm.rb +0 -39
  108. data/lib/install/erb.rb +0 -25
  109. data/lib/install/examples/angular/hello_angular.js +0 -7
  110. data/lib/install/examples/angular/hello_angular/app/app.component.ts +0 -9
  111. data/lib/install/examples/angular/hello_angular/app/app.module.ts +0 -16
  112. data/lib/install/examples/angular/hello_angular/index.ts +0 -8
  113. data/lib/install/examples/angular/hello_angular/polyfills.ts +0 -73
  114. data/lib/install/examples/coffee/hello_coffee.coffee +0 -4
  115. data/lib/install/examples/elm/Main.elm +0 -55
  116. data/lib/install/examples/elm/hello_elm.js +0 -16
  117. data/lib/install/examples/erb/hello_erb.js.erb +0 -6
  118. data/lib/install/examples/react/babel.config.js +0 -87
  119. data/lib/install/examples/react/hello_react.jsx +0 -26
  120. data/lib/install/examples/react/tsconfig.json +0 -21
  121. data/lib/install/examples/stimulus/application.js +0 -1
  122. data/lib/install/examples/stimulus/controllers/hello_controller.js +0 -18
  123. data/lib/install/examples/stimulus/controllers/index.js +0 -9
  124. data/lib/install/examples/svelte/app.svelte +0 -11
  125. data/lib/install/examples/svelte/hello_svelte.js +0 -20
  126. data/lib/install/examples/typescript/hello_typescript.ts +0 -4
  127. data/lib/install/examples/typescript/tsconfig.json +0 -24
  128. data/lib/install/examples/vue/hello_vue.js +0 -72
  129. data/lib/install/loaders/coffee.js +0 -6
  130. data/lib/install/loaders/elm.js +0 -25
  131. data/lib/install/loaders/erb.js +0 -11
  132. data/lib/install/loaders/svelte.js +0 -9
  133. data/lib/install/loaders/vue.js +0 -6
  134. data/lib/install/react.rb +0 -18
  135. data/lib/install/stimulus.rb +0 -12
  136. data/lib/install/svelte.rb +0 -29
  137. data/lib/install/typescript.rb +0 -39
  138. data/lib/install/vue.rb +0 -49
  139. data/lib/tasks/installers.rake +0 -42
  140. data/package/config_types/__tests__/config_list.js +0 -118
  141. data/package/config_types/__tests__/config_object.js +0 -43
  142. data/package/config_types/config_list.js +0 -75
  143. data/package/config_types/config_object.js +0 -55
  144. data/package/config_types/index.js +0 -7
  145. data/package/rules/module.css.js +0 -3
  146. data/package/rules/module.sass.js +0 -8
  147. data/package/rules/node_modules.js +0 -22
  148. data/package/utils/__tests__/deep_assign.js +0 -32
  149. data/package/utils/__tests__/deep_merge.js +0 -10
  150. data/package/utils/__tests__/get_style_rule.js +0 -65
  151. data/package/utils/__tests__/objectify.js +0 -9
  152. data/package/utils/deep_assign.js +0 -22
  153. data/package/utils/deep_merge.js +0 -22
  154. data/package/utils/objectify.js +0 -3
@@ -128,3 +128,21 @@ namespace :deploy do
128
128
  end
129
129
  end
130
130
  ```
131
+
132
+ If you use [nvm](https://github.com/nvm-sh/nvm) to manage node versions for your deployment user, use the below snippet instead:
133
+
134
+ ```ruby
135
+ before "deploy:assets:precompile", "deploy:yarn_install"
136
+ namespace :deploy do
137
+ desc "Run rake yarn install"
138
+ task :yarn_install do
139
+ on roles(:web) do
140
+ within release_path do
141
+ execute("source ~/.nvm/nvm.sh && cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")
142
+ end
143
+ end
144
+ end
145
+ end
146
+ ```
147
+ The `source ~/.nvm/nvm.sh` is required because [nvm is not automatically loaded in non-interactive shells](https://github.com/nvm-sh/nvm/issues/1718).
148
+
@@ -17,7 +17,7 @@ services:
17
17
  volumes:
18
18
  - .:/webpacker-example-app
19
19
  ports:
20
- - '3035:3035'
20
+ - '127.0.0.1:3035:3035'
21
21
  ```
22
22
 
23
23
  add nodejs and yarn as dependencies in Dockerfile,
@@ -56,7 +56,7 @@ then add the webpacker host name environment variable to the web/app service:
56
56
  volumes:
57
57
  - .:/usr/src/app
58
58
  ports:
59
- - "3000:3000"
59
+ - "127.0.0.1:3000:3000"
60
60
  environment:
61
61
  - WEBPACKER_DEV_SERVER_HOST=webpacker
62
62
  ```
@@ -99,7 +99,7 @@ Now you can use `stylesheet_pack_tag` and `javascript_pack_tag` from within your
99
99
 
100
100
  Add Rake task to compile assets in production (`rake my_engine:webpacker:compile`)
101
101
 
102
- - File `my_engine_rootlib/tasks/my_engine_tasks.rake`
102
+ - File `lib/tasks/my_engine_tasks.rake`
103
103
 
104
104
  ```ruby
105
105
  def ensure_log_goes_to_stdout
@@ -49,6 +49,11 @@ dotenvFiles.forEach((dotenvFile) => {
49
49
  dotenv.config({ path: dotenvFile, silent: true })
50
50
  })
51
51
 
52
+ environment.plugins.insert(
53
+ "Environment",
54
+ new webpack.EnvironmentPlugin(process.env)
55
+ )
56
+
52
57
  module.exports = environment
53
58
  ```
54
59
 
@@ -42,7 +42,7 @@ The comment you see above (`/* webpackChunkName */`) is not arbitrary, it is one
42
42
  **Warning**: You should not attempt to dynamically load anything from your `packs/` folder. Instead, try to make your `pack` scripts a hub from which you dynamically load `non-pack` scripts.
43
43
 
44
44
  - [Docs for using magic comments](https://webpack.js.org/api/module-methods/#magic-comments)
45
- - [Docs for configuring `splitChunks` in webpacker](https://github.com/rails/webpacker/blob/master/docs/webpack.md#add-splitchunks-webpack-v4).
45
+ - [Docs for configuring `splitChunks` in webpacker](/docs/webpack.md#add-splitchunks-webpack-v4).
46
46
  - [Docs for using dynamic `import()`](https://webpack.js.org/guides/code-splitting#dynamic-imports).
47
47
 
48
48
  ## Module import vs require()
@@ -213,7 +213,7 @@ in `app/javascript/packs` so that you can experiment with CoffeeScript right awa
213
213
 
214
214
  To add [Erb](https://apidock.com/ruby/ERB) support in your JS templates,
215
215
  run `bundle exec rails webpacker:install:erb` on a Rails app already
216
- setup with Webpacker.
216
+ setup with Webpacker and add extension 'erb' on file `config/webpacker.yml`.
217
217
 
218
218
  An example `hello_erb.js.erb` file will also be added to your project
219
219
  in `app/javascript/packs` so that you can experiment with Erb-flavoured
@@ -1,45 +1,9 @@
1
1
  # Props
2
2
 
3
+ How do you pass props from your view to your JavaScript component? Here you go.
3
4
 
4
5
  ## React
5
-
6
- If you need more advanced React-integration, like server rendering, redux, or react-router, see [shakacode/react_on_rails](https://github.com/shakacode/react_on_rails), [react-rails](https://github.com/reactjs/react-rails), and [webpacker-react](https://github.com/renchap/webpacker-react).
7
-
8
- If you're not concerned with view helpers to pass props or server rendering, can do it yourself:
9
-
10
- ```erb
11
- <%# views/layouts/application.html.erb %>
12
-
13
- <%= content_tag :div,
14
- id: "hello-react",
15
- data: {
16
- message: 'Hello!',
17
- name: 'David'
18
- }.to_json do %>
19
- <% end %>
20
- ```
21
-
22
- ```js
23
- // app/javascript/packs/hello_react.js
24
-
25
- const Hello = props => (
26
- <div className='react-app-wrapper'>
27
- <img src={clockIcon} alt="clock" />
28
- <h5 className='hello-react'>
29
- {props.message} {props.name}!
30
- </h5>
31
- </div>
32
- )
33
-
34
- // Render component with data
35
- document.addEventListener('DOMContentLoaded', () => {
36
- const node = document.getElementById('hello-react')
37
- const data = JSON.parse(node.getAttribute('data'))
38
-
39
- ReactDOM.render(<Hello {...data} />, node)
40
- })
41
- ```
42
-
6
+ See [docs/react.md](./react.md#props-hydration-and-server-side-rendering-ssr).
43
7
 
44
8
  ## Vue
45
9
 
@@ -0,0 +1,183 @@
1
+ # React
2
+
3
+ ## Props Hydration and Server-Side Rendering (SSR)
4
+ You only _need_ props hydration if you need SSR. However, there's no good reason to
5
+ have your app make a second round trip to the Rails server to get initialization props.
6
+
7
+ Server-Side Rendering (SSR) results in Rails rendering HTML for your React components.
8
+ The main reasons to use SSR are better SEO and pages display more quickly.
9
+
10
+ ### Rails and React Integration Gems
11
+ If you desire more advanced React-integration, like server-side rendering, SSR with react-router, SSR with code splitting, then you should consider these gems:
12
+
13
+ | Gem | Props Hydration | Server-Side-Rendering (SSR) | SSR with HMR | SSR with React-Router | SSR with Code Splitting | Node SSR |
14
+ | --- | --------------- | --- | --------------------- | ----------------------| ------------------------|----|
15
+ | [shakacode/react_on_rails](https://github.com/shakacode/react_on_rails) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
16
+ | [react-rails](https://github.com/reactjs/react-rails) | ✅ | ✅ | | | | | |
17
+ | [webpacker-react](https://github.com/renchap/webpacker-react) | ✅ | | | | | | |
18
+
19
+ Note, Node SSR for React on Rails requires [React on Rails Pro](https://www.shakacode.com/react-on-rails-pro).
20
+
21
+ ### Hydration of Props the Manual Way
22
+
23
+ If you're not concerned with view helpers to pass props or server-side rendering, you can do it like this:
24
+
25
+ ```erb
26
+ <%# views/layouts/application.html.erb %>
27
+
28
+ <%= content_tag :div,
29
+ id: "hello-react",
30
+ data: {
31
+ message: 'Hello!',
32
+ name: 'David'
33
+ }.to_json do %>
34
+ <% end %>
35
+ ```
36
+
37
+ ```js
38
+ // app/javascript/packs/hello_react.js
39
+
40
+ const Hello = props => (
41
+ <div className='react-app-wrapper'>
42
+ <img src={clockIcon} alt="clock" />
43
+ <h5 className='hello-react'>
44
+ {props.message} {props.name}!
45
+ </h5>
46
+ </div>
47
+ )
48
+
49
+ // Render component with data
50
+ document.addEventListener('DOMContentLoaded', () => {
51
+ const node = document.getElementById('hello-react')
52
+ const data = JSON.parse(node.getAttribute('data'))
53
+
54
+ ReactDOM.render(<Hello {...data} />, node)
55
+ })
56
+ ```
57
+
58
+ ----
59
+
60
+ ## HMR and React Hot Reloading
61
+
62
+ Before turning HMR on, consider upgrading to the latest stable gems and packages:
63
+ https://github.com/rails/webpacker#upgrading
64
+
65
+ Configure `config/webpacker.yml` file:
66
+
67
+ ```yaml
68
+ development:
69
+ extract_css: false
70
+ dev_server:
71
+ hmr: true
72
+ inline: true
73
+ ```
74
+
75
+ This basic configuration alone will have HMR working with the default webpacker setup. However, an code saves will trigger a full page refresh each time you save a file.
76
+
77
+ Webpack's HMR allows the replacement of modules for React in-place without reloading the browser. To do this, you have two options:
78
+
79
+ 1. Steps below for the [github.com/pmmmwh/react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin).
80
+ 1. Deprecated steps below for using the [github.com/gaearon/react-hot-loader](https://github.com/gaearon/react-hot-loader).
81
+
82
+ ### React Refresh Webpack Plugin
83
+ [github.com/pmmmwh/react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin)
84
+
85
+ You can see an example commit of adding this [here](https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/commit/7e53803fce7034f5ecff335db1f400a5743a87e7).
86
+
87
+ 1. Add react refresh packages:
88
+ `yarn add @pmmmwh/react-refresh-webpack-plugin react-refresh -D`
89
+ 2. Update `babel.config.js` adding
90
+ ```js
91
+ plugins: [
92
+ process.env.WEBPACK_DEV_SERVER && 'react-refresh/babel',
93
+ // other plugins
94
+ ```
95
+ 3. Update `config/webpack/development.js`, only including the plugin if running the WEBPACK_DEV_SERVER
96
+ ```js
97
+ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
98
+ const environment = require('./environment')
99
+
100
+ const isWebpackDevServer = process.env.WEBPACK_DEV_SERVER;
101
+
102
+ //plugins
103
+ if (isWebpackDevServer) {
104
+ environment.plugins.append(
105
+ 'ReactRefreshWebpackPlugin',
106
+ new ReactRefreshWebpackPlugin({
107
+ overlay: {
108
+ sockPort: 3035
109
+ }
110
+ })
111
+ );
112
+ }
113
+ ```
114
+
115
+ ### React Hot Loader (Deprecated)
116
+
117
+ 1. Add the `react-hot-loader` and ` @hot-loader/react-dom` npm packages.
118
+ ```sh
119
+ yarn add --dev react-hot-loader @hot-loader/react-dom
120
+ ```
121
+
122
+ 2. Update your babel config, `babel.config.js`. Add the plugin `react-hot-loader/babel`
123
+ with option `"safetyNet": false`:
124
+
125
+ ```
126
+ {
127
+ "plugins": [
128
+ [
129
+ "react-hot-loader/babel",
130
+ {
131
+ "safetyNet": false
132
+ }
133
+ ]
134
+ ]
135
+ }
136
+ ```
137
+
138
+ 3. Add changes like this to your entry points:
139
+
140
+ ```diff
141
+ // app/javascript/app.jsx
142
+
143
+ import React from 'react';
144
+ + import { hot } from 'react-hot-loader/root';
145
+
146
+ const App = () => <SomeComponent(s) />
147
+
148
+ - export default App;
149
+ + export default hot(App);
150
+ ```
151
+
152
+ 4. Adjust your webpack configuration for development so that `sourceMapContents` option for the sass
153
+ loader is `false`:
154
+
155
+ ```diff
156
+ // config/webpack/development.js
157
+
158
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
159
+
160
+ const environment = require('./environment')
161
+
162
+ // allows for editing sass/scss files directly in browser
163
+ + if (!module.hot) {
164
+ + environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader').options.sourceMapContents = false
165
+ + }
166
+ +
167
+ module.exports = environment.toWebpackConfig()
168
+ ```
169
+
170
+ 5. Adjust your `config/webpack/environment.js` for a
171
+
172
+ ```diff
173
+ // config/webpack/environment.js
174
+
175
+ // ...
176
+
177
+ // Fixes: React-Hot-Loader: react-🔥-dom patch is not detected. React 16.6+ features may not work.
178
+ // https://github.com/gaearon/react-hot-loader/issues/1227#issuecomment-482139583
179
+ + environment.config.merge({ resolve: { alias: { 'react-dom': '@hot-loader/react-dom' } } });
180
+
181
+ module.exports = environment;
182
+ ```
183
+
@@ -134,3 +134,14 @@ Make sure you configure Rails to serve static files from the public directory in
134
134
  # Configure public file server for tests with Cache-Control for performance.
135
135
  config.public_file_server.enabled = true
136
136
  ```
137
+
138
+ ## Webpacker Configuration and Rails Tests
139
+
140
+ Webpacker ships with three javascript configuration files: `test.js`,
141
+ `development.js`, and `production.js`. The `NODE_ENV` environment
142
+ variable determines which config will be used. `NODE_ENV` is
143
+ independent of `RAILS_ENV` and is set to `development` by [default](/lib/install/bin/webpack#L4).
144
+ This means that `rails test` or `rspec` will use `development.js`
145
+ by default, _not_ `test.js`.
146
+
147
+ For more information see [Why doesn't Webpacker use my test config when I run Rails tests?](https://rossta.net/blog/why-doesnt-webpacker-use-my-test-config-when-i-run-rails-tests.html)
@@ -37,7 +37,7 @@ The default installation only transpiles your TypeScript code using Babel. If yo
37
37
  );
38
38
  ```
39
39
 
40
- If you are `fork-ts-checker-webpack-plugin` older than 5.0, the `tsconfig` option also needs to be specified:
40
+ If you are using `fork-ts-checker-webpack-plugin` older than 5.0, the `tsconfig` option also needs to be specified:
41
41
 
42
42
  ```js
43
43
  const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
@@ -83,7 +83,7 @@ If you update your App to `webpacker >= 5.1` and had TypeScript installed before
83
83
 
84
84
  ## TypeScript with React
85
85
 
86
- 1. Setup react using Webpacker [react installer](../README.md#react). Then run the TypeScript installer
86
+ 1. Setup react using Webpacker [react installer](integrations.md#react). Then run the TypeScript installer
87
87
 
88
88
  ```bash
89
89
  bundle exec rails webpacker:install:typescript
@@ -1,6 +1,5 @@
1
1
  # webpack-dev-server
2
2
 
3
-
4
3
  ## HTTPS
5
4
 
6
5
  If you're using the `webpack-dev-server` in development, you can serve your packs over HTTPS
@@ -13,24 +12,28 @@ so your web browser will display a warning/exception upon accessing the page. If
13
12
  in your console, simply open the link in your browser and accept the SSL exception.
14
13
  Now if you refresh your Rails view everything should work as expected.
15
14
 
16
-
17
- ## HOT module replacement
15
+ ## Hot Module Replacement
18
16
 
19
17
  Webpacker out-of-the-box supports HMR with `webpack-dev-server` and
20
- you can toggle it by setting `dev_server/hmr` option inside `webpacker.yml`.
21
-
22
- Check out this guide for more information:
18
+ you can toggle it by setting options in `config/webpacker.yml`:
23
19
 
24
- - https://webpack.js.org/configuration/dev-server/#devserver-hot
20
+ ```yaml
21
+ development:
22
+ # ...
23
+ dev_server:
24
+ # ...
25
+ hmr: true
26
+ inline: true
27
+ # ...
28
+ ```
25
29
 
26
- To support HMR with React you would need to add `react-hot-loader`. Checkout this guide for
27
- more information:
30
+ `dev_server/hmr` option inside `webpacker.yml`.
28
31
 
29
- - https://gaearon.github.io/react-hot-loader/getstarted/
32
+ Check out this guide for more information:
30
33
 
31
- **Note:** Don't forget to disable `HMR` if you are not running `webpack-dev-server`
32
- otherwise you will get not found error for stylesheets.
34
+ - https://webpack.js.org/configuration/dev-server/#devserver-hot
33
35
 
36
+ To support HMR with React, see [docs/react.md](./react.md#hmr-and-react-hot-reloading).
34
37
 
35
38
  ## Nginx
36
39
 
@@ -77,9 +80,8 @@ server {
77
80
  ## Customizing Logging
78
81
 
79
82
  By default, the dev server will display a colored progress notification while
80
- your code is being compiled. (Under the hood, we are using `webpack-dev-server
81
- --progress --color`). However, this might cause issues if you don't use
82
- `foreman` and/or try to log webpack-dev-server's output to a file. You can
83
+ your code is being compiled. (Under the hood, we are using `webpack-dev-server --progress --color`). However, this might cause issues if you don't use
84
+ `foreman` and/or try to log webpack-dev-server's output to a file. You can
83
85
  disable this stylized output by adding `pretty: false` to your `dev_server`
84
86
  config:
85
87
 
@@ -14,6 +14,7 @@ if you do need to customize or add a new loader, this is where you would go.
14
14
 
15
15
  Here is how you can modify webpack configuration:
16
16
 
17
+ You might add separate files to keep your code more organized.
17
18
  ```js
18
19
  // config/webpack/custom.js
19
20
  module.exports = {
@@ -27,7 +28,11 @@ module.exports = {
27
28
  }
28
29
  }
29
30
  }
31
+ ```
32
+
33
+ Then `require` this file in your `config/webpack/environment.js`:
30
34
 
35
+ ```js
31
36
  // config/webpack/environment.js
32
37
  const { environment } = require('@rails/webpacker')
33
38
  const customConfig = require('./custom')
@@ -38,6 +43,8 @@ environment.config.set('output.filename', '[name].js')
38
43
 
39
44
  // Merge custom config
40
45
  environment.config.merge(customConfig)
46
+
47
+ // Merge other options
41
48
  environment.config.merge({ devtool: 'none' })
42
49
 
43
50
  // Delete a property
@@ -59,36 +66,36 @@ console.log(config.source_path)
59
66
  ## Loaders
60
67
 
61
68
  You can add additional loaders beyond the base set that Webpacker provides by
62
- adding it to your environment. We'll use `json-loader` as an example:
69
+ adding it to your environment. We'll use `url-loader` as an example:
63
70
 
64
71
  ```
65
- yarn add json-loader
72
+ yarn add url-loader
66
73
  ```
67
74
 
68
75
  ```js
69
76
  // config/webpack/environment.js
70
77
  const { environment } = require('@rails/webpacker')
71
78
 
72
- const jsonLoader = {
73
- test: /\.json$/,
74
- use: 'json-loader'
79
+ const urlLoader = {
80
+ test: /\.png$/,
81
+ use: 'url-loader'
75
82
  }
76
83
 
77
- // Insert json loader at the end of list
78
- environment.loaders.append('json', jsonLoader)
84
+ // Insert url loader at the end of list
85
+ environment.loaders.append('url', urlLoader)
79
86
 
80
- // Insert json loader at the top of list
81
- environment.loaders.prepend('json', jsonLoader)
87
+ // Insert url loader at the top of list
88
+ environment.loaders.prepend('url', urlLoader)
82
89
 
83
- // Insert json loader after/before a given loader
84
- environment.loaders.insert('json', jsonLoader, { after: 'style'} )
85
- environment.loaders.insert('json', jsonLoader, { before: 'babel'} )
90
+ // Insert url loader after/before a given loader
91
+ environment.loaders.insert('url', urlLoader, { after: 'style'} )
92
+ environment.loaders.insert('url', urlLoader, { before: 'babel'} )
86
93
 
87
94
  module.exports = environment
88
95
  ```
89
96
 
90
- Finally add `.json` to the list of extensions in `config/webpacker.yml`. Now if you `import()` any `.json` files inside your JavaScript
91
- they will be processed using `json-loader`. Voila!
97
+ Finally, add `.png` to the list of extensions in `config/webpacker.yml`. Now if you `import()` any `.png` files inside your JavaScript
98
+ they will be processed using `url-loader`. Voila!
92
99
 
93
100
  You can also modify the loaders that Webpacker pre-configures for you. We'll update
94
101
  the `babel` loader as an example:
@@ -132,6 +139,7 @@ module.exports = environment
132
139
  To use react svg loader, you should append svg loader before file loader:
133
140
 
134
141
  ```js
142
+ // config/webpack/environment.js
135
143
  const { environment } = require('@rails/webpacker')
136
144
 
137
145
  const babelLoader = environment.loaders.get('babel')
@@ -155,61 +163,31 @@ fileLoader.exclude = /\.(svg)$/i
155
163
 
156
164
  ### Url Loader
157
165
 
166
+ Be sure to add the default options from the file loader, as those are applied with the file loader if the size is greater than the `limit`.
167
+
158
168
  ```js
159
- // config/webpack/loaders/url.js
169
+ // config/webpack/environment.js
160
170
 
161
- module.exports = {
171
+ const { environment } = require('@rails/webpacker');
172
+ const rules = environment.loaders;
173
+
174
+ const urlFileSizeCutover = 10000;
175
+ const urlLoaderOptions = Object.assign({ limit: urlFileSizeCutover }, fileLoader.use[0].options);
176
+ const urlLoader = {
162
177
  test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
163
- use: [{
178
+ use: {
164
179
  loader: 'url-loader',
165
- options: {
166
- limit: 10000,
167
- name: '[name]-[hash].[ext]'
168
- }
169
- }]
170
- }
171
-
172
- // config/webpack/environment.js
173
-
174
- const { environment } = require('@rails/webpacker')
175
- const url = require('./loaders/url')
180
+ options: urlLoaderOptions,
181
+ },
182
+ };
176
183
 
177
- environment.loaders.prepend('url', url)
184
+ environment.loaders.prepend('url', urlLoader)
178
185
 
179
186
  // avoid using both file and url loaders
187
+ // Note, this list should take into account the config value for static_assets_extensions
180
188
  environment.loaders.get('file').test = /\.(tiff|ico|svg|eot|otf|ttf|woff|woff2)$/i
181
189
  ```
182
190
 
183
- ### Overriding Loader Options in webpack 3+ (for CSS Modules etc.)
184
-
185
- In webpack 3+, if you'd like to specify additional or different options for a loader, edit `config/webpack/environment.js` and provide an options object to override. This is similar to the technique shown above, but the following example shows specifically how to apply CSS Modules, which is what you may be looking for:
186
-
187
- ```javascript
188
- const { environment } = require('@rails/webpacker')
189
- const merge = require('webpack-merge')
190
-
191
- const myCssLoaderOptions = {
192
- modules: {
193
- localIdentName: '[name]__[local]___[hash:base64:5]'
194
- },
195
- sourceMap: true,
196
- }
197
-
198
- const CSSLoader = environment.loaders.get('sass').use.find(el => el.loader === 'css-loader')
199
-
200
- CSSLoader.options = merge(CSSLoader.options, myCssLoaderOptions)
201
-
202
- module.exports = environment
203
- ```
204
-
205
- See [issue #756](https://github.com/rails/webpacker/issues/756#issuecomment-327148547) for additional discussion of this.
206
-
207
- For this to work, don't forget to use the `stylesheet_pack_tag`, for example:
208
-
209
- ```
210
- <%= stylesheet_pack_tag 'YOUR_PACK_NAME_HERE' %>
211
- ```
212
-
213
191
  ## Plugins
214
192
 
215
193
  The process for adding or modifying webpack plugins is the same as the process
@@ -239,14 +217,6 @@ environment.plugins.prepend(
239
217
  })
240
218
  )
241
219
 
242
- // Insert before a given plugin
243
- environment.plugins.insert('CommonChunkVendor',
244
- new webpack.optimize.CommonsChunkPlugin({
245
- name: 'vendor', // Vendor code
246
- minChunks: (module) => module.context && module.context.indexOf('node_modules') !== -1
247
- })
248
- , { before: 'manifest' })
249
-
250
220
  module.exports = environment
251
221
  ```
252
222
 
@@ -261,7 +231,7 @@ const { environment } = require('@rails/webpacker')
261
231
  environment.resolvedModules.append('vendor', 'vendor')
262
232
  ```
263
233
 
264
- ### Add SplitChunks (Webpack V4)
234
+ ### Add SplitChunks (Webpack V4+)
265
235
  Originally, chunks (and modules imported inside them) were connected by a parent-child relationship in the internal webpack graph. The CommonsChunkPlugin was used to avoid duplicated dependencies across them, but further optimizations were not possible.
266
236
 
267
237
  Since webpack v4, the CommonsChunkPlugin was removed in favor of optimization.splitChunks.
@@ -303,8 +273,6 @@ get duplicated chunks on the page.
303
273
  <%= javascript_packs_with_chunks_tag 'map' %>
304
274
  ```
305
275
 
306
- For the old configuration with the CommonsChunkPlugin see below. **Note** that this functionality is deprecated in Webpack V4.
307
-
308
276
  #### Preloading
309
277
 
310
278
  Before preload or prefetch your assets, please read [https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content).
@@ -319,46 +287,29 @@ You can preload your assets with the `preload_pack_asset` helper if you have Rai
319
287
 
320
288
  **Warning:** You don't want to preload the css, you want to preload the fonts and images inside the css so that fonts, css, and images can all be downloaded in parallel instead of waiting for the browser to parse the css.
321
289
 
322
- ### Add common chunks (deprecated in Webpack V4)
323
-
324
- 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.
325
-
326
- Add the plugins in `config/webpack/environment.js`:
327
-
328
- ```js
329
- const webpack = require('webpack')
330
-
331
- environment.plugins.append(
332
- 'CommonsChunkVendor',
333
- new webpack.optimize.CommonsChunkPlugin({
334
- name: 'vendor',
335
- minChunks: (module) => {
336
- // this assumes your vendor imports exist in the node_modules directory
337
- return module.context && module.context.indexOf('node_modules') !== -1
338
- }
339
- })
340
- )
341
-
342
- environment.plugins.append(
343
- 'CommonsChunkManifest',
344
- new webpack.optimize.CommonsChunkPlugin({
345
- name: 'manifest',
346
- minChunks: Infinity
347
- })
348
- )
349
- ```
290
+ More detailed guides available here: [webpack guides](https://webpack.js.org/guides/)
350
291
 
351
- Now, add these files to your `layouts/application.html.erb`:
292
+ ## Webpack Multi-Compiler and Server-Side Rendering
293
+ You can export an Array of Object to have both `bin/webpack` and `bin/webpack-dev-server`
294
+ use multiple configurations. This is commonly done for React server-side rendering (SSR).
352
295
 
353
- ```erb
354
- <%# Head %>
296
+ For an example of this, see the configuration within the [`/config/webpack` dir of the React on Rails Example](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/config/webpack).
355
297
 
356
- <%= javascript_pack_tag "manifest" %>
357
- <%= javascript_pack_tag "vendor" %>
298
+ Take special care in that you need to make a deep copy of the output from the the basic "client" configuration.
358
299
 
359
- <%# If importing any styles from node_modules in your JS app %>
300
+ In the example below, you _cannot_ modify the clientConfigObject as that would mutate the "environment" that is global.
360
301
 
361
- <%= stylesheet_pack_tag "vendor" %>
302
+ ```js
303
+ const environment = require('./environment');
304
+
305
+ // make a deep copy
306
+ const clientConfigObject = environment.toWebpackConfig();
307
+ const serverWebpackConfig = merge({}, clientConfigObject);
308
+
309
+ // make whatever changes you want for the serverWebpackConfig
310
+
311
+ // No splitting of chunks for a server bundle
312
+ serverWebpackConfig.optimization = {
313
+ minimize: false,
314
+ };
362
315
  ```
363
-
364
- More detailed guides available here: [webpack guides](https://webpack.js.org/guides/)