vue_cli-rails 0.2.0 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a7ee2779059b83202b6057251b245a50fc3b0e7a803c0a61e113da7aa6b10d1
4
- data.tar.gz: 8bde5723e1263ec2f0a0063e78c8f7467effe82a661dd6910fc020275b3776fb
3
+ metadata.gz: e23e30ec06f2e4f661258507ac78cca3ee9b9e2f583fac001b231cfc0194d00f
4
+ data.tar.gz: 4fe54577949add5a0739a612bf501ef667c1ac7b3964c0c9e7423f1019d0a46a
5
5
  SHA512:
6
- metadata.gz: 6b244978b9ca71bd0fff983c1f45db81ed07aee91664830fa53a65ba8e85b98d18479736ad4208979d52e67bff54fcdf389a333e09143e312c7f4684c4076a5b
7
- data.tar.gz: 30adca9ac7ec73732568e9865666c1035298828893cdecf8c4f92fd14e71d8993ad7638385c428eefc043645e43c37a6543a07da4aaa1b59f0c1349346388298
6
+ metadata.gz: e866c1167152e328b6b1d750dfabcc88ecf495342d493153e319bd2309d85e6554b2d92bae1a95c7545c65631415486765f14e965505f56f10d3de71f4a10a8c
7
+ data.tar.gz: d9178061fe4134ab393c386cafd3530aa7fa2e7d3f3d7d485f540fb539f000b87fca2c7b542919e98a7002efaef1f870d6e265113893f25e8b6a0d7352af3747
data/README.md CHANGED
@@ -28,9 +28,12 @@ And then execute:
28
28
  - Feel free to use `yarn` or `npm`.
29
29
  - Single `vue_entry` rather than confusing `stylesheet_pack_tag`, `javascript_packs_tag` and `javascript_packs_with_chunks_tag`.
