Skip to content

Commit 4ccd823

Browse files
committed
added render_vue to controllers. entry point position breaking change
1 parent b98244f commit 4ccd823

File tree

22 files changed

+431
-107
lines changed

22 files changed

+431
-107
lines changed

README.md

Lines changed: 256 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ And then execute:
2828
- Feel free to use `yarn` or `npm`.
2929
- Single `vue_entry` rather than confusing `stylesheet_pack_tag`, `javascript_packs_tag` and `javascript_packs_with_chunks_tag`.
3030
- 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+
3437
- Run `webpack-dev-server` together with Rails server with development mode.
3538
- Just single `RAILS_ENV`, no more `NODE_ENV`.
3639
- Rails way configurations in `config/vue.yml`.
@@ -40,9 +43,13 @@ And then execute:
4043
Out-of-box workflow:
4144

4245
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`).
4653

4754
> More settings are available in `config/vue.yml`
4855
@@ -52,17 +59,19 @@ Out-of-box workflow:
5259

5360
#### Concept: Entry Point and File structure
5461

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.
5663

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.
5867

5968
> Be aware, `.js.erb` and `.vue.erb` are NOT supported. I will explain the reason in [Q&A section](#difference-from-webpacker).
6069
6170
If you are new to modern front-end development, or more specifically with `webpack` in this case, please read [Q&A section](#qa) for more information.
6271

6372
#### Helper `vue_entry`
6473

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).)
6675

6776
> You may have interest of path alias in `config/vue.yml`.
6877
@@ -74,12 +83,11 @@ If you are new to modern front-end development, or more specifically with `webpa
7483
[+] app
7584
[+] assets
7685
[+] 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
8187
[+] foo
8288
[-] bar.js - entry point: import '~views/FooBar.vue'
89+
[+] views - alias `~views`
90+
[-] FooBar.vue - Vue component for `foo/bar`
8391
[+] controllers
8492
[+] foo_controller.rb - controller
8593
[+] views
@@ -94,7 +102,7 @@ If you are new to modern front-end development, or more specifically with `webpa
94102
```yaml
95103
# default
96104
alias:
97-
~views: app/assets/vue/components/views
105+
~views: app/assets/vue/views
98106
```
99107
100108
- Your controller:
@@ -117,7 +125,7 @@ If you are new to modern front-end development, or more specifically with `webpa
117125
- Entry point JS:
118126

119127
```js
120-
// file - app/assets/vue/views/foo/bar.js
128+
// file - app/assets/vue/entry_points/foo/bar.js
121129
import Vue from 'vue';
122130

123131
import Foo from '~views/FooBar.vue';
@@ -130,7 +138,7 @@ If you are new to modern front-end development, or more specifically with `webpa
130138
- Your Vue component for your entry point:
131139

132140
```vue
133-
// file - app/assets/vue/components/views/FooBar.vue
141+
// file - app/assets/vue/views/FooBar.vue
134142
<template>
135143
<div id="foo-bar">
136144
<h1>Foo/bar</h1>
@@ -168,6 +176,55 @@ If you are new to modern front-end development, or more specifically with `webpa
168176

169177
</details>
170178

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+
171228
#### Public Output Path
172229

173230
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
192249

193250
</details>
194251

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+
195258
### Available Settings
196259

197260
#### General settings file is `config/vue.yml`
198261

199262
- `manifest_output`
200263

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.
202265

203266
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.
204267

@@ -218,9 +281,13 @@ Actually `public_output_path` in `config/vue.yml` is very simple - just a sub pa
218281

219282
Please see [available options](#valid-vue-cli-config-options).
220283

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+
221288
#### Customize your webpack configurations in `vue.config.js`
222289

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`.
224291

225292
### Rake Tasks
226293

@@ -313,7 +380,7 @@ Feel free update `vue.config.js` by yourself. There are some lines of boiler-pla
313380
}
314381
```
315382

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.
317384
318385
## Valid Vue CLI config Options
319386

@@ -505,3 +572,173 @@ Sorry, I don't think many gems work on Windows. Please install a virtual machine
505572
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.
506573

507574
</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> -->

0 commit comments

Comments
 (0)