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/assets.md ADDED
@@ -0,0 +1,106 @@
1
+ # Assets
2
+
3
+
4
+ Static assets like images and fonts support is enabled out-of-box
5
+ and you can link them into your javascript app code and have them
6
+ compiled automatically.
7
+
8
+
9
+ ## Import from node modules
10
+
11
+ You can also import styles from `node_modules` using the following syntax.
12
+ Please note that your styles will always be extracted into `[pack_name].css`:
13
+
14
+ ```sass
15
+ // app/javascript/styles.sass
16
+ // ~ to tell webpack that this is not a relative import:
17
+
18
+ @import '~@material/animation/mdc-animation'
19
+ @import '~bootstrap/dist/css/bootstrap'
20
+ ```
21
+
22
+ ```js
23
+ // Your main app pack
24
+ // app/javascript/packs/app.js
25
+
26
+ import '../styles'
27
+ ```
28
+
29
+ ```erb
30
+ <%# In your views %>
31
+
32
+ <%= javascript_pack_tag 'app' %>
33
+ <%= stylesheet_pack_tag 'app' %>
34
+ ```
35
+
36
+
37
+ ## Import from sprockets using helpers
38
+
39
+ 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:
40
+
41
+ ```erb
42
+ <%# app/javascript/my_pack/example.js.erb %>
43
+
44
+ <% helpers = ActionController::Base.helpers %>
45
+ var railsImagePath = "<%= helpers.image_path('rails.png') %>"
46
+ ```
47
+
48
+ This is enabled by the `rails-erb-loader` loader rule in `config/webpack/loaders/erb.js`.
49
+
50
+
51
+ ## Using babel module resolver
52
+
53
+ You can also use [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver) to reference assets directly from `app/assets/**`
54
+
55
+ ```bash
56
+ yarn add babel-plugin-module-resolver
57
+ ```
58
+
59
+ Specify the plugin in your `.babelrc` with the custom root or alias. Here's an example:
60
+
61
+ ```json
62
+ {
63
+ "plugins": [
64
+ ["module-resolver", {
65
+ "root": ["./app"],
66
+ "alias": {
67
+ "assets": "./assets"
68
+ }
69
+ }]
70
+ ]
71
+ }
72
+ ```
73
+
74
+ And then within your javascript app code:
75
+
76
+ ```js
77
+ // Note: we don't have do any ../../ jazz
78
+
79
+ import FooImage from 'assets/images/foo-image.png'
80
+ import 'assets/stylesheets/bar'
81
+ ```
82
+
83
+
84
+ ## Link in your Rails views
85
+
86
+ You can also link `js/images/styles/fonts` used within your js app in views using
87
+ `asset_pack_path` helper. This helper is useful in cases where you just want to
88
+ create a `<link rel="prefetch">` or `<img />` for an asset.
89
+
90
+ ```yml
91
+ app/javascript:
92
+ - packs
93
+ - hello_react.js
94
+ - styles
95
+ - hello_react.css
96
+ - images
97
+ - calendar.png
98
+ ```
99
+
100
+ ```erb
101
+ <%= asset_pack_path 'hello_react.css' %>
102
+ <%# => "/packs/hello_react.css" %>
103
+
104
+ <img src="<%= asset_pack_path 'images/calendar.png' %>" />
105
+ <% # => <img src="/packs/images/calendar.png" /> %>
106
+ ```
data/docs/css.md ADDED
@@ -0,0 +1,82 @@
1
+ # CSS, SASS and SCSS
2
+
3
+
4
+ Webpacker supports importing css, sass and scss files directly into your javascript files.
5
+
6
+
7
+ ## Import styles into your JS app
8
+
9
+ ```sass
10
+ // app/javascript/hello_react/styles/hello-react.sass
11
+
12
+ .hello-react
13
+ padding: 20px
14
+ font-size: 12px
15
+ ```
16
+
17
+ ```js
18
+ // React component example
19
+ // app/javascripts/packs/hello_react.jsx
20
+
21
+ import React from 'react'
22
+ import helloIcon from '../hello_react/images/icon.png'
23
+ import '../hello_react/styles/hello-react'
24
+
25
+ const Hello = props => (
26
+ <div className="hello-react">
27
+ <img src={helloIcon} alt="hello-icon" />
28
+ <p>Hello {props.name}!</p>
29
+ </div>
30
+ )
31
+ ```
32
+
33
+
34
+ ## Link styles from your Rails views
35
+
36
+ Under the hood webpack uses
37
+ [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
38
+ a separate `[pack_name].css` bundle so that in your view you can use the
39
+ `stylesheet_pack_tag` helper.
40
+
41
+ ```erb
42
+ <%= stylesheet_pack_tag 'hello_react' %>
43
+ ```
44
+
45
+
46
+ ## Add bootstrap
47
+
48
+ You can use yarn to add bootstrap or any other modules available on npm:
49
+
50
+ ```bash
51
+ yarn add bootstrap
52
+ ```
53
+
54
+ Import Bootstrap and theme (optional) CSS in your app/javascript/packs/app.js file:
55
+
56
+ ```js
57
+ import 'bootstrap/dist/css/bootstrap'
58
+ import 'bootstrap/dist/css/bootstrap-theme'
59
+ ```
60
+
61
+ Or in your app/javascript/app.sass file:
62
+
63
+ ```sass
64
+ // ~ to tell that this is not a relative import
65
+
66
+ @import '~bootstrap/dist/css/bootstrap'
67
+ @import '~bootstrap/dist/css/bootstrap-theme'
68
+ ```
69
+
70
+
71
+ ## Post-Processing CSS
72
+
73
+ Webpacker out-of-the-box provides CSS post-processing using
74
+ [postcss-loader](https://github.com/postcss/postcss-loader)
75
+ and the installer sets up a standard `.postcssrc.yml`
76
+ file in your app root with standard plugins.
77
+
78
+ ```yml
79
+ plugins:
80
+ postcss-smart-import: {}
81
+ postcss-cssnext: {}
82
+ ```
@@ -0,0 +1,39 @@
1
+ # Deployment
2
+
3
+
4
+ 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
5
+ can manually trigger `bundle exec rails webpacker:compile` during your app deploy.
6
+
7
+ 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.
8
+
9
+ By default the output will look like this in different environments:
10
+
11
+ ```html
12
+ <!-- In development mode -->
13
+ <script src="/packs/calendar.js"></script>
14
+ <link rel="stylesheet" media="screen" href="/packs/calendar.css">
15
+ <!-- In development mode with webpack-dev-server -->
16
+ <script src="http://localhost:8080/calendar.js"></script>
17
+ <link rel="stylesheet" media="screen" href="http://localhost:8080/calendar.css">
18
+ <!-- In production mode -->
19
+ <script src="/packs/calendar-0bd141f6d9360cf4a7f5.js"></script>
20
+ <link rel="stylesheet" media="screen" href="/packs/calendar-dc02976b5f94b507e3b6.css">
21
+ ```
22
+
23
+
24
+ ## Heroku
25
+
26
+ Heroku installs yarn and node by default if you deploy a rails app with
27
+ Webpacker so all you would need to do:
28
+
29
+ ```bash
30
+ heroku create shiny-webpacker-app
31
+ heroku addons:create heroku-postgresql:hobby-dev
32
+ git push heroku master
33
+ ```
34
+
35
+
36
+ ## CDN
37
+
38
+ 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
39
+ you don't need to do anything extra for webpacker, it just works.
data/docs/env.md ADDED
@@ -0,0 +1,62 @@
1
+ # Environment variables
2
+
3
+
4
+ Environment variables are supported out of the box in Webpacker. For example if
5
+ you run the Webpack dev server like so:
6
+ ```
7
+ FOO=hello BAR=world ./bin/webpack-dev-server
8
+ ```
9
+
10
+ You can then reference these variables in your javascript app code with
11
+ `process.env`:
12
+
13
+ ```js
14
+ console.log(process.env.FOO) // Compiles to console.log("hello")
15
+ ```
16
+
17
+ You may want to store configuration in environment variables via `.env` files,
18
+ similar to the [dotenv Ruby gem](https://github.com/bkeepers/dotenv).
19
+
20
+ In development, if you use Foreman or [Invoker](http://invoker.codemancers.com)
21
+ to launch the Webpack server, both of these tools have basic support for a
22
+ `.env` file (Invoker also supports `.env.local`), so no further configuration
23
+ is needed.
24
+
25
+ However, if you run the Webpack server without Foreman/Invoker, or if you
26
+ want more control over what `.env` files to load, you can use the
27
+ [dotenv npm package](https://github.com/motdotla/dotenv). Here is what you could
28
+ do to support a "Ruby-like" dotenv:
29
+
30
+ ```
31
+ yarn add dotenv
32
+ ```
33
+
34
+ ```javascript
35
+ // config/webpack/environment.js
36
+
37
+ ...
38
+ const dotenv = require('dotenv');
39
+
40
+ const dotenvFiles = [
41
+ `.env.${process.env.NODE_ENV}.local`,
42
+ '.env.local',
43
+ `.env.${process.env.NODE_ENV}`,
44
+ '.env'
45
+ ];
46
+ dotenvFiles.forEach((dotenvFile) => {
47
+ dotenv.config({ path: dotenvFile, silent: true });
48
+ });
49
+
50
+ module.exports = {
51
+ ...
52
+ ```
53
+
54
+ **Warning:** using Foreman/Invoker and npm dotenv at the same time can result in
55
+ confusing behavior, in that Foreman/Invoker variables take precedence over
56
+ npm dotenv variables.
57
+
58
+ If you'd like to pass custom variables to the on demand compiler, use `Webpack::Compiler.env` attribute.
59
+
60
+ ```rb
61
+ Webpacker::Compiler.env['FRONTEND_API_KEY'] = 'your_secret_key'
62
+ ```
data/docs/es6.md ADDED
@@ -0,0 +1,53 @@
1
+ # ES6
2
+
3
+
4
+ ## Babel
5
+
6
+ Webpacker ships with [babel](https://babeljs.io/) - a JavaScript compiler so
7
+ you can use next generation JavaScript, today. The Webpacker installer sets up a
8
+ standard `.babelrc` file in your app root, which will work great in most cases
9
+ because of [babel-env-preset](https://github.com/babel/babel-preset-env).
10
+
11
+ Following ES6/7 features are supported out of the box:
12
+
13
+ * Async/await.
14
+ * Object Rest/Spread Properties.
15
+ * Exponentiation Operator.
16
+ * Dynamic import() - useful for route level code-splitting
17
+ * Class Fields and Static Properties.
18
+
19
+ We have also included [babel polyfill](https://babeljs.io/docs/usage/polyfill/)
20
+ that includes a custom regenerator runtime and core-js.
21
+
22
+ Don't forget to import `babel-polyfill` in your main entry point like so:
23
+
24
+ ```js
25
+ import "babel-polyfill"
26
+ ```
27
+
28
+
29
+ ## Module import() vs require()
30
+
31
+ While you are free to use `require()` and `module.exports`, we encourage you
32
+ to use `import` and `export` instead since it reads and looks much better.
33
+
34
+ ```js
35
+ import Button from 'react-bootstrap/lib/Button'
36
+
37
+ // or
38
+ import { Button } from 'react-bootstrap'
39
+
40
+ class Foo {
41
+ // code...
42
+ }
43
+
44
+ export default Foo
45
+ import Foo from './foo'
46
+ ```
47
+
48
+ You can also use named export and import
49
+
50
+ ```js
51
+ export const foo = () => console.log('hello world')
52
+ import { foo } from './foo'
53
+ ```
@@ -0,0 +1,66 @@
1
+ # Folder Structure
2
+
3
+
4
+ ## Packs a.k.a Webpack entries
5
+
6
+ "Packs" is a special directory made only for Webpack entry files so don't put anything
7
+ here that you don't want to link in your views.
8
+
9
+
10
+ ## Source
11
+
12
+ You can put your app source under `app/javascript` folder or whatever you have configured
13
+ in `config/webpacker.yml`.
14
+
15
+
16
+ ## Example
17
+
18
+ Let's say you're building a calendar app. Your JS app structure could look like this:
19
+
20
+ ```js
21
+ // app/javascript/packs/calendar.js
22
+
23
+ import 'calendar'
24
+ ```
25
+
26
+ ```
27
+ app/javascript/calendar/index.js // gets loaded by import 'calendar'
28
+ app/javascript/calendar/components/grid.jsx
29
+ app/javascript/calendar/styles/grid.sass
30
+ app/javascript/calendar/models/month.js
31
+ ```
32
+
33
+ ```erb
34
+ <%# app/views/layouts/application.html.erb %>
35
+
36
+ <%= javascript_pack_tag 'calendar' %>
37
+ <%= stylesheet_pack_tag 'calendar' %>
38
+ ```
39
+
40
+ But it could also look a million other ways.
41
+
42
+
43
+ ## Namespacing
44
+
45
+ You can also namespace your packs using directories similar to a Rails app.
46
+
47
+ ```
48
+ app/javascript/packs/admin/orders.js
49
+ app/javascript/packs/shop/orders.js
50
+ ```
51
+
52
+ and reference them in your views like this:
53
+
54
+ ```erb
55
+ <%# app/views/admin/orders/index.html.erb %>
56
+
57
+ <%= javascript_pack_tag 'admin/orders' %>
58
+ ```
59
+
60
+ and
61
+
62
+ ```erb
63
+ <%# app/views/shop/orders/index.html.erb %>
64
+
65
+ <%= javascript_pack_tag 'shop/orders' %>
66
+ ```
data/docs/misc.md ADDED
@@ -0,0 +1,23 @@
1
+ # How-Tos
2
+
3
+
4
+ ## Ignoring swap files
5
+
6
+ If you are using vim or emacs and want to ignore certain files you can add `ignore-loader`:
7
+
8
+ ```
9
+ yarn add ignore-loader
10
+ ```
11
+
12
+ and add `ignore-loader` to `config/webpack/environment.js`
13
+
14
+ ```js
15
+ // ignores vue~ swap files
16
+ const { environment } = require('@rails/webpacker')
17
+ environment.loaders.add('ignore', {
18
+ test: /.vue~$/,
19
+ loader: 'ignore-loader'
20
+ })
21
+ ```
22
+
23
+ And now all files with `.vue~` will be ignored by the webpack compiler.
data/docs/props.md ADDED
@@ -0,0 +1,105 @@
1
+ # Props
2
+
3
+
4
+ ## 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
+
43
+
44
+ ## Vue
45
+
46
+ Add the data as attributes in the element you are going to use (or any other element for that matter).
47
+
48
+ ```erb
49
+ <%= content_tag :div,
50
+ id: "hello-vue",
51
+ data: {
52
+ message: "Hello!",
53
+ name: "David"
54
+ }.to_json do %>
55
+ <% end %>
56
+ ```
57
+
58
+ This should produce the following HTML:
59
+
60
+ ```html
61
+ <div id="hello-vue" data="{&quot;message&quot;:&quot;Hello!&quot;,&quot;name&quot;:&quot;David&quot;}"></div>
62
+ ```
63
+
64
+ Now, modify your Vue app to expect the properties.
65
+
66
+ ```html
67
+ <template>
68
+ <div id="app">
69
+ <p>{{test}}{{message}}{{name}}</p>
70
+ </div>
71
+ </template>
72
+
73
+ <script>
74
+ export default {
75
+ // A child component needs to explicitly declare
76
+ // the props it expects to receive using the props option
77
+ // See https://vuejs.org/v2/guide/components.html#Props
78
+ props: ["message","name"],
79
+ data: function () {
80
+ return {
81
+ test: 'This will display: ',
82
+ }
83
+ }
84
+ }
85
+ </script>
86
+
87
+ <style>
88
+ </style>
89
+
90
+ ```
91
+
92
+ ```js
93
+ document.addEventListener('DOMContentLoaded', () => {
94
+ // Get the properties BEFORE the app is instantiated
95
+ const node = document.getElementById('hello-vue')
96
+ const props = JSON.parse(node.getAttribute('data'))
97
+
98
+ // Render component with props
99
+ new Vue({
100
+ render: h => h(App, { props })
101
+ }).$mount('#hello-vue');
102
+ })
103
+ ```
104
+
105
+ You can follow same steps for Angular too.