Skip to content

Commit

Permalink
Merge pull request #1 from astrocket/react-support
Browse files Browse the repository at this point in the history
React support
  • Loading branch information
Astro authored Sep 15, 2019
2 parents 94972d5 + b1612c3 commit 8baba3a
Show file tree
Hide file tree
Showing 20 changed files with 264 additions and 44 deletions.
20 changes: 10 additions & 10 deletions Gemfile.tt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "<%= RUBY_VERSION %>"

gem "rails", "~> <%= Rails.version %>"
gem "rails", "~> <%= Rails.version || "~> 6.0.0" %>"
# gem 'rails-i18n'

gem 'pg', '>= 0.18', '< 2.0'<%= gemfile_requirement("pg") %>
Expand All @@ -14,28 +14,28 @@ gem 'puma', '~> 3.11'<%= gemfile_requirement("puma") %>
# gem 'aws-sdk-s3' # for DigitalOcean config

# Auth
<%= "#" unless use_active_admin == 'yes' %>gem 'devise'
<%= "#" unless use_active_admin == 'yes' %>gem 'devise-i18n'
<%= "#" unless use_active_admin %>gem 'devise'
<%= "#" unless use_active_admin %>gem 'devise-i18n'

# Model
gem 'jbuilder', '~> 2.5'
# gem 'aasm'

# View
gem 'sass-rails', '~> 5.0'
gem 'webpacker', '>= 4.0.0.rc.3'
gem 'turbolinks', '~> 5'
gem 'webpacker', '>= 4.0.0'
<%= "gem 'turbolinks', '~> 5'" unless use_react %>
# gem 'inline_svg' if using svg files

# CMS
<%= "#" unless use_active_admin == 'yes' %>gem 'activeadmin'
<%= "#" unless use_active_admin == 'yes' %>gem 'activeadmin_addons'
<%= "#" unless use_active_admin == 'yes' %>gem 'arctic_admin'
<%= "#" unless use_active_admin == 'yes' %>gem 'arbre', '>= 1.2.1'
<%= "#" unless use_active_admin %>gem 'activeadmin'
<%= "#" unless use_active_admin %>gem 'activeadmin_addons'
<%= "#" unless use_active_admin %>gem 'arctic_admin'
<%= "#" unless use_active_admin %>gem 'arbre', '>= 1.2.1'

# Background
gem 'sidekiq'
<%= "#" unless slack_notification == 'yes' %>gem 'slack-ruby-client'
<%= "#" unless use_slack_notification %>gem 'slack-ruby-client'
# gem 'whenever'

gem 'bootsnap', '>= 1.1.0', require: false
Expand Down
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ rails new project -T -d postgresql \

* Docker for production deploy
* Nginx Proxy server configuration with Let's encrypt SSL Certificate
* Webpacker and Stimulus setting for client javascript
* React / Stimulus setting for client javascript
* ActiveJob + Sidekiq + Redis setting for async jobs
* ActiveAdmin + ArcticAdmin for application admin
* Foreman setting for integrative dev setup
Expand All @@ -43,7 +43,11 @@ It runs
* guard
* sidekiq

## Stimulus generator
## Stimulus.js

