webpacker 6.0.0.pre.2 → 6.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/jest.yml +5 -2
  3. data/.github/workflows/js-lint.yml +5 -2
  4. data/.github/workflows/rubocop.yml +1 -1
  5. data/.github/workflows/ruby.yml +17 -14
  6. data/.node-version +1 -1
  7. data/.rubocop.yml +106 -0
  8. data/CHANGELOG.md +36 -9
  9. data/CONTRIBUTING.md +1 -1
  10. data/Gemfile.lock +93 -90
  11. data/README.md +363 -107
  12. data/config/README.md +3 -0
  13. data/config/webpacker.yml +1 -0
  14. data/docs/deployment.md +9 -29
  15. data/docs/developing_webpacker.md +29 -0
  16. data/docs/troubleshooting.md +57 -25
  17. data/docs/v6_upgrade.md +75 -0
  18. data/gemfiles/Gemfile-rails-edge +1 -1
  19. data/gemfiles/Gemfile-rails.6.1.x +12 -0
  20. data/lib/install/config/webpacker.yml +5 -7
  21. data/lib/install/{javascript/packs → packs/entrypoints}/application.js +4 -3
  22. data/lib/install/template.rb +17 -10
  23. data/lib/tasks/webpacker/binstubs.rake +2 -2
  24. data/lib/tasks/webpacker/check_node.rake +3 -0
  25. data/lib/tasks/webpacker/check_yarn.rake +4 -1
  26. data/lib/tasks/webpacker/clobber.rake +1 -1
  27. data/lib/tasks/webpacker/install.rake +2 -2
  28. data/lib/tasks/webpacker/verify_config.rake +14 -0
  29. data/lib/tasks/webpacker/verify_install.rake +1 -11
  30. data/lib/webpacker.rb +1 -1
  31. data/lib/webpacker/commands.rb +2 -1
  32. data/lib/webpacker/compiler.rb +9 -3
  33. data/lib/webpacker/configuration.rb +19 -8
  34. data/lib/webpacker/dev_server.rb +6 -0
  35. data/lib/webpacker/dev_server_runner.rb +7 -2
  36. data/lib/webpacker/env.rb +5 -1
  37. data/lib/webpacker/helper.rb +26 -50
  38. data/lib/webpacker/instance.rb +4 -0
  39. data/lib/webpacker/manifest.rb +1 -2
  40. data/lib/webpacker/railtie.rb +1 -2
  41. data/lib/webpacker/runner.rb +1 -1
  42. data/lib/webpacker/version.rb +1 -1
  43. data/lib/webpacker/webpack_runner.rb +1 -0
  44. data/package.json +25 -29
  45. data/package/__tests__/development.js +3 -2
  46. data/package/__tests__/env.js +8 -4
  47. data/package/__tests__/index.js +9 -0
  48. data/package/babel/preset.js +24 -14
  49. data/package/env.js +7 -1
  50. data/package/environments/__tests__/base.js +7 -7
  51. data/package/environments/base.js +25 -25
  52. data/package/environments/development.js +7 -8
  53. data/package/environments/production.js +28 -30
  54. data/package/index.js +9 -2
  55. data/package/inliningCss.js +7 -0
  56. data/package/rules/babel.js +1 -1
  57. data/package/rules/coffee.js +5 -5
  58. data/package/rules/erb.js +5 -3
  59. data/package/rules/file.js +5 -3
  60. data/package/rules/index.js +9 -17
  61. data/package/rules/less.js +14 -10
  62. data/package/rules/raw.js +5 -0
  63. data/package/rules/sass.js +12 -9
  64. data/package/rules/stylus.js +26 -0
  65. data/package/utils/get_style_rule.js +28 -30
  66. data/package/utils/helpers.js +25 -0
  67. data/test/configuration_test.rb +3 -3
  68. data/test/dev_server_runner_test.rb +13 -2
  69. data/test/helper_test.rb +59 -60
  70. data/test/manifest_test.rb +16 -0
  71. data/test/mounted_app/test/dummy/config/webpacker.yml +4 -4
  72. data/test/test_app/app/{javascript/packs → packs/entrypoints}/application.js +1 -1
  73. data/test/test_app/app/{javascript/packs → packs/entrypoints}/multi_entry.css +0 -0
  74. data/test/test_app/app/{javascript/packs → packs/entrypoints}/multi_entry.js +0 -0
  75. data/test/test_app/config/webpacker.yml +4 -6
  76. data/test/test_app/config/webpacker_other_location.yml +79 -0
  77. data/test/test_app/public/packs/manifest.json +19 -5
  78. data/test/webpacker_test.rb +17 -0
  79. data/yarn.lock +1567 -1039
  80. metadata +24 -36
  81. data/docs/assets.md +0 -135
  82. data/docs/cloud9.md +0 -310
  83. data/docs/css.md +0 -303
  84. data/docs/docker.md +0 -68
  85. data/docs/engines.md +0 -213
  86. data/docs/env.md +0 -68
  87. data/docs/es6.md +0 -72
  88. data/docs/folder-structure.md +0 -66
  89. data/docs/integrations.md +0 -220
  90. data/docs/misc.md +0 -23
  91. data/docs/props.md +0 -187
  92. data/docs/react.md +0 -183
  93. data/docs/target.md +0 -22
  94. data/docs/testing.md +0 -147
  95. data/docs/typescript.md +0 -190
  96. data/docs/v4-upgrade.md +0 -142
  97. data/docs/webpack-dev-server.md +0 -94
  98. data/docs/webpack.md +0 -315
  99. data/docs/yarn.md +0 -23
  100. data/lib/install/examples/vue3/app.vue +0 -27
  101. data/lib/install/examples/vue3/hello_vue.js +0 -15
  102. data/lib/install/javascript/packs/application.css +0 -9
  103. data/package/babel/preset-react.js +0 -62
  104. data/package/rules/svg.js +0 -23
