Suddenly, building an environment is as troublesome and weak as shaving every morning. If you are reading this article, you may be not good at building an environment.
We often hear from members of the company that they are not as good at building an environment as a Yankee who hangs out at a convenience store. I think this first hurdle to building an environment is hampering creative behavior! I am confident that more services will be created in this world if we save the trouble of building an environment! Therefore, this time, we will release an environment construction manual for creating a service that "uses Rails as an API server" and "draws with React"!
――I'm using a Mac because it looks fashionable! ――Since I graduated from programming school, I want to make a personal app! ――I want to learn a modern Javascript framework called React.js and make a difference! ――I want to loosely couple the interaction between Rails and React by a method that does not use Gem such as react-rails! --Docker? What is it delicious? (This article does not explain Docker)
name | Description |
---|---|
Ruby | I don't know |
Rails | I don't know |
MySQL | I don't know |
brew | Package management (mainly server side) |
yarn | Package management (mainly front side) |
rails new app name-–skip-turbolinks --webpack=react --database=mysql --api
It's rumored that how many times in your life you hit this "rails new" command will determine your value as a Rails engineer. By the way, you can rewrite the options if necessary.
Webpacker is a module bundler that comes standard with Rails and is a wrapper for Webpack. A bundler is a person who bundles. It is a guy that bundles files in various formats such as HTML, CSS, and JS.
By the way, a rapper is not a person who steps on the rhyme. It's a rapper like Saran Wrap. It means "wrap". Webpacker is a wrapper for Webpack because it calls Webpack internally.
By the way, if you are interested in the front end, you should have some knowledge of Webpack. It's GOOD if you remember it as a set with words like "Babel" and "ES6"!
rails webpacker:install
rails webpacker:install:react
This time I will use MySQL for DB. I use PostgreSQL for my daily work, but I think programming school graduates are used to MySQL. I feel that many new product DB selections use the ones that are familiar to the site. I'm sorry if it's different. By the way, as an aside of aside, I'm personally interested in NoSQL's MongoDB. The reason is, "It looks like a cool engineer if you know it somehow."
This time I will install MySQL via a package manager called brew
brew install mysql
After installing MySQL, create a user for use with this app. I will omit each command because it seems that it is not necessary to explain it in detail.
mysql -u root -p
create user'username' @'localhost' identified by'password';
select User,Host from mysql.user;
grant all on *. * To'[username]' @'localhost';
After creating the user, link the created user with Rails. The rule is to describe Rails DB settings in database.yml.
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV['DATABASE_USERNAME'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
host: <%= ENV['DATABASE_HOST'] %>
development:
<<: *default
database: app_name_development
test:
<<: *default
database: app_name_test
production:
<<: *default
database: app_name_production
username: <%= ENV['APP_NAME_DATABASE_USERNAME'] %>
password: <%= ENV['APP_NAME_DATABASE_PASSWORD'] %>
Please replace "app_name_ ○○" with the app name when Rails new was done. Since the username and password will be visible if you publish them on GitHub It is recommended to hide it using gem "dotenv" etc. By the way, it is meaningless unless you remove the ".env" file created by dotenv from Git management, so be sure to add ".env" to ".gitignore" once you have created it! If you don't know what you're talking about, check out "dotenv environment variables"! "Finding what you don't understand" is the basis of an engineer! I feel that how we can dig deeper into this "investigation" is a shortcut for growth.
rake db:create
rails s
Environment construction will continue a little longer. It's already about the 6th station. A little more.
A Webpack plugin that automatically splits chunks. You can save the file size, but you don't have to.
const { environment } = require('@rails/webpacker');
environment.splitChunks();
module.exports = environment;
app/views/top/show.html.erb It means to refer to the file named "index" in javascript / packs /.
<%#When using split chunks%>
<%= javascript_packs_with_chunks_tag 'index' %>
<%#When not using split chunks%>
<%= javascript_pack_tag 'index' %>
config/routes.rb
Rails.application.routes.draw do
#Root page settings
root "top#show"
end
app/controllers/top_controller.rb
class TopController < ApplicationController
def show
end
end
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Application title</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= javascript_pack_tag 'application' %>
</head>
<body>
<div id="root">← This is
<%= yield %>
</div>
</body>
</html>
app/javascript/packs/index.jsx File referenced from app / views / top / show.html.erb This file is the entrance to React. Asynchronous, routing, state management, etc., packages for React are imported and set. You will install each package later.
//This file is the very first file called by Rails View (EntryPoint)
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'
import {
Router,
Route,
Switch,
IndexRoute,
useLocation
} from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { composeWithDevTools } from 'redux-devtools-extension';
// reducer
import rootReducer from '~/src/reducers/';
// Component
import Top from '~/src/components/tops/';
const middleWares = [thunk];
//For development environment, settings for using development tools
const enhancer = process.env.NODE_ENV === 'development' ?
composeWithDevTools(applyMiddleware(...middleWares)) : applyMiddleware(...middleWares);
const store = createStore(rootReducer, enhancer);
const customHistory = createBrowserHistory();
render(
<Provider store={store}>
<Router history={customHistory}>
<Route render={({ location }) => (
<div>
<Switch location={location}>
<Route exact path='/' component={Top} />
</Switch>
</div>
)}/>
</Router>
</Provider>,
document.getElementById('root')
)
app/javascript/src/components/tops/index.jsx Use a file with the extension jsx to describe the React component. Write HTML in the JS file. At first, I feel uncomfortable writing HTML tags in JS, but I get used to it.
import React from 'react';
const Top = () => (
<h1>
<center>Application title</center>
</h1>
)
export default Top;
app/javascript/src/reducers/index.js
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
import top from '~/src/modules/tops/';
export default combineReducers({
form: formReducer,
top,
});
The summary here is stored in the Redux store. Redux is a package that centrally manages the state. A store is a box that stores state. This is the most important feature of Redux. The use of Redux is not essential for React development, but it is better to include it from the beginning because it becomes difficult to manage the state as the scale of the product increases with React alone. It doesn't have to be LP or a small product.
The directory structure uses the ducks pattern. The ducks pattern is the idea of describing "action type", "action creator", and "reducer" in one file. It's a design concept. It's not about installing something.
app/javascript/src/modules/tops/index.js
// action-type
const TOP_INITIAL = 'TOP_INITIAL';
// reducer
const initialState = {
top: null,
}
export default function top(state = initialState, action) {
switch (action.type) {
case TOP_INITIAL:
return {
...state,
}
default:
return state
}
}
// action-creator
export const topInitial = () => ({
type: TOP_INITIAL,
});
Normally, files are created for each of "action type", "action creator", and "reducer", but if you incorporate the ducks pattern, they will be combined into one file, so you can simply reduce the number of files. It is recommended because it is a design concept that can withstand even medium-sized products at all. If you're wondering what an action type is, check out Redux Official!
Install using a package manager called yarn. There is a similar package manager with "npm", but "yarn" is upward compatible with "npm". The package installed by yarn is automatically added to the file "package.json" directly under the root directory. Add a package with "yarn add package name" Remove the package with "yarn remove package name".
yarn add redux react-redux react-router-dom redux-devtools-extension redux-form redux-thunk axios @babel/preset-react babel-plugin-root-import
If you are interested, "@ reduxjs / toolkit", "@ material-ui / core" Is also recommended
If you've ever developed React on your own, you should have thought this once. "React relative path tends to be hell." React tends to fall into the relative path specification hell when importing. It is recommended to include "babel-plugin-root-import" to prevent this from happening. Actually, it is secretly included in "yarn add" in 11. above, so the person who copied and executed the command is already included by my strategy.
Create a file called ".babelrc" and describe the settings there. The location to create the ".babelrc" file is directly under the root directory.
.babelrc
{
"plugins": [
[
"babel-plugin-root-import",
{
"paths": [
{
"rootPathSuffix": "./app/javascript/src",
"rootPathPrefix": "~/src/"
},
]
}
]
]
}
The above setting only sets the path specification "./app/javascript/src" so that it can also be specified with the character string "~ / src /". Now you can use "~ / src / ○○" when importing with React component, so you can get out of relative path hell. By the way, the "" ~ / src / "" part can be set as you like with either "" ~ / "" or "" @ / src / "".
./bin/webpack-dev-server
It is a development server that automatically compiles. We also monitor the code all the time, so if you rewrite the React code, it will automatically rewrite the drawing on the browser. (By the way, Rails Model, Controller, View, etc. are not monitored, so even if you change them, they will not be drawn automatically. Let's update the browser with "command + R" obediently.)
You should now have a Rails & React development environment ... If "Application title" is displayed in [http: // localhost: 3000 /](http: // localhost: 3000 /), it is successful! Let's have fun 3R (Ruby on Rails on React) development!
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/' succeeds before bundling.
If the above error message is displayed and bundle install fails ↓
In some cases it can be resolved with sudo xcodebuild -license accept
Recommended Posts