webpacker 2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +21 -21
  4. data/CHANGELOG.md +107 -4
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +15 -8
  7. data/README.md +137 -937
  8. data/docs/assets.md +106 -0
  9. data/docs/css.md +82 -0
  10. data/docs/deployment.md +39 -0
  11. data/docs/env.md +62 -0
  12. data/docs/es6.md +53 -0
  13. data/docs/folder-structure.md +66 -0
  14. data/docs/misc.md +23 -0
  15. data/docs/props.md +105 -0
  16. data/docs/testing.md +45 -0
  17. data/docs/troubleshooting.md +65 -0
  18. data/docs/typescript.md +115 -0
  19. data/docs/webpack-dev-server.md +32 -0
  20. data/docs/webpack.md +108 -0
  21. data/docs/yarn.md +12 -0
  22. data/lib/install/angular.rb +4 -7
  23. data/lib/install/bin/webpack-dev-server.tt +35 -11
  24. data/lib/install/bin/webpack.tt +3 -4
  25. data/lib/install/config/.babelrc +1 -0
  26. data/lib/install/config/.postcssrc.yml +1 -2
  27. data/lib/install/config/webpack/development.js +2 -31
  28. data/lib/install/config/webpack/environment.js +3 -0
  29. data/lib/install/config/webpack/production.js +2 -34
  30. data/lib/install/config/webpack/test.js +2 -5
  31. data/lib/install/config/webpacker.yml +20 -2
  32. data/lib/install/elm.rb +6 -11
  33. data/lib/install/examples/vue/hello_vue.js +31 -2
  34. data/lib/install/react.rb +2 -5
  35. data/lib/install/template.rb +3 -8
  36. data/lib/install/vue.rb +4 -7
  37. data/lib/tasks/webpacker.rake +1 -1
  38. data/lib/tasks/webpacker/{check_webpack_binstubs.rake → check_binstubs.rake} +3 -2
  39. data/lib/tasks/webpacker/check_node.rake +8 -6
  40. data/lib/tasks/webpacker/check_yarn.rake +2 -2
  41. data/lib/tasks/webpacker/clobber.rake +2 -3
  42. data/lib/tasks/webpacker/compile.rake +16 -18
  43. data/lib/tasks/webpacker/verify_install.rake +5 -5
  44. data/lib/tasks/webpacker/yarn_install.rake +1 -1
  45. data/lib/webpacker.rb +15 -11
  46. data/lib/webpacker/commands.rb +22 -0
  47. data/lib/webpacker/compiler.rb +66 -10
  48. data/lib/webpacker/configuration.rb +54 -38
  49. data/lib/webpacker/dev_server.rb +47 -0
  50. data/lib/webpacker/dev_server_proxy.rb +24 -0
  51. data/lib/webpacker/helper.rb +23 -5
  52. data/lib/webpacker/instance.rb +44 -0
  53. data/lib/webpacker/manifest.rb +58 -34
  54. data/lib/webpacker/railtie.rb +22 -3
  55. data/lib/webpacker/version.rb +2 -1
  56. data/package.json +37 -7
  57. data/package/asset_host.js +21 -0
  58. data/package/config.js +8 -0
  59. data/package/environment.js +95 -0
  60. data/package/environments/development.js +47 -0
  61. data/package/environments/production.js +34 -0
  62. data/package/environments/test.js +3 -0
  63. data/package/index.js +16 -0
  64. data/package/loaders/babel.js +11 -0
  65. data/{lib/install/config/loaders/core → package/loaders}/coffee.js +0 -0
  66. data/{lib/install/config/loaders/installers → package/loaders}/elm.js +4 -5
  67. data/{lib/install/config/loaders/core → package/loaders}/erb.js +0 -0
  68. data/package/loaders/file.js +15 -0
  69. data/package/loaders/style.js +31 -0
  70. data/{lib/install/config/loaders/installers/angular.js → package/loaders/typescript.js} +1 -1
  71. data/package/loaders/vue.js +12 -0
  72. data/test/compiler_test.rb +20 -0
  73. data/test/configuration_test.rb +43 -19
  74. data/test/dev_server_test.rb +24 -0
  75. data/test/helper_test.rb +21 -5
  76. data/test/manifest_test.rb +25 -19
  77. data/test/test_app/public/packs/manifest.json +3 -1
  78. data/test/webpacker_test_helper.rb +40 -0
  79. data/webpacker.gemspec +1 -1
  80. data/yarn.lock +4701 -578
  81. metadata +52 -29
  82. data/lib/install/config/loaders/core/assets.js +0 -12
  83. data/lib/install/config/loaders/core/babel.js +0 -5
  84. data/lib/install/config/loaders/core/sass.js +0 -15
  85. data/lib/install/config/loaders/installers/react.js +0 -5
  86. data/lib/install/config/loaders/installers/vue.js +0 -13
  87. data/lib/install/config/webpack/configuration.js +0 -35
  88. data/lib/install/config/webpack/shared.js +0 -58
  89. data/lib/webpacker/env.rb +0 -23
  90. data/lib/webpacker/file_loader.rb +0 -24
  91. data/test/env_test.rb +0 -14
  92. data/test/webpacker_test.rb +0 -15