data/docs/props.md DELETED
@@ -1,187 +0,0 @@
1
- # Props
2
-
3
- How do you pass props from your view to your JavaScript component? Here you go.
4
-
5
- ## React
6
- See [docs/react.md](./react.md#props-hydration-and-server-side-rendering-ssr).
7
-
8
- ## Vue
9
-
10
- Add the data as attributes in the element you are going to use (or any other element for that matter).
11
-
12
- ```erb
13
- <%= content_tag :div,
14
- id: "hello-vue",
15
- data: {
16
- message: "Hello!",
17
- name: "David"
18
- }.to_json do %>
19
- <% end %>
20
- ```
21
-
22
- This should produce the following HTML:
23
-
24
- ```html
25
- <div id="hello-vue" data="{&quot;message&quot;:&quot;Hello!&quot;,&quot;name&quot;:&quot;David&quot;}"></div>
26
- ```
27
-
28
- Now, modify your Vue app to expect the properties.
29
-
30
- ```html
31
- <template>
32
- <div id="app">
33
- <p>{{test}}{{message}}{{name}}</p>
34
- </div>
35
- </template>
36
-
37
- <script>
38
- export default {
39
- // A child component needs to explicitly declare
40
- // the props it expects to receive using the props option
41
- // See https://vuejs.org/v2/guide/components.html#Props
42
- props: ["message","name"],
43
- data: function () {
44
- return {
45
- test: 'This will display: '
46
- }
47
- }
48
- }
49
- </script>
50
-
51
- <style>
52
- </style>
53
-
54
- ```
55
-
56
- ```js
57
- document.addEventListener('DOMContentLoaded', () => {
58
- // Get the properties BEFORE the app is instantiated
59
- const node = document.getElementById('hello-vue')
60
- const props = JSON.parse(node.getAttribute('data'))
61
-
62
- // Render component with props
63
- new Vue({
64
- render: h => h(App, { props })
65
- }).$mount('#hello-vue');
66
- })
67
- ```
68
-
69
- You can follow same steps for Angular too.
70
-
71
-
72
- ## Elm
73
-
74
- Just like with other implementations, we'll render our data inside a `data`
75
- attribute:
76
-
77
- ```erb
78
- <%= content_tag :div,
79
- id: "hello-elm",
80
- data: {
81
- message: "Hello",
82
- name: "David"
83
- }.to_json do %>
84
- <% end %>
85
- ```
86
-
87
- We parse the JSON data and pass it to Elm as flags:
88
-
89
- ```js
90
- import Elm from '../Main'
91
-
92
- document.addEventListener('DOMContentLoaded', () => {
93
- const node = document.getElementById('hello-elm')
94
- const data = JSON.parse(node.getAttribute('data'))
95
- Elm.Main.embed(node, data)
96
- })
97
- ```
98
-
99
- Defining `Flags` as a `type alias`, we instruct Elm to demand flags `message`
100
- and `name` of type `String` on initialization.
101
-
102
- Using `programWithFlags` we bring all the pieces together:
103
-
104
-
105
- ```elm
106
- module Main exposing (..)
107
-
108
- import Html exposing (Html, programWithFlags, h1, text)
109
- import Html.Attributes exposing (style)
110
-
111
-
112
- -- MODEL
113
-
114
-
115
- type alias Flags =
116
- { message : String
117
- , name : String
118
- }
119
-
120
-
121
- type alias Model =
122
- { message : String
123
- , name : String
124
- }
125
-
126
-
127
- type Msg
128
- = NoOp
129
-
130
-
131
-
132
- -- INIT
133
-
134
-
135
- init : Flags -> ( Model, Cmd Msg )
136
- init flags =
137
- let
138
- { message, name } =
139
- flags
140
- in
141
- ( Model message name, Cmd.none )
142
-
143
-
144
-
145
- -- UPDATE
146
-
147
-
148
- update : Msg -> Model -> ( Model, Cmd Msg )
149
- update msg model =
150
- case msg of
151
- NoOp ->
152
- ( model, Cmd.none )
153
-
154
-
155
-
156
- -- SUBSCRIPTIONS
157
-
158
-
159
- subscriptions : Model -> Sub Msg
160
- subscriptions model =
161
- Sub.none
162
-
163
-
164
-
165
- -- VIEW
166
-
167
-
168
- view : Model -> Html Msg
169
- view model =
170
- h1 [ style [ ( "display", "flex" ), ( "justify-content", "center" ) ] ]
171
- [ text (model.message ++ ", " ++ model.name ++ "!") ]
172
-
173
-
174
-
175
- -- MAIN
176
-
177
-
178
- main : Program Flags Model Msg
179
- main =
180
- programWithFlags
181
- { view = view
182
- , init = init
183
- , update = update
184
- , subscriptions = subscriptions
185
- }
186
-
187
- ```
data/docs/react.md DELETED
@@ -1,183 +0,0 @@
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
-
data/docs/target.md DELETED
@@ -1,22 +0,0 @@
1
- # Target browsers
2
-
3
- By default webpacker provides these front-end tools:
4
- - [@babel/preset-env](https://github.com/babel/babel/tree/master/packages/babel-preset-env)
5
- - [Autoprefixer](https://github.com/postcss/autoprefixer)
6
- - [postcss-preset-env](https://github.com/csstools/postcss-preset-env)
7
-
8
- All these tools use [Browserslist](https://github.com/browserslist/browserslist) to detect which environment your users have
9
-
10
- Webpacker browserslist default target:
11
- ```
12
- defaults
13
- ```
14
-
15
- `defaults`: `(> 0.5%, last 2 versions, Firefox ESR, not dead)`, [browserl.ist](https://browserl.ist/) is an online tool to check what browsers will be selected by some query.
16
-
17
- To keep browsers data up to date, you need to run:
18
- ```bash
19
- yarn upgrade caniuse-lite
20
- ```
21
-
22
- at least once every few months, to prevent such [problems](https://github.com/browserslist/browserslist/issues/492)
data/docs/testing.md DELETED
@@ -1,147 +0,0 @@
1
- # Testing
2
-
3
- ## Karma setup for Typescript
4
-
5
- Webpacker does not setup `Karma` by default, so you've to manually install it along with its dependencies as per your need. Following things marked as optional can be used to fancify the test results (Recommended).
6
-
7
- ```js
8
- // package.json
9
- "scripts": {
10
- "test": "NODE_ENV=test karma start"
11
- },
12
- "dependencies": {
13
- "typescript": "^2.5.2"
14
- },
15
- "devDependencies": {
16
- "karma": "^1.7.1",
17
- "karma-webpack": "^2.0.4",
18
- "karma-chrome-launcher": "^2.2.0",
19
- "karma-jquery": "^0.2.2",
20
- "karma-jasmine": "^1.1.0",
21
- "karma-jasmine-jquery": "^0.1.1",
22
- "jasmine-core": "^2.8.0",
23
- [optional] "karma-coverage": "^1.1.1",
24
- [optional] "karma-coverage-istanbul-reporter": "^1.3.0",
25
- [optional] "karma-spec-reporter": "0.0.31",
26
- [optional] "istanbul-instrumenter-loader": "^3.0.0",
27
- }
28
- ```
29
-
30
- It is beneficial to use the same webpack configuration file (generated by webpacker) in Karma configuration to avoid redundancy. Following line tells Karma not to write transpiled source files onto filesystem while testing to avoid `Error: EACCES: permission denied, mkdir '/_karma_webpack_' ` error. Then inject a new rule a.k.a. loader in the existing ones (needed only if you have installed `istanbul-instrumenter-loader`) to generate a coverage report under `/coverage` directory.
31
-
32
- ```js
33
- // config/webpack/test.js
34
- const environment = require('./environment')
35
- environment.plugins.get('Manifest').options.writeToFileEmit = process.env.NODE_ENV !== 'test'
36
- environment.loaders.append('istanbul-instrumenter', {
37
- test: /\.ts$/,
38
- enforce: "post",
39
- loader: "istanbul-instrumenter-loader",
40
- query: {
41
- esModules: true
42
- },
43
- exclude: ["node_modules", /\.test\.ts$/]
44
- }) /* optional */
45
- module.exports = environment.toWebpackConfig()
46
- ```
47
-
48
- Finally, update `karma.conf.js` to read the same `test.js` file mentioned above. Rest of the things are mandatory (few marked as optional wherever appropriate).
49
-
50
- ```js
51
- // karma.conf.js
52
- const webpackConfig = require('./config/webpack/test.js')
53
- module.exports = function(config) {
54
- config.set({
55
- basePath: "",
56
- frameworks: ["jquery-3.2.1", "jasmine-jquery", "jasmine"],
57
- plugins: [
58
- "karma-jquery",
59
- "karma-jasmine-jquery",
60
- "karma-jasmine",
61
- "karma-webpack",
62
- "karma-chrome-launcher",
63
- "karma-coverage-istanbul-reporter" /* optional */,
64
- "karma-spec-reporter" /* optional */
65
- ],
66
- files: [ "/* add spec files */" ],
67
- exclude: [],
68
- webpack: webpackConfig,
69
- preprocessors: {"/* add spec files */" : ["webpack"]},
70
- mime: { "text/x-typescript": ["ts"] },
71
- reporters: ["progress", "coverage-istanbul" /* optional */],
72
- coverageIstanbulReporter: {
73
- reports: [ 'html', 'lcovonly', 'text-summary' ],
74
- fixWebpackSourcePaths: true
75
- } /* optional */,
76
- port: 9876,
77
- colors: true,
78
- logLevel: config.LOG_INFO,
79
- autoWatch: true,
80
- browsers: ["Chrome"],
81
- singleRun: true
82
- });
83
- };
84
- ```
85
-
86
- ## Lazy compilation
87
-
88
- Webpacker lazily compiles assets in test env so you can write your tests without any extra
89
- setup and everything will just work out of the box.
90
-
91
- Here is a sample system test case with hello_react example component:
92
-
93
- ```js
94
- // Example React component
95
-
96
- import React from 'react'
97
- import ReactDOM from 'react-dom'
98
- import PropTypes from 'prop-types'
99
-
100
- const Hello = props => (
101
- <div>Hello David</div>
102
- )
103
-
104
- document.addEventListener('DOMContentLoaded', () => {
105
- ReactDOM.render(
106
- <Hello />,
107
- document.body.appendChild(document.createElement('div')),
108
- )
109
- })
110
- ```
111
-
112
- ```erb
113
- <%# views/pages/home.html.erb %>
114
-
115
- <%= javascript_pack_tag "hello_react" %>
116
- ```
117
-
118
- ```rb
119
- # Tests example React component
120
- require "application_system_test_case"
121
- class HomesTest < ApplicationSystemTestCase
122
- test "can see the hello message" do
123
- visit root_url
124
- assert_selector "h5", text: "Hello! David"
125
- end
126
- end
127
- ```
128
-
129
- ## Capybara setup for Rails
130
- Make sure you configure Rails to serve static files from the public directory in the test environment.
131
-
132
- ```rb
133
- # config/environments/test.rb
134
- # Configure public file server for tests with Cache-Control for performance.
135
- config.public_file_server.enabled = true
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)