vue_cli-rails 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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') %>