data/docs/testing.md ADDED
@@ -0,0 +1,45 @@
1
+ # Testing
2
+
3
+
4
+ ## Lazy compilation
5
+
6
+ Webpacker lazily compiles assets in test env so you can write your tests without any extra
7
+ setup and everything will just work out of the box.
8
+
9
+ Here is a sample system test case with hello_react example component:
10
+
11
+ ```js
12
+ // Example react component
13
+
14
+ import React from 'react'
15
+ import ReactDOM from 'react-dom'
16
+ import PropTypes from 'prop-types'
17
+
18
+ const Hello = props => (
19
+ <div>Hello David</div>
20
+ )
21
+
22
+ document.addEventListener('DOMContentLoaded', () => {
23
+ ReactDOM.render(
24
+ <Hello />,
25
+ document.body.appendChild(document.createElement('div')),
26
+ )
27
+ })
28
+ ```
29
+
30
+ ```erb
31
+ <%# views/pages/home.html.erb %>
32
+
33
+ <%= javascript_pack_tag "hello_react" %>
34
+ ```
35
+
36
+ ```rb
37
+ # Tests example react component
38
+ require "application_system_test_case"
39
+ class HomesTest < ApplicationSystemTestCase
40
+ test "can see the hello message" do
41
+ visit root_url
42
+ assert_selector "h5", text: "Hello! David"
43
+ end
44
+ end
45
+ ```
@@ -0,0 +1,65 @@
1
+ # Troubleshooting
2
+
3
+
4
+ ## ENOENT: no such file or directory - node-sass
5
+
6
+ * If you get this error `ENOENT: no such file or directory - node-sass` on Heroku
7
+ or elsewhere during `assets:precompile` or `bundle exec rails webpacker:compile`
8
+ then you would need to rebuild node-sass. It's a bit of a weird error;
9
+ basically, it can't find the `node-sass` binary.
10
+ An easy solution is to create a postinstall hook - `npm rebuild node-sass` in
11
+ `package.json` and that will ensure `node-sass` is rebuilt whenever
12
+ you install any new modules.
13
+
14
+
15
+ ## Can't find hello_react.js in manifest.json
16
+
17
+ * If you get this error `Can't find hello_react.js in manifest.json`
18
+ when loading a view in the browser it's because Webpack is still compiling packs.
19
+ Webpacker uses a `manifest.json` file to keep track of packs in all environments,
20
+ however since this file is generated after packs are compiled by webpack. So,
21
+ if you load a view in browser whilst webpack is compiling you will get this error.
22
+ Therefore, make sure webpack
23
+ (i.e `./bin/webpack-dev-server`) is running and has
24
+ completed the compilation successfully before loading a view.
25
+
26
+
27
+ ## throw er; // Unhandled 'error' event
28
+
29
+ * If you get this error while trying to use Elm, try rebuilding Elm. You can do
30
+ so with a postinstall hook in your `package.json`:
31
+
32
+ ```
33
+ "scripts": {
34
+ "postinstall": "npm rebuild elm"
35
+ }
36
+ ```
37
+
38
+
39
+ ## webpack or webpack-dev-server not found
40
+
41
+ * This could happen if `webpacker:install` step is skipped. Please run `bundle exec rails webpacker:install` to fix the issue.
42
+
43
+ * If you encounter the above error on heroku after upgrading from Rails 4.x to 5.1.x, then the problem might be related to missing `yarn` binstub. Please run following commands to update/add binstubs:
44
+
45
+ ```bash
46
+ bundle config --delete bin
47
+ ./bin/rails app:update:bin # or rails app:update:bin
48
+ ```
49
+
50
+
51
+ ## Running Webpack on Windows
52
+
53
+ If you are running Webpack on Windows, your command shell may not be able to interpret the preferred interpreter
54
+ for the scripts generated in `bin/webpack` and `bin/webpack-dev-server`. Instead you'll want to run the scripts
55
+ manually with Ruby:
56
+
57
+ ```
58
+ C:\path>ruby bin\webpack
59
+ C:\path>ruby bin\webpack-dev-server
60
+ ```
61
+
62
+
63
+ ## Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
64
+
65
+ If you receive this error when running `$ ./bin/webpack-dev-server` ensure your configuration is correct; most likely the path to your "packs" folder is incorrect if you modified from the original "source_path" defined in `config/webpacker.yml`.
@@ -0,0 +1,115 @@
1
+ # Typescript
2
+
3
+
4
+ ## Typescript with React
5
+
6
+ 1. Setup react using webpacker [react installer](#react). Then add required depedencies
7
+ for using typescript with React:
8
+
9
+ ```bash
10
+ yarn add ts-loader typescript @types/react @types/react-dom
11
+ ```
12
+
13
+ 2. Add a `tsconfig.json` to project root:
14
+
15
+ ``` json
16
+ {
17
+ "compilerOptions": {
18
+ "declaration": false,
19
+ "emitDecoratorMetadata": true,
20
+ "experimentalDecorators": true,
21
+ "lib": ["es6", "dom"],
22
+ "module": "es6",
23
+ "moduleResolution": "node",
24
+ "sourceMap": true,
25
+ "jsx": "react",
26
+ "target": "es5"
27
+ },
28
+ "exclude": [
29
+ "**/*.spec.ts",
30
+ "node_modules",
31
+ "public"
32
+ ],
33
+ "compileOnSave": false
34
+ }
35
+ ```
36
+
37
+ 3. Finally add `.tsx` to the list of extensions in `config/webpacker.yml`
38
+ and rename your generated `hello_react.js` using react installer
39
+ to `hello_react.tsx` and make it valid typescript and now you can use
40
+ typescript, JSX with React.
41
+
42
+
43
+
44
+ ## HTML templates with Typescript and Angular
45
+
46
+ After you have installed angular using `bundle exec rails webpacker:install:angular`
47
+ you would need to follow these steps to add HTML templates support:
48
+
49
+ 1. Use `yarn` to add html-loader
50
+
51
+ ```bash
52
+ yarn add html-loader
53
+ ```
54
+
55
+ 2. Add html-loader to `config/webpack/environment.js`
56
+
57
+ ```js
58
+ environment.loaders.add('html', {
59
+ test: /\.html$/,
60
+ use: [{
61
+ loader: 'html-loader',
62
+ options: {
63
+ minimize: true,
64
+ removeAttributeQuotes: false,
65
+ caseSensitive: true,
66
+ customAttrSurround: [ [/#/, /(?:)/], [/\*/, /(?:)/], [/\[?\(?/, /(?:)/] ],
67
+ customAttrAssign: [ /\)?\]?=/ ]
68
+ }
69
+ }]
70
+ })
71
+ ```
72
+
73
+ 3. Add `.html` to `config/webpacker.yml`
74
+
75
+ ```yml
76
+ extensions:
77
+ - .elm
78
+ - .coffee
79
+ - .html
80
+ ```
81
+
82
+ 4. Setup a custom `d.ts` definition
83
+
84
+ ```ts
85
+ // app/javascript/hello_angular/html.d.ts
86
+
87
+ declare module "*.html" {
88
+ const content: string
89
+ export default content
90
+ }
91
+ ```
92
+
93
+ 5. Add a template.html file relative to `app.component.ts`
94
+
95
+ ```html
96
+ <h1>Hello {{name}}</h1>
97
+ ```
98
+
99
+ 6. Import template into `app.component.ts`
100
+
101
+ ```ts
102
+ import { Component } from '@angular/core'
103
+ import templateString from './template.html'
104
+
105
+ @Component({
106
+ selector: 'hello-angular',
107
+ template: templateString
108
+ })
109
+
110
+ export class AppComponent {
111
+ name = 'Angular!'
112
+ }
113
+ ```
114
+
115
+ That's all. Voila!
@@ -0,0 +1,32 @@
1
+ # Webpack Dev Server
2
+
3
+
4
+ ## HTTPS
5
+
6
+ If you're using the `webpack-dev-server` in development, you can serve your packs over HTTPS
7
+ by setting the `https` option for `webpack-dev-server` to `true` in `config/webpacker.yml`,
8
+ then start the dev server as usual with `./bin/webpack-dev-server`.
9
+
10
+ Please note that the `webpack-dev-server` will use a self-signed certificate,
11
+ so your web browser will display a warning/exception upon accessing the page. If you get
12
+ `https://localhost:3035/sockjs-node/info?t=1503127986584 net::ERR_INSECURE_RESPONSE`
13
+ in your console, simply open the link in your browser and accept the SSL exception.
14
+ Now if you refresh your rails view everything should work as expected.
15
+
16
+
17
+ ## HOT module replacement
18
+
19
+ 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
+ Checkout this guide for more information:
23
+
24
+ - https://webpack.js.org/configuration/dev-server/#devserver-hot
25
+
26
+ To support HMR with React you would need to add `react-hot-loader`. Checkout this guide for
27
+ more information:
28
+
29
+ - https://gaearon.github.io/react-hot-loader/getstarted/
30
+
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.
data/docs/webpack.md ADDED
@@ -0,0 +1,108 @@
1
+ # Webpack
2
+
3
+
4
+ ## Configuration
5
+
6
+ Webpacker gives you a default set of configuration files for test, development and
7
+ production environments in `config/webpack/*.js`. You can configure each individual
8
+ environment in their respective files or configure them all in the base
9
+ `config/webpack/environment.js` file.
10
+
11
+ By default, you shouldn't have to make any changes to `config/webpack/*.js`
12
+ files since it's all standard production-ready configuration. However,
13
+ if you do need to customize or add a new loader, this is where you would go.
14
+
15
+
16
+ ## Loaders
17
+
18
+ You can add additional loaders beyond the base set that webpacker provides by
19
+ adding it to your environment. We'll use `json-loader` as an example:
20
+
21
+ ```
22
+ yarn add json-loader
23
+ ```
24
+
25
+ ```js
26
+ // config/webpack/environment.js
27
+ const { environment } = require('@rails/webpacker')
28
+
29
+ environment.loaders.add('json', {
30
+ test: /\.json$/,
31
+ use: 'json-loader'
32
+ })
33
+
34
+ module.exports = environment
35
+ ```
36
+
37
+ Finally add `.json` to the list of extensions in `config/webpacker.yml`. Now if you `import()` any `.json` files inside your javascript
38
+ they will be processed using `json-loader`. Voila!
39
+
40
+ You can also modify the loaders that webpacker pre-configures for you. We'll update
41
+ the `babel` loader as an example:
42
+
43
+ ```js
44
+ // config/webpack/environment.js
45
+ const { environment } = require('@rails/webpacker')
46
+
47
+ // Update an option directly
48
+ const babelLoader = environment.loaders.get('babel')
49
+ babelLoader.options.cacheDirectory = false
50
+
51
+ module.exports = environment
52
+ ```
53
+
54
+
55
+ ## Plugins
56
+
57
+ The process for adding or modifying webpack plugins is the same as the process
58
+ for loaders above:
59
+
60
+ ```js
61
+ // config/webpack/environment.js
62
+ const { environment } = require('@rails/webpacker')
63
+
64
+ // Get a pre-configured plugin
65
+ environment.plugins.get('ExtractText') // Is an ExtractTextPlugin instance
66
+
67
+ // Add an additional plugin of your choosing
68
+ environment.plugins.add('Fancy', new MyFancyWebpackPlugin)
69
+
70
+ module.exports = environment
71
+ ```
72
+
73
+
74
+ ### Add common chunks
75
+
76
+ 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.
77
+
78
+ Add the plugins in `config/webpack/environment.js`:
79
+
80
+ ```js
81
+ environment.plugins.add('CommonsChunkVendor', new webpack.optimize.CommonsChunkPlugin({
82
+ name: 'vendor',
83
+ minChunks: (module) => {
84
+ // this assumes your vendor imports exist in the node_modules directory
85
+ return module.context && module.context.indexOf('node_modules') !== -1;
86
+ }
87
+ }))
88
+
89
+ environment.plugins.add('CommonsChunkManifest', new webpack.optimize.CommonsChunkPlugin({
90
+ name: 'manifest',
91
+ minChunks: Infinity
92
+ }))
93
+ ```
94
+
95
+ Now, add these files to your `layouts/application.html.erb`:
96
+
97
+ ```erb
98
+ <%# Head %>
99
+
100
+ <%= javascript_pack_tag 'manifest' %>
101
+ <%= javascript_pack_tag 'vendor' %>
102
+
103
+ <%# If importing any styles from node_modules in your JS app %>
104
+
105
+ <%= stylesheet_pack_tag 'vendor' %>
106
+ ```
107
+
108
+ More detailed guides available here: [Webpack guides](https://webpack.js.org/guides/)
data/docs/yarn.md ADDED
@@ -0,0 +1,12 @@
1
+ # Yarn
2
+
3
+ Webpacker by default uses `yarn` as package manager for node modules
4
+
5
+
6
+ ## Add a new npm module
7
+
8
+ To add any new JS module you can use `yarn`:
9
+
10
+ ```bash
11
+ yarn add bootstrap material-ui
12
+ ```
@@ -1,13 +1,10 @@
1
1
  require "webpacker/configuration"
2
2
 
3
- puts "Copying angular loader to config/webpack/loaders"
4
- copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js"
3
+ puts "Copying angular example entry file to #{Webpacker.config.source_entry_path}"
4
+ copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker.config.source_entry_path}/hello_angular.js"
5
5
 
6
- puts "Copying angular example entry file to #{Webpacker::Configuration.entry_path}"
7
- copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker::Configuration.entry_path}/hello_angular.js"
8
-
9
- puts "Copying hello_angular app to #{Webpacker::Configuration.source_path}"
10
- directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker::Configuration.source_path}/hello_angular"
6
+ puts "Copying hello_angular app to #{Webpacker.config.source_path}"
7
+ directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker.config.source_path}/hello_angular"
11
8
 