30
30
  - Get all benefits of [@vue/cli](https://cli.vuejs.org/).
31
- - Powered by `webpack` 4
32
- - DRY: all-in-one configuration file rather than repeating for `webpack`, `eslint` and etc.
33
- - Out-of-box tooling: Babel, TypeScript, PWA, `vue-router`, `vuex`, CSS pre-processors, linter and testing tools.
31
+
32
+ - Powered by `webpack` 4
33
+ - DRY: all-in-one configuration file rather than repeating for `webpack`, `eslint` and etc.
34
+ - Out-of-box tooling: Babel, TypeScript, PWA, `vue-router`, `vuex`, CSS pre-processors, linter and testing tools.
35
+ - Enhanced alias support in `jest.config.js`.
36
+
34
37
  - Run `webpack-dev-server` together with Rails server with development mode.
35
38
  - Just single `RAILS_ENV`, no more `NODE_ENV`.
36
39
  - Rails way configurations in `config/vue.yml`.
@@ -40,9 +43,13 @@ And then execute:
40
43
  Out-of-box workflow:
41
44
 
42
45
  1. `bundle exec rake vue:create` and follow the steps.
43
- 2. Put your entry point files under `app/assets/vue/views`.
44
- 3. `webpack-dev-server` auto starts alongside `rails server` in dev mode.
45
- 4. Invoke `bundle exec rake vue:compile` to compile assets (you still have to set `RAILS_ENV=production` manually).
46
+
47
+ > Don NOT select `In package.json` for "Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?". Some functionalities like alias of jest may not work.
48
+
49
+ 2. Put your JavaScript files under `app/assets/vue/entry_points`.
50
+ 3. Insert your entry point by `vue_entry 'entry_point'` in views or `render_vue 'entry_point'` in controllers.
51
+ 4. `webpack-dev-server` auto starts alongside `rails server` in dev mode.
52
+ 5. Invoke `env RAILS_ENV=production bundle exec rake vue:compile` to compile assets (you still must manually set `RAILS_ENV` to `production`).
46
53
 
47
54
  > More settings are available in `config/vue.yml`
48
55
 
@@ -52,9 +59,11 @@ Out-of-box workflow:
52
59
 
53
60
  #### Concept: Entry Point and File structure
54
61
 
55
- Webpack sees JavaScript files as the center of page rather than HTML. Thus all styles, images, fonts and other assets are related to a JS files. Any `.js` files under `app/assets/vue/views` will be treated as entry-point files.
62
+ The root path of your Vue assets is `app/assets/vue`. This gem will generate several folders. However, `app/assets/vue/entry_points` is the only one matters.
56
63
 
57
- Please ONLY puts your entry-point files under `app/assets/vue/views` folder with `.js` extension name.
64
+ Webpack sees one JavaScript file as the center of a web page rather than HTML. Thus all styles, images, fonts and other assets are related to a JS files by `import 'css/png/svg/woff2/json'`. Any `.js` file under `app/assets/vue/entry_points` will be a entry-point.
65
+
66
+ Please ONLY puts your entry-point files under `app/assets/vue/entry_points` folder with `.js` extension name.
58
67
 
59
68
  > Be aware, `.js.erb` and `.vue.erb` are NOT supported. I will explain the reason in [Q&A section](#difference-from-webpacker).
60
69
 
@@ -62,7 +71,7 @@ If you are new to modern front-end development, or more specifically with `webpa
62
71
 
63
72
  #### Helper `vue_entry`
64
73
 
65
- `vue_entry` is like `javascript_include_tag` and `stylesheet_link_tag` which generates relative assets links for your entry point. (It's like a combination of `stylesheet_pack_tag` and `javascript_packs_with_chunks_tag` in Webpacker 4. I will explain why it's different in [Q&A](#qa).)
74
+ `vue_entry` is like `javascript_include_tag` and `stylesheet_link_tag` which generates relative assets links for your entry point. (It's like `javascript_packs_with_chunks_tag` in Webpacker 4. I will explain why it's different in [Q&A](#qa).)
66
75
 
67
76
  > You may have interest of path alias in `config/vue.yml`.
68
77
 
@@ -74,12 +83,11 @@ If you are new to modern front-end development, or more specifically with `webpa
74
83
  [+] app
75
84
  [+] assets
76
85
  [+] vue
77
- [+] components
78
- [+] views - alias `~views`
79
- [-] FooBar.vue - Vue component for `foo/bar`
80
- [+] views - Folder for entry points
86
+ [+] entry_points - Folder for entry points
81
87
  [+] foo
82
88
  [-] bar.js - entry point: import '~views/FooBar.vue'
89
+ [+] views - alias `~views`
90
+ [-] FooBar.vue - Vue component for `foo/bar`
83
91
  [+] controllers
84
92
  [+] foo_controller.rb - controller
85
93
  [+] views
@@ -94,7 +102,7 @@ If you are new to modern front-end development, or more specifically with `webpa
94
102
  ```yaml
95
103
  # default
96
104
  alias:
97
- ~views: app/assets/vue/components/views
105
+ ~views: app/assets/vue/views
98
106
  ```
99
107
 
100
108
  - Your controller:
@@ -117,7 +125,7 @@ If you are new to modern front-end development, or more specifically with `webpa
117
125
  - Entry point JS:
118
126
 
119
127
  ```js
120
- // file - app/assets/vue/views/foo/bar.js
128
+ // file - app/assets/vue/entry_points/foo/bar.js
121
129
  import Vue from 'vue';
122
130
 
123
131
  import Foo from '~views/FooBar.vue';
@@ -130,7 +138,7 @@ If you are new to modern front-end development, or more specifically with `webpa
130
138
  - Your Vue component for your entry point:
131
139
 
132
140
  ```vue
133
- // file - app/assets/vue/components/views/FooBar.vue
141
+ // file - app/assets/vue/views/FooBar.vue
134
142
  <template>
135
143
  <div id="foo-bar">
136
144
  <h1>Foo/bar</h1>
@@ -168,6 +176,55 @@ If you are new to modern front-end development, or more specifically with `webpa
168
176
 
169
177
  </details>
170
178
 
179
+ #### Use `render_vue` in controllers
180
+
181
+ Usually you only need `<div id="app"></div>` and `vue_entry 'entry/point'` to render a Vue page. You can use `render_vue 'entry/point'` inside your controller.
182
+
183
+ This method is simply a wrap of `render html: vue_entry('entry_point'), layout: true`. So you can pass any arguments supported by `render` including `layout`.
184
+
185
+ <details><summary>For example</summary>
186
+
187
+ ```ruby
188
+ # app/controllers/my_vue_controller
189
+ class MyVueController < ApplicationController
190
+ layout 'vue_base'
191
+
192
+ def foo
193
+ render_vue 'foo/bar'
194
+ end
195
+ end
196
+ ```
197
+
198
+ ```html
199
+ <!-- app/views/layouts/vue_base.erb -->
200
+ <!DOCTYPE html>
201
+ <html>
202
+ <head>
203
+ <title>My Vue</title>
204
+ </head>
205
+ <body>
206
+ <div id="app"></div>
207
+ <%= yield %>
208
+ </body>
209
+ </html>
210
+ ```
211
+
212
+ ```js
213
+ // app/assets/vue/entry_points/foo/bar.js
214
+
215
+ import Vue from 'vue';
216
+
217
+ import Bar from '../views/Bar.vue';
218
+
219
+ Vue.config.productionTip = false;
220
+
221
+ new Vue({
222
+ render: h => h(Bar),
223
+ }).$mount('#app');
224
+ ```
225
+
226
+ </details>
227
+
171
228
  #### Public Output Path
172
229
 
173
230
  If the default setting `vue_assets` does not bother you at all, you can ignore this section.
@@ -192,13 +249,19 @@ Actually `public_output_path` in `config/vue.yml` is very simple - just a sub pa
192
249
 
193
250
  </details>
194
251
 
252
+ #### Summary
253
+
254
+ If you still feel confusing, please create a new project and select copy demo code.
255
+
256
+ I will explain what happens in [Explanation by Demo](#explanation-by-demo).
257
+
195
258
  ### Available Settings
196
259
 
197
260
  #### General settings file is `config/vue.yml`
198
261
 
199
262
  - `manifest_output`
200
263
 
201
- Where to put `manifest.json` which required by Rails.
264
+ Where to put `manifest.json` which required by Rails production mode. You can set it in development mode for inspection.
202
265
 
203
266
  All entry-points will be compiled into assets files. Rails needs `manifest.json` to know what are the files and will serve all its JS/CSS tags.
204
267
 
@@ -218,9 +281,13 @@ Actually `public_output_path` in `config/vue.yml` is very simple - just a sub pa
218
281
 
219
282
  Please see [available options](#valid-vue-cli-config-options).
220
283
 
284
+ - `alias`
285
+
286
+ It's basically `resolve/alias` for Webpack. However, you don't have to config this settings in `.eslintrc.js` and `jest.config.js` again and again. `@vue/cli` will pass the settings to eslint via its plugin. The configuration for jest will be generated and passed to `jest.config.js` through `vue.rails.js`.
287
+
221
288
  #### Customize your webpack configurations in `vue.config.js`
222
289
 
223
- Feel free update `vue.config.js` by yourself. There are some lines of boiler-plate code to adapt `compression-webpack-plugin` and `webpack-bundle-analyzer`.
290
+ Feel free to update `vue.config.js` by yourself. There are some lines of boiler-plate code to adapt `compression-webpack-plugin` and `webpack-bundle-analyzer`.
224
291
 
225
292
  ### Rake Tasks
226
293
 
@@ -313,7 +380,7 @@ Feel free update `vue.config.js` by yourself. There are some lines of boiler-pla
313
380
  }
314
381
  ```
315
382
 
316
- > You may need to invoke with `bundle exec`. Rails 5 and above supports new `rails rake:task` flavor.
383
+ > You may need to invoke `rake` with `bundle exec`. Rails 5 and above supports new `rails rake:task` flavor.
317
384
 
318
385
  ## Valid Vue CLI config Options
319
386
 
@@ -505,3 +572,173 @@ Sorry, I don't think many gems work on Windows. Please install a virtual machine
505
572
  Currently `vue.config.js` is reading configurations from `vue.rails.js` which depends on `js-yaml`. It will fallback to `bundle exec rake vue:json_config` without `js-yaml` installed. You may suffer performance issue if your rake tasks are slow.
506
573
 
507
574
  </details>
575
+
576
+ ## Explanation by Demo
577
+
578
+ <!-- <details><summary>Explanation by Demo</summary> -->
579
+
580
+ ### Install
581
+
582
+ Run `bundle exec rake vue:create` or `rails vue:create` in Rails 5+, and follow the steps:
583
+
584
+ ```
585
+ $ bundle exec rake vue:create
586
+ Which package manager to use? (Y=yarn, N=npm) [Yn]
587
+ ...
588
+ ? Generate project in current directory? Yes
589
+ ...
590
+ ? Check the features needed for your project: Babel, Linter, Unit
591
+ ? Pick a linter / formatter config: Airbnb
592
+ ? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
593
+ ? Pick a unit testing solution: Jest
594
+ ? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
595
+ ...
596
+ Do you want to copy demo code? (Y=Yes, N=No) [yN]y
597
+ ...
598
+ ```
599
+
600
+ ### First Taste
601
+
602
+ Now with `rails s`, open `http://localhost:3000/vue_demo/foo` in a browser you should be able to see a red big red "Foo" with blue "Hello Vue!".
603
+
604
+ Do not stop your rails server, open `app/assets/vue/views/Foo.vue` in your editor:
605
+
606
+ ```diff
607
+ <template>
608
+ <div id="app">
609
+ <h1>Foo</h1>
610
+ - <HelloWorld msg="Vue!"></HelloWorld>
611
+ + <HelloWorld msg="Rails!"></HelloWorld>
612
+ </div>
613
+ </template>
614
+ ```
615
+
616
+ Change `msg="Vue!"` to `msg="Rails!"` and save. You will the text in your browser changed to "Hello Rails!". You can change styles or edit `app/assets/vue/components/HelloWorld.vue` and immediately see the result as well.
617
+
618
+ This functionality is called [HMR (Hot Module Replacement)](https://webpack.js.org/concepts/hot-module-replacement/) which is the killing feature provided by webpack-dev-server. You will soon fail in love with this feature and never want to go back to manually refresh your browser again and again.
619
+
620
+ ### What in the box
621
+
622
+ ```
623
+ .
624
+ ├── app
625
+ │   ├── assets
626
+ │   │   └── vue
627
+ │   │   ├── components
628
+ │   │   │   ├── HelloWorld.vue
629
+ │   │   │   └── layouts
630
+ │   │   │   ├── App.vue
631
+ │   │   │   └── index.js
632
+ │   │   ├── entry_points
633
+ │   │   │   ├── bar.js
634
+ │   │   │   └── foo.js
635
+ │   │   └── views
636
+ │   │   ├── Bar.vue
637
+ │   │   └── Foo.vue
638
+ │   ├── controllers
639
+ │   │   └── vue_demo_controller.rb
640
+ │   └── views
641
+ │   ├── layouts
642
+ │   │   └── vue_demo.html.erb
643
+ │   └── vue_demo
644
+ │   └── foo.html.erb
645
+ ├── config
646
+ │   ├── routes.rb
647
+ │   └── vue.yml
648
+ ├── tests
649
+ │   └── unit
650
+ │   └── example.spec.js
651
+ ├── .browserslistrc
652
+ ├── .editorconfig
653
+ ├── .eslintrc.js
654
+ ├── .gitignore
655
+ ├── babel.config.js
656
+ ├── jest.config.js
657
+ ├── package.json
658
+ ├── postcss.config.js
659
+ ├── vue.config.js
660
+ ├── vue.rails.js
661
+ └── yarn.lock
662
+ ```
663
+
664
+ You can run ESLint by
665
+
666
+ $ yarn lint
667
+
668
+ Run Jest
669
+
670
+ $ yarn test:unit
671
+
672
+ ### Compile Assets
673
+
674
+ First let's compile the assets
675
+
676
+ ```
677
+ $ env RAILS_ENV=production bundle exec rake vue:compile
678
+ run: yarn exec vue-cli-service build
679
+ ...
680
+ File Size Gzipped
681
+
682
+ public/vue_assets/js/chunk-vendors.b54 82.49 KiB 29.80 KiB
683
+ 85759.js
684
+ public/vue_assets/js/foo.dcbad15e.js 2.74 KiB 1.23 KiB
685
+ public/vue_assets/js/bar.d4fc59af.js 2.03 KiB 1.00 KiB
686
+ public/vue_assets/css/foo.4bbe6793.css 0.12 KiB 0.11 KiB
687
+ public/vue_assets/css/bar.96de90a8.css 0.02 KiB 0.04 KiB
688
+
689
+ Images and other types of assets omitted.
690
+ ...
691
+ ```
692
+
693
+ Your file names could be different from mine. Don't worry, we won't look those files. There are the files you got:
694
+
695
+ ```
696
+ .
697
+ ├── app
698
+ │   ├── assets
699
+ │   │   └── vue
700
+ │   │   └── manifest.json
701
+ └── public
702
+     └── vue_assets
703
+     ├── css
704
+     │   ├── bar.96de90a8.css
705
+     │   └── foo.4bbe6793.css
706
+     └── js
707
+     ├── bar.d4fc59af.js
708
+     ├── chunk-vendors.b5485759.js
709
+     └── foo.dcbad15e.js
710
+ ```
711
+
712
+ Let have a look at `app/assets/vue/manifest.json`:
713
+
714
+ ```json
715
+ {
716
+ "bar.css": "/vue_assets/css/bar.96de90a8.css",
717
+ "bar.js": "/vue_assets/js/bar.d4fc59af.js",
718
+ "chunk-vendors.js": "/vue_assets/js/chunk-vendors.b5485759.js",
719
+ "entrypoints": {
720
+ "bar": {
721
+ "js": [
722
+ "/vue_assets/js/chunk-vendors.b5485759.js",
723
+ "/vue_assets/js/bar.d4fc59af.js"
724
+ ],
725
+ "css": [
726
+ "/vue_assets/css/bar.96de90a8.css"
727
+ ]
728
+ },
729
+ "foo": {
730
+ "js": [
731
+ "/vue_assets/js/chunk-vendors.b5485759.js",
732
+ "/vue_assets/js/foo.dcbad15e.js"
733
+ ],
734
+ "css": [
735
+ "/vue_assets/css/foo.4bbe6793.css"
736
+ ]
737
+ }
738
+ },
739
+ "foo.css": "/vue_assets/css/foo.4bbe6793.css",
740
+ "foo.js": "/vue_assets/js/foo.dcbad15e.js"
741
+ }
742
+ ```
743
+
744
+ <!-- </details> -->
@@ -27,6 +27,7 @@ class VueCreate
27
27
  copy_demo?
28
28
  copy_config
29
29
  generate_vue_yml
30
+ ensure_entry_point!
30
31
  fix_jest_config!
31
32
  puts 'vue:create finished!'
32
33
  ensure
@@ -101,6 +102,9 @@ class VueCreate
101
102
  end
102
103
  pub_dir = @root.join('public')
103
104
  FileUtils.mv(pub_dir, "#{pub_dir}.backup")
105
+ reademe = @root.join('README.md')
106
+ reademe = reademe.exist? && reademe
107
+ FileUtils.mv(reademe, "#{reademe}.backup") if reademe
104
108
 
105
109
  begin
106
110
  @pm.exec('vue create', '', "-n -m #{@pm.package_manager} .")
@@ -109,6 +113,10 @@ class VueCreate
109
113
  FileUtils.rm_rf(pub_dir) if pub_dir.exist?
110
114
  FileUtils.mv("#{pub_dir}.backup", pub_dir)
111
115
  FileUtils.mv("#{vue_config}.backup", vue_config) if backup_vue_config
116
+ if reademe
117
+ FileUtils.rm_f(reademe)
118
+ FileUtils.mv("#{reademe}.backup", reademe)
119
+ end
112
120
  end
113
121
 
114
122
  # merge gitignore
@@ -169,16 +177,17 @@ class VueCreate
169
177
  foo = false
170
178
  bar = false
171
179
  route_lines.each do |line|
172
- foo ||= line.include?('vue#foo')
173
- bar ||= line.include?('vue#bar')
180
+ foo ||= line.include?('vue_demo#foo')
181
+ bar ||= line.include?('vue_demo#bar')
174
182
  end
175
183
  return if foo && bar
176
184
 
177
185
  end_line = route_lines.rindex { |ln| ln =~ /^\s*end\b/ }
178
186
  return if end_line.blank?
179
187
 
180
- route_lines.insert(end_line, " get 'vue/bar' => 'vue#bar'") unless bar
181
- route_lines.insert(end_line, " get 'vue/foo' => 'vue#foo'") unless foo
188
+ route_lines.insert(end_line, " get 'vue_demo/baz' => 'vue_demo#baz'") unless foo
189
+ route_lines.insert(end_line, " get 'vue_demo/bar' => 'vue_demo#bar'") unless bar
190
+ route_lines.insert(end_line, " get 'vue_demo/foo' => 'vue_demo#foo'") unless foo
182
191
  route_lines.insert(end_line, ' # Example of vue_cli-rails')
183
192
  routes.write(route_lines.join("\n"))
184
193
  end
@@ -205,12 +214,27 @@ class VueCreate
205
214
  yml_dest.write(yml)
206
215
  end
207
216
 
217
+ def ensure_entry_point!
218
+ %w[entry_points assets components utils views].each do |dir_name|
219
+ dir = @root.join("app/assets/vue/#{dir_name}")
220
+ FileUtils.mkdir_p(dir) unless dir.exist?
221
+ end
222
+
223
+ ep_dir = @root.join('app/assets/vue/entry_points')
224
+ return if Dir[ep_dir.join('**/*.js')].any?
225
+ ep_dir.join('entry_point_demo.js').write("console.log('This is a demo entry point')")
226
+ end
227
+
208
228
  def fix_jest_config!
209
229
  jest_file = @root.join('jest.config.js')
210
230
  return unless jest_file.exist?
211
231
 
212
232
  jest_config = %x`node -e "console.log(JSON.stringify(require('./jest.config.js')))"`
213
233
  jest_config = JSON.parse(jest_config)
234
+ if jest_config['transformIgnorePatterns'] &&
235
+ !jest_config['transformIgnorePatterns'].include?('<rootDir>/node_modules/')
236
+ jest_config['transformIgnorePatterns'] << '<rootDir>/node_modules/'
237
+ end
214
238
  jest_config.delete('moduleNameMapper')
215
239
  jest = <<~JS
216
240
  const { jestModuleNameMapper: moduleNameMapper } = require('./vue.rails');
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <div class="hello">
3
+ <h2>Hello {{ msg }}</h2>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'HelloWorld',
10
+ props: {
11
+ msg: String,
12
+ },
13
+ };
14
+ </script>
15
+
16
+ <style scoped>
17
+ h2 {
18
+ color: blue;
19
+ }
20
+ </style>
@@ -0,0 +1,9 @@
1
+ import Vue from 'vue';
2
+
3
+ import Bar from '../views/Bar.vue';
4
+
5
+ Vue.config.productionTip = false;
6
+
7
+ new Vue({
8
+ render: h => h(Bar),
9
+ }).$mount('#app');
@@ -0,0 +1,4 @@
1
+ import launch from '../components/layouts';
2
+ import Foo from '../views/Foo.vue';
3
+
4
+ launch(Foo);
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <div id="app">
3
+ <h1>Foo</h1>
4
+ <HelloWorld msg="Vue!"></HelloWorld>
5
+ </div>
6
+ </template>
7
+
8
+ <script>
9
+ import HelloWorld from '../components/HelloWorld.vue';
10
+
11
+ export default {
12
+ name: 'Foo',
13
+ components: { HelloWorld },
14
+ };
15
+ </script>
16
+
17
+ <style scoped>
18
+ h1 {
19
+ color: red;
20
+ }
21
+ </style>
@@ -0,0 +1,11 @@
1
+ class VueDemoController < ApplicationController
2
+ layout 'vue_demo'
3
+
4
+ def bar
5
+ render_vue 'bar'
6
+ end
7
+
8
+ def baz
9
+ render html: vue_entry('foo')
10
+ end
11
+ end
@@ -5,7 +5,7 @@
5
5
  <%= csrf_meta_tags %>
6
6
  </head>
7
7
  <body>
8
- <div id="app"></div>
9
- <%= yield %>
8
+ <div id="app"></div>
9
+ <%= yield %>
10
10
  </body>
11
11
  </html>
File without changes
@@ -2,6 +2,7 @@ const { env } = require('process');
2
2
 
3
3
  module.exports = (() => {
4
4
  let settings = {};
5
+ const assets = {};
5
6
 
6
7
  try {
7
8
  /* eslint-disable global-require,import/no-extraneous-dependencies */
@@ -36,7 +37,7 @@ module.exports = (() => {
36
37
  devServer.contentBase = resolve(root, devServer.contentBase);
37
38
  }
38
39
  const entry = {};
39
- const assetRoot = resolve(root, 'app/assets/vue/views');
40
+ const assetRoot = resolve(root, 'app/assets/vue/entry_points');
40
41
  const findAllJsFiles = (path) => {
41
42
  readdirSync(path).forEach((fn) => {
42
43
  const filename = resolve(path, fn);
@@ -58,7 +59,7 @@ module.exports = (() => {
58
59
  settings = {
59
60
  env: railsEnv,
60
61
  root,
61
- manifestOutput: resolve(root, manifestOutput),
62
+ manifestOutput: manifestOutput && resolve(root, manifestOutput),
62
63
 
63
64
  outputDir: resolve(root, 'public', pop),
64
65
  publicPath: `/${pop}/`,
@@ -80,7 +81,15 @@ module.exports = (() => {
80
81
  }/$1`,
81
82
  }), {}),
82
83
 
83
- devServer,
84
+ devServer: devServer && {
85
+ ...devServer,
86
+ before(app) {
87
+ app.get('/__manifest/', ({ query }, res) => {
88
+ const entryPoint = Object.keys(query || {})[0];
89
+ res.json(entryPoint === '!!INSPECT!!' ? assets : assets.entrypoints[entryPoint]);
90
+ });
91
+ },
92
+ },
84
93
  filenameHashing,
85
94
  lintOnSave,
86
95
  runtimeCompiler,
@@ -109,17 +118,19 @@ module.exports = (() => {
109
118
  return v === undefined ? cfg : { ...cfg, [k]: v };
110
119
  }, {});
111
120
  const { jestModuleNameMapper } = settings;
121
+ const isProd = settings.env === 'production';
112
122
 
113
123
  return {
114
- isProd: settings.env === 'production',
124
+ isProd,
115
125
  manifest: {
116
126
  /* eslint-disable-next-line global-require,import/no-extraneous-dependencies */
117
127
  plugin: require('webpack-assets-manifest'),
118
128
  options: {
129
+ assets,
119
130
  entrypoints: true,
120
- writeToDisk: true,
131
+ writeToDisk: !!settings.manifestOutput,
121
132
  publicPath: true,
122
- output: settings.manifestOutput,
133
+ output: settings.manifestOutput || '',
123
134
  },
124
135
  },
125
136
  jestModuleNameMapper,
data/lib/source/vue.yml CHANGED
@@ -1,17 +1,16 @@
1
1
  default: &default
2
2
  package_manager: ${PACKAGE_MANAGER}
3
- manifest_output: tmp/manifest.json
4
3
  public_output_path: vue_assets
5
4
  # js_output:
6
5
  # filename: 'js/[name].[hash:8].js'
7
6
  # chunkFilename: 'js/[name].[hash:8].js'
8
7
  alias:
9
8
  '@': app/assets/vue
10
- ~views: app/assets/vue/components/views
11
- ~v-launcher: app/assets/vue/components/layouts
9
+ # '~': app/assets/vue/components
12
10
 
13
11
  development:
14
12
  <<: *default
13
+ # manifest_output: tmp/manifest.json
15
14
  devServer:
16
15
  contentBase: public
17
16
  host: localhost
@@ -4,6 +4,16 @@ module VueCli
4
4
  def initialize
5
5
  @root = ::Rails.root
6
6
  load_config(YAML.load_file(@root.join('config/vue.yml')))
7
+ self.class.setup(self)
8
+ end
9
+
10
+ def entry_assets_prod(entry_point)
11
+ self.class.entry_points[entry_point]
12
+ end
13
+
14
+ def entry_assets_dev(entry_point)
15
+ assets = Net::HTTP.get(URI("#{self.class.dev_server_url}?#{entry_point}"))
16
+ assets.blank? ? nil : JSON.parse(assets)
7
17
  end
8
18
 
9
19
  def node_env
@@ -33,9 +43,6 @@ module VueCli
33
43
  c['root'] = @root.to_s
34
44
  cw['output'] = config['js_output'] if config['js_output'].present?
35
45
  c['manifestOutput'] = config['manifest_output']
36
- unless c['manifestOutput'].presence
37
- raise(Error, 'Incorrect manifest_output in config/vue.yml')
38
- end
39
46
 
40
47
  public_output_path = c['public_output_path'] || 'vue_assets'
41
48
  c['outputDir'] = File.join(resolve('public'), public_output_path)
@@ -60,7 +67,7 @@ module VueCli
60
67
 
61
68
  jest = {}
62
69
  c['jestModuleNameMapper'] = jest
63
- resolve_config(c, 'manifestOutput')
70
+ resolve_config(c, 'manifestOutput') if c['manifestOutput'].present?
64
71
  config['alias']&.tap do |aliases|
65
72
  aliases.each_key do |k|
66
73
  key = k.gsub(%r<(?=[-{}()+.,^$#/\s\]])>, '\\')
@@ -72,8 +79,7 @@ module VueCli
72
79
  end
73
80
  dev_server = c['devServer'] || {}
74
81
  resolve_config(dev_server, 'contentBase')
75
-
76
- self.class.manifest_file = c['manifestOutput']
82
+ ensure
77
83
  @config = c
78
84
  end
79
85
 
@@ -94,26 +100,24 @@ module VueCli
94
100
  JSON.pretty_generate(@config)
95
101
  end
96
102
 
97
- def manifest_data
98
- self.class.manifest.data
99
- end
100
-
101
103
  class << self
104
+ attr_reader :dev_server_url, :entry_points
105
+
102
106
  def instance
103
107
  @instance ||= new
104
108
  end
105
109
 
106
- def manifest_file=(val)
107
- @manifest_file = val ? Pathname.new(val) : nil
108
- end
110
+ def setup(config)
111
+ config.dev_server_host.presence&.tap do |host|
112
+ @dev_server_url = "http://#{host}/__manifest/"
113
+ end
109
114
 
110
- def manifest
111
- @manifest ||= OpenStruct.new(mtime: nil, data: {})
112
- if @manifest_file&.exist? && @manifest.mtime != @manifest_file.mtime
113
- @manifest.mtime = @manifest_file.mtime
114
- @manifest.data = JSON.parse(@manifest_file.read)
115
+ @entry_points = {}
116
+ manifest = config['manifestOutput'].presence
117
+ manifest &&= Pathname.new(manifest)
118
+ if manifest&.exist?
119
+ @entry_points = (JSON.parse(manifest.read || '{}')['entrypoints'] || {}).freeze
115
120
  end
116
- @manifest
117
121
  end
118
122
  end
119
123
 
@@ -124,7 +128,7 @@ module VueCli
124
128
  end
125
129
 
126
130
  def entry
127
- base_dir = @root.join('app/assets/vue/views')
131
+ base_dir = @root.join('app/assets/vue/entry_points')
128
132
  start = base_dir.to_s.size + 1
129
133
  Dir[base_dir.join('**/*.js')].each_with_object({}) do |filename, h|
130
134
  h[filename[start...-3]] = filename
@@ -4,14 +4,32 @@ module VueCli
4
4
 
5
5
  class Engine < ::Rails::Engine
6
6
  initializer 'vue_cli' do |app|
7
- if ::Rails.env.development? && defined?(::Rails::Server)
8
- require 'vue_cli/rails/dev_server_proxy'
9
- app.middleware.insert_before(0, DevServerProxy)
10
- Engine.start_wds! if ENV['NO_WEBPACK_DEV_SERVER'].blank?
7
+ if defined?(::Rails::Server)
8
+ is_dev = ::Rails.env.development?
9
+
10
+ if is_dev
11
+ require 'vue_cli/rails/dev_server_proxy'
12
+
13
+ app.middleware.insert_before(0, DevServerProxy)
14
+ Engine.start_wds! if ENV['NO_WEBPACK_DEV_SERVER'].blank?
15
+ end
16
+
17
+ Configuration.class_eval do
18
+ alias_method :entry_assets, :"entry_assets_#{is_dev ? 'dev' : 'prod'}"
19
+ remove_method :entry_assets_dev, :entry_assets_prod
20
+ end
21
+ Configuration.instance unless is_dev
11
22
  end
12
23
 
13
24
  ::ActiveSupport.on_load(:action_controller) do
14
- ::ActionController::Base.helper(Helper)
25
+ ::ActionController::Base.class_eval do
26
+ helper(Helper)
27
+ include(Helper)
28
+
29
+ define_method(:render_vue) do |entry, **args|
30
+ render({ html: vue_entry(entry), layout: true }.merge(args))
31
+ end
32
+ end
15
33
  end
16
34
 
17
35
  ::ActiveSupport.on_load(:action_view) do
@@ -28,7 +46,9 @@ module VueCli
28
46
  pid = running&.dig(1)&.split(/\s+/, 3)&.dig(1)
29
47
  Process.kill('INT', pid.to_i) if pid.present?
30
48
  end
31
- config.node_env.exec(config['launch_dev_service'] || 'vue-cli-service serve')
49
+
50
+ cmd = config['launch_dev_service'].presence || 'vue-cli-service serve'
51
+ config.node_env.exec(cmd)
32
52
  end
33
53
  end
34
54
  end
@@ -1,21 +1,18 @@
1
1
  module VueCli
2
2
  module Rails
3
3
  module Helper
4
- def vue_entry(name)
5
- @config ||= VueCli::Rails::Configuration.instance
4
+ def vue_entry(entry)
5
+ assets = VueCli::Rails::Configuration.instance.entry_assets(entry)
6
+ raise(ArgumentError, "Vue entry (#{entry}) not found!") if assets.blank?
6
7
 
7
- entry = (@config.manifest_data['entrypoints'] || {})[name]
8
- return raise(VueCli::Rails::Error, "Not found vue entry point: #{name}") if entry.blank?
9
-
10
- assets = []
11
- (entry['css'] || []).each do |css|
12
- assets << stylesheet_link_tag(css)
8
+ tags = ''.dup
9
+ (assets['css'] || []).each do |css|
10
+ tags << %{<link href="#{css}" rel="stylesheet">}
13
11
  end
14
- (entry['js'] || []).each do |js|
15
- assets << javascript_include_tag(js)
12
+ (assets['js'] || []).each do |js|
13
+ tags << %{<script src="#{js}"></script>}
16
14
  end
17
-
18
- assets.join('').html_safe
15
+ tags.html_safe
19
16
  end
20
17
  end
21
18
  end
@@ -11,7 +11,7 @@ module VueCli
11
11
  def use!(manager)
12
12
  @pm = manager.to_sym
13
13
  raise(ArgumentError, "Unsupported manager: #{@pm}") unless %i[npm yarn].include?(@pm)
14
- raise(VueCli::Rails::Error, "Not installed: #{@pm}") unless try(:"#{@pm}?")
14
+ raise(ArgumentError, "Not installed: #{@pm}") unless try(:"#{@pm}?")
15
15
  end
16
16
 
17
17
  def reset
@@ -1,5 +1,5 @@
1
1
  module VueCli
2
2
  module Rails
3
- VERSION = '0.2.0'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vue_cli-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Chen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-10 00:00:00.000000000 Z
11
+ date: 2019-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -131,16 +131,16 @@ files:
131
131
  - lib/helpers/scripts/install_rails.rb
132
132
  - lib/helpers/scripts/vue_command.rb
133
133
  - lib/helpers/scripts/vue_create.rb
134
+ - lib/source/app/assets/vue/components/HelloWorld.vue
134
135
  - lib/source/app/assets/vue/components/layouts/App.vue
135
136
  - lib/source/app/assets/vue/components/layouts/index.js
136
- - lib/source/app/assets/vue/components/views/Bar.vue
137
- - lib/source/app/assets/vue/components/views/Foo.vue
138
- - lib/source/app/assets/vue/views/bar.js
139
- - lib/source/app/assets/vue/views/foo.js
140
- - lib/source/app/controllers/vue_controller.rb
141
- - lib/source/app/views/layouts/vue.html.erb
142
- - lib/source/app/views/vue/bar.html.erb
143
- - lib/source/app/views/vue/foo.html.erb
137
+ - lib/source/app/assets/vue/entry_points/bar.js
138
+ - lib/source/app/assets/vue/entry_points/foo.js
139
+ - lib/source/app/assets/vue/views/Bar.vue
140
+ - lib/source/app/assets/vue/views/Foo.vue
141
+ - lib/source/app/controllers/vue_demo_controller.rb
142
+ - lib/source/app/views/layouts/vue_demo.html.erb
143
+ - lib/source/app/views/vue_demo/foo.html.erb
144
144
  - lib/source/vue.config.js
145
145
  - lib/source/vue.rails.js
146
146
  - lib/source/vue.yml
@@ -174,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
174
174
  - !ruby/object:Gem::Version
175
175
  version: '0'
176
176
  requirements: []
177
- rubygems_version: 3.0.2
177
+ rubygems_version: 3.0.3
178
178
  signing_key:
179
179
  specification_version: 4
180
180
  summary: Get vue-cli working with Rails
@@ -1,17 +0,0 @@
1
- <template>
2
- <div id="foo">
3
- <h1>Foo</h1>
4
- </div>
5
- </template>
6
-
7
- <script>
8
- export default {
9
- name: 'Foo',
10
- };
11
- </script>
12
-
13
- <style scoped>
14
- #foo {
15
- color: red;
16
- }
17
- </style>
@@ -1,4 +0,0 @@
1
- import launch from '~v-launcher';
2
- import Bar from '~views/Bar.vue';
3
-
4
- launch(Bar);
@@ -1,4 +0,0 @@
1
- import launch from '~v-launcher';
2
- import Foo from '~views/Foo.vue';
3
-
4
- launch(Foo);
@@ -1,7 +0,0 @@
1
- class VueController < ApplicationController
2
- layout 'vue'
3
-
4
- def foo; end
5
-
6
- def bar; end
7
- end
@@ -1 +0,0 @@
1
- <%= vue_entry('bar') %>