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 +4 -4
- data/README.md +256 -19
- data/lib/helpers/scripts/vue_create.rb +28 -4
- data/lib/source/app/assets/vue/components/HelloWorld.vue +20 -0
- data/lib/source/app/assets/vue/entry_points/bar.js +9 -0
- data/lib/source/app/assets/vue/entry_points/foo.js +4 -0
- data/lib/source/app/assets/vue/{components/views → views}/Bar.vue +0 -0
- data/lib/source/app/assets/vue/views/Foo.vue +21 -0
- data/lib/source/app/controllers/vue_demo_controller.rb +11 -0
- data/lib/source/app/views/layouts/{vue.html.erb → vue_demo.html.erb} +2 -2
- data/lib/source/app/views/{vue → vue_demo}/foo.html.erb +0 -0
- data/lib/source/vue.rails.js +17 -6
- data/lib/source/vue.yml +2 -3
- data/lib/vue_cli/rails/configuration.rb +24 -20
- data/lib/vue_cli/rails/engine.rb +26 -6
- data/lib/vue_cli/rails/helper.rb +9 -12
- data/lib/vue_cli/rails/node_env.rb +1 -1
- data/lib/vue_cli/rails/version.rb +1 -1
- metadata +11 -11
- data/lib/source/app/assets/vue/components/views/Foo.vue +0 -17
- data/lib/source/app/assets/vue/views/bar.js +0 -4
- data/lib/source/app/assets/vue/views/foo.js +0 -4
- data/lib/source/app/controllers/vue_controller.rb +0 -7
- data/lib/source/app/views/vue/bar.html.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e23e30ec06f2e4f661258507ac78cca3ee9b9e2f583fac001b231cfc0194d00f
|
4
|
+
data.tar.gz: 4fe54577949add5a0739a612bf501ef667c1ac7b3964c0c9e7423f1019d0a46a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
[+]
|
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/
|
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/
|
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/
|
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?('
|
173
|
-
bar ||= line.include?('
|
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 '
|
181
|
-
route_lines.insert(end_line, " get '
|
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>
|
File without changes
|
@@ -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>
|
File without changes
|
data/lib/source/vue.rails.js
CHANGED
@@ -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/
|
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
|
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:
|
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
|
-
~
|
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
|
107
|
-
|
108
|
-
|
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
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
@
|
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/
|
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
|
data/lib/vue_cli/rails/engine.rb
CHANGED
@@ -4,14 +4,32 @@ module VueCli
|
|
4
4
|
|
5
5
|
class Engine < ::Rails::Engine
|
6
6
|
initializer 'vue_cli' do |app|
|
7
|
-
if
|
8
|
-
|
9
|
-
|
10
|
-
|
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.
|
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
|
-
|
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
|
data/lib/vue_cli/rails/helper.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
module VueCli
|
2
2
|
module Rails
|
3
3
|
module Helper
|
4
|
-
def vue_entry(
|
5
|
-
|
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
|
-
|
8
|
-
|
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
|
-
(
|
15
|
-
|
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(
|
14
|
+
raise(ArgumentError, "Not installed: #{@pm}") unless try(:"#{@pm}?")
|
15
15
|
end
|
16
16
|
|
17
17
|
def reset
|
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.
|
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-
|
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/
|
137
|
-
- lib/source/app/assets/vue/
|
138
|
-
- lib/source/app/assets/vue/views/
|
139
|
-
- lib/source/app/assets/vue/views/
|
140
|
-
- lib/source/app/controllers/
|
141
|
-
- lib/source/app/views/layouts/
|
142
|
-
- lib/source/app/views/
|
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.
|
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 +0,0 @@
|
|
1
|
-
<%= vue_entry('bar') %>
|