12
9
  puts "Copying tsconfig.json to the Rails root directory for typescript"
13
10
  copy_file "#{__dir__}/examples/angular/tsconfig.json", "tsconfig.json"
@@ -3,6 +3,7 @@ $stdout.sync = true
3
3
 
4
4
  require "shellwords"
5
5
  require "yaml"
6
+ require "socket"
6
7
 
7
8
  ENV["RAILS_ENV"] ||= "development"
8
9
  RAILS_ENV = ENV["RAILS_ENV"]
@@ -13,7 +14,9 @@ NODE_ENV = ENV["NODE_ENV"]
13
14
  APP_PATH = File.expand_path("../", __dir__)
14
15
  CONFIG_FILE = File.join(APP_PATH, "config/webpacker.yml")
15
16
  NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
16
- WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/development.js")
17
+ WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js")
18
+
19
+ LISTEN_HOST_ADDR = NODE_ENV == 'development' ? 'localhost' : '0.0.0.0'
17
20
 
18
21
  def args(key)
19
22
  index = ARGV.index(key)
@@ -21,23 +24,44 @@ def args(key)
21
24
  end
22
25
 
23
26
  begin
24
- dev_server = YAML.load_file(CONFIG_FILE)["development"]["dev_server"]
27
+ dev_server = YAML.load_file(CONFIG_FILE)[RAILS_ENV]["dev_server"]
25
28
 