With [stimulus.js]([https://stimulusjs.org](https://stimulusjs.org/)) you can keep your client-side code style as basic style `html + css + js` stack and still get the advantages of modern Javascript open sources through npm.

### generator

Stimulus specific generator task.

Expand All @@ -53,6 +57,20 @@ It generates

* `app/javascript/posts/index_controller.js` with sample html markup containing stimulus path helper.

## React.js

With [react.js](https://reactjs.org/) you can build modern single page application in the most common way. (This template implements react.js with hooks.)

In order to integrate react.js and rails.

Template contains

- react layout : `react.html.erb`
- routing for react : `/:path => 'react#index'`
- routing for rails : `/api`, `/app`
- some examples with routing over rails pages <-> react pages
- example functional component with fetching api from client to server.

## Production deploy process

After installing [docker](https://docs.docker.com/install/) & [docker-compose](https://docs.docker.com/compose/install/) in your host machine.
Expand Down Expand Up @@ -151,4 +169,5 @@ docker rm processid
```

## TODO
- Zero downtime deployment with docker-compose.
-
Empty file.
9 changes: 9 additions & 0 deletions app/controllers/api/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Api
class HomeController < Api::ApiController
def index
render json: {
hello: "Hello World from Rails"
}
end
end
end
4 changes: 4 additions & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class HomeController < ApplicationController
def index
end
end
3 changes: 3 additions & 0 deletions app/controllers/react_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class ReactController < ApplicationController
def index; render "layouts/react" end
end
20 changes: 20 additions & 0 deletions app/javascript/packs/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import { useRoutes, A } from "hookrouter";
import routes from "./routes";

function App() {
const routeResult = useRoutes(routes);
return (
<div>
<A href='/home'>React SPA /home</A>
<br/>
<A href='/about'>React SPA /about</A>
<br/>
<a href="/">Rails SSR /</a>
<hr/>
{routeResult || <h1>404 on React SPA</h1>}
</div>
);
}

export default App;
7 changes: 7 additions & 0 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App';

document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(<App/>, document.body.appendChild(document.createElement('div')))
});
25 changes: 25 additions & 0 deletions app/javascript/packs/pages/home/Index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useState, useEffect } from "react";
import api from 'utils/api';

function Index() {
const [ helloWorld, setHelloWorld ] = useState('loading...');

useEffect(() => {
console.log(window, 'mount');
api.get('/api/home/index').then((res) => {
setHelloWorld(res.data.hello);
});
return () => {
console.log(window, 'unmount')
}
}, []);

return (
<div>
<h2>HomeIndex Page from React.js</h2>
<p>{helloWorld}</p>
</div>
);
}

export default Index;
9 changes: 9 additions & 0 deletions app/javascript/packs/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";
import HomeIndex from "./pages/home/Index.jsx";

const routes = {
"/home": () => <HomeIndex />,
"/about": () => <h2>About Page from React.js</h2>
};

export default routes;
2 changes: 1 addition & 1 deletion app/lib/exceptions/default_error.rb.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Exceptions
def initialize(msg = "알 수 없는 에러가 발생했습니다.", notification = false)
@message = msg
puts "DefaultError => #{msg}" if Rails.env.development?
<%= "#" unless slack_notification == 'yes' %>SlackService.send_message("Exceptions::DefaultError", msg, :error) if notification
<%= "#" unless use_slack_notification %>SlackService.send_message("Exceptions::DefaultError", msg, :error) if notification
end
end
end
5 changes: 5 additions & 0 deletions app/services/slack_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ def send_message(title, msg, channel = :log)
SlackMessageJob.perform_later("*#{title}*#{"\n"}```#{msg}```", CHANNELS[channel])
end

def send_exception(e, title = e.message, prepend = nil)
title = "🤔 " + title
SlackMessageJob.perform_later("*#{title}*#{"\n"}```#{prepend}#{"\n"}#{e.backtrace.first(20).join("\n")}```", CHANNELS[:error])
end

def upload_file(file, channel = :log)
# client.files_upload(
# channels: '#general',
Expand Down
25 changes: 22 additions & 3 deletions app/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,32 @@

copy_file 'app/controllers/api/api_controller.rb'

copy_file 'app/controllers/home_controller.rb'
template 'app/views/home/index.html.erb.tt'

copy_file 'app/javascript/utils/api.js'
copy_file 'app/javascript/utils/helpers.js'
copy_file 'app/javascript/controllers/index.js', force: true

if use_react
copy_file 'app/javascript/packs/application.js', force: true
copy_file 'app/javascript/packs/routes.js'
copy_file 'app/javascript/packs/App.jsx'
copy_file 'app/javascript/packs/pages/home/Index.jsx'

copy_file 'app/controllers/react_controller.rb'
template 'app/views/layouts/react.html.erb.tt'

copy_file 'app/controllers/api/home_controller.rb'

copy_file 'app/assets/javascripts/application.js', force: true
template 'app/views/layouts/application.html.erb.tt', force: true
else
copy_file 'app/javascript/controllers/index.js', force: true
end

copy_file 'app/jobs/http_post_job.rb'
template 'app/lib/exceptions/default_error.rb.tt'
copy_file 'app/lib/bot_helper.rb'

copy_file 'app/jobs/slack_message_job.rb' if slack_notification == 'yes'
copy_file 'app/services/slack_service.rb' if slack_notification == 'yes'
copy_file 'app/jobs/slack_message_job.rb' if use_slack_notification
copy_file 'app/services/slack_service.rb' if use_slack_notification
13 changes: 13 additions & 0 deletions app/views/home/index.html.erb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div><% if use_react %>
<a href="/home">React SPA /home</a>
<br>
<a href="/about">React SPA /about</a>
<br>
<a href="/">Rails SSR /</a>
<% else %>
<a href="/">Home</a>
<% end %></div>
<hr>
<h2>
Application Root
</h2>
15 changes: 15 additions & 0 deletions app/views/layouts/application.html.erb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title><%= app_name %></title>
<%%= csrf_meta_tags %>
<%%= csp_meta_tag %>

<%%= stylesheet_link_tag 'application', media: 'all' %>
<%%= javascript_include_tag 'application', media: 'all' %>
</head>

<body>
<%%= yield %>
</body>
</html>
11 changes: 11 additions & 0 deletions app/views/layouts/react.html.erb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title><%= app_name %></title>
<%%= csrf_meta_tags %>
<%%= csp_meta_tag %>

<%%= stylesheet_link_tag 'application', media: 'all' %>
<%%= javascript_pack_tag 'application' %>
</head>
</html>
42 changes: 32 additions & 10 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,53 @@
insert_into_file 'config/routes.rb', before: /^end/ do
if use_active_admin
<<-'RUBY'
authenticate :admin_user do
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
end
namespace :api do
end
%w( 404 422 500 ).each do |code|
get code, :to => "errors#show", :code => code
end
RUBY
else
<<-'RUBY'
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
RUBY
end
end

insert_into_file 'config/routes.rb', before: /^end/ do
<<-'RUBY'
namespace :api do
get '/home/index' => 'home#index'
end
RUBY
end

insert_into_file 'config/routes.rb', before: /^end/ do
if use_react
<<-'RUBY'
namespace :app do
get '/' => 'home#index'
end
# To render react packs for any path except app/api
scope '/:path', constraints: { path: /.+/ } do
get '/' => 'react#index', as: :react # react_path
end
RUBY
end
end

insert_into_file 'config/routes.rb', before: /^end/ do
<<-'RUBY'
root 'home#index'
%w( 404 422 500 ).each do |code|
get code, :to => "errors#show", :code => code
end
RUBY
end
end
end
2 changes: 1 addition & 1 deletion config/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
template "config/database.yml.tt", force: true
copy_file 'config/initializers/sidekiq.rb'
copy_file 'config/sidekiq.yml'
copy_file 'config/initializers/slack.rb' if slack_notification == 'yes'
copy_file 'config/initializers/slack.rb' if use_slack_notification
10 changes: 7 additions & 3 deletions lib/template.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
copy_file 'lib/tasks/deploy.rake'
copy_file 'lib/tasks/hot.rake'
template 'lib/generators/stimulus/templates/controller.js.erb.tt'
copy_file 'lib/generators/stimulus/stimulus_generator.rb'
copy_file 'lib/generators/stimulus/USAGE'
if use_react

else
template 'lib/generators/stimulus/templates/controller.js.erb.tt'
copy_file 'lib/generators/stimulus/stimulus_generator.rb'
copy_file 'lib/generators/stimulus/USAGE'
end
Loading

0 comments on commit 8baba3a

Please sign in to comment.