26
- DEV_SERVER_HOST = "http#{"s" if args('--https') || dev_server["https"]}://#{args('--host') || dev_server["host"]}:#{args('--port') || dev_server["port"]}"
29
+ HOSTNAME = args('--host') || dev_server["host"]
30
+ PORT = args('--port') || dev_server["port"]
31
+ HTTPS = ARGV.include?('--https') || dev_server["https"]
32
+ DEV_SERVER_ADDR = "http#{"s" if HTTPS}://#{HOSTNAME}:#{PORT}"
27
33
 
28
34
  rescue Errno::ENOENT, NoMethodError
29
- puts "Webpack dev_server configuration not found in #{CONFIG_FILE}."
30
- puts "Please run bundle exec rails webpacker:install to install webpacker"
35
+ $stdout.puts "Webpack dev_server configuration not found in #{CONFIG_FILE}."
36
+ $stdout.puts "Please run bundle exec rails webpacker:install to install webpacker"
37
+ exit!
38
+ end
39
+
40
+ begin
41
+ server = TCPServer.new(LISTEN_HOST_ADDR, PORT)
42
+ server.close
43
+
44
+ rescue Errno::EADDRINUSE
45
+ $stdout.puts "Another program is running on port #{PORT}. Set a new port in #{CONFIG_FILE} for dev_server"
31
46
  exit!
32
47
  end
33
48
 
34
- newenv = {
35
- "NODE_PATH" => NODE_MODULES_PATH.shellescape,
36
- "ASSET_HOST" => DEV_SERVER_HOST.shellescape
37
- }.freeze
49
+ # Delete supplied host and port CLI arguments
50
+ ["--host", "--port"].each do |arg|
51
+ ARGV.delete(args(arg))
52
+ ARGV.delete(arg)
53
+ end
54
+
55
+ env = { "NODE_PATH" => NODE_MODULES_PATH.shellescape }
38
56
 
39
- cmdline = ["yarn", "run", "webpack-dev-server", "--", "--progress", "--color", "--config", WEBPACK_CONFIG] + ARGV
57
+ cmd = [
58
+ "#{NODE_MODULES_PATH}/.bin/webpack-dev-server", "--progress", "--color",
59
+ "--config", WEBPACK_CONFIG,
60
+ "--host", LISTEN_HOST_ADDR,
61
+ "--public", "#{HOSTNAME}:#{PORT}",
62
+ "--port", PORT.to_s
63
+ ] + ARGV
40
64
 
41
65
  Dir.chdir(APP_PATH) do
42
- exec newenv, *cmdline
66
+ exec env, *cmd
43
67
  end