Guide for the initial configuration for projects that are built with the following technologies stack: Phoenix Framework, Webpack Module Bundler, React Library and GraphQL Query Language and how each element should be organized in the internal structure of the project.
To be able to create projects with this stack of technologies it is necessary to install Phoenix on the system. Webpack, React and QraphQL will be installed later on each project when configuring it.
To know if Phoenix has already been installed on the computer, you can enter the following console command:
mix phx.new --versionIf this does not return version information, it must have to be installed. In the Phoenix documentation there is a page with the Installation instructions.
-
Create a new Phoenix project:
mix phx.new project_name
During the process of creating files, is asked if you want to extract and install the dependencies for the project, indicate yes.
-
Access to the project_name\assets directory of the project.
cd project_name\assets -
Uninstall via NPM the following dependencies:
- brunch
- babel-brunch
- clean-css-brunch
- uglify-js-brunch
npm uninstall --save-dev babel-brunch brunch clean-css-brunch uglify-js-brunch -
Delete the brunch-config.js file.
rm brunch-config.js -
Install via NPM the following dependencies:
- webpack
- webpack-cli
- copy-webpack-plugin
- uglifyjs-webpack-plugin
- graphql
- react
- react-dom
- react-router-dom
- prop-types
- @babel/core
- @babel/cli
- @babel/preset-env
- @babel/preset-react
- @babel/plugin-proposal-class-properties
- babel-loader
- css-loader
- url-loader
- file-loader
- mini-css-extract-plugin
- optimize-css-assets-webpack-plugin
npm install --save-dev webpack webpack-cli copy-webpack-plugin uglifyjs-webpack-plugin graphql react react-dom react-router-dom prop-types @babel/core @babel/cli @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties babel-loader css-loader url-loader file-loader mini-css-extract-plugin optimize-css-assets-webpack-plugin -
Create a new file with .babelrc as file name.
touch .babelrc
-
Edit the .babelrc file and place the following code:
{ "presets": [ ["@babel/preset-env", {"modules" : false}], "@babel/preset-react" ], "plugins": [ "@babel/plugin-proposal-class-properties" ] } -
Edit the package.json file and replace the value of the
scriptskey with the following code:"scripts": { "deploy": "webpack --mode production", "start": "webpack --mode development --watch-stdin --color" },
-
Create a new file with webpack.config.js as file name.
touch webpack.config.js
-
Edit the webpack.config.js file and place the following code:
const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = (env, options) => ({ optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }), new OptimizeCSSAssetsPlugin({}) ] }, entry: './js/app.js', output: { filename: 'app.js', path: path.resolve(__dirname, '../priv/static/js') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }, { test: /\.svg$/, use: [ { loader: 'file-loader', options: { mimetype: 'image/svg+xml', outputPath: '../images', name (file) { if (env === 'development' || env === undefined) return '[name].[ext]' else return '[hash].[ext]' } } } ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: '../css/app.css' }), new CopyWebpackPlugin([{ from: 'static/', to: '../' }]) ] });
-
Access to the project_name\assets\js directory of the project.
cd js
-
Create a new file with index.js as file name.
touch index.js
-
Edit the index.js file and place the following code:
// Dependencies import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class App extends Component { render() { return ( <div>Ok</div> ); } } ReactDOM.render( <App />, document.getElementById('root') );
-
Create the components, pages and data directories.
mkdir components && mkdir pages && mkdir data
-
Edit the app.js file and after the last
importplace the following code:import css from "../css/app.css" import { index } from "./index"
-
Access to the project_name\config directory of the project.
cd ..\..\config
-
Edit the dev.exs file and replace the value of the
watcherskey with the following code:watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin", "--color", cd: Path.expand("../assets", __DIR__)]]
-
Configure in the dev.exs and test.exs files the credentials for the databases to be created.
config :project_name, ProjectName.Repo, adapter: Ecto.Adapters.Postgres, username: "postgres", password: "pass", database: "project_name_dev", hostname: "localhost", pool_size: 10
-
Access to the project_name\lib\project_name_web\templates\layout directory of the project.
cd ..\lib\project_name_web\templates\layout
-
Edit the app.html.eex file and replace the tag
<body>and its content with the following code:<body> <main role="main"> <%= render @view_module, @view_template, assigns %> </main> <script src="<%= static_path(@conn, "/js/app.js") %>"></script> </body>
-
Access to the project_name\lib\project_name_web\templates\page directory of the project.
cd ..\page
-
Edit the index.html.eex file and replace all the content with the following code:
<div id="root"></div>
-
Access to the root directory of the project: project_name.
cd ..\..\..\..
-
Edit the mix.exs and add the following dependencies:
{:plug_cowboy, "~> 1.0"}, {:absinthe, "~> 1.4.13"}, {:absinthe_ecto, "~> 0.1.3"}, {:absinthe_plug, "~> 1.4.6"}, {:absinthe_phoenix, "~> 1.4.3"}
Delete the following dependency in the same file:
{:cowboy, "~> 1.0"}
-
Access to the project_name\lib\project_name_web directory of the project.
cd lib\project_name_web -
Edit the router.ex file and add the following code after de last
scope:if Mix.env == :dev do forward "/graphiql", Absinthe.Plug.GraphiQL, schema: ProjectName.Graphql.Schema, interface: :advanced, context: %{pubsub: ProjectName.Endpoint} end
Do not forget to replace the module name
ProjectNamein this code with the actual project name. -
Access to the project_name\lib\project_name directory of the project.
cd ..\project_name
-
Create the graphql directory and access it.
mkdir graphql && cd graphql
-
Create a new file with queries.ex as file name.
touch queries.ex
-
Edit the queries.ex file and place the following code:
defmodule ProjectName.Graphql.Queries do @moduledoc false use Absinthe.Schema.Notation object :queries do end end
Do not forget to replace the module name
ProjectNamein this code with the actual project name. -
Create a new file with mutations.ex as file name.
touch mutations.ex
-
Edit the mutations.ex file and place the following code:
defmodule ProjectName.Graphql.Mutations do @moduledoc false use Absinthe.Schema.Notation object :mutations do end end
Do not forget to replace the module name
ProjectNamein this code with the actual project name. -
Create a new file with subscriptions.ex as file name.
touch subscriptions.ex
-
Edit the subscriptions.ex file and place the following code:
defmodule ProjectName.Graphql.Subscriptions do @moduledoc false use Absinthe.Schema.Notation object :subscriptions do end end
Do not forget to replace the module name
ProjectNamein this code with the actual project name. -
Create a new file with schema.ex as file name.
touch schema.ex
-
Edit the schema.ex file and place the following code:
defmodule ProjectName.Graphql.Schema do @moduledoc false use Absinthe.Schema import_types ProjectName.Graphql.Queries import_types ProjectName.Graphql.Mutations import_types ProjectName.Graphql.Subscriptions import_types Absinthe.Plug.Types import_types Absinthe.Type.Custom query [], do: import_fields :queries mutation [], do: import_fields :mutations subscription [], do: import_fields :subscriptions end
Do not forget to replace the module name
ProjectNamein this code with the actual project name. -
Access to the root directory of the project: project_name.
cd ..\..\..
-
Update and compile the new dependencies of the Phoenix project.
mix deps.get && mix deps.compile
-
Create the project database.
mix ecto.create
To verify that the project has been correctly configured, the server must be initialized with the command:
mix phx.serverIn the browser enter the URL localhost:4000. If it displays a blank page with a single text "Ok" and shows no errors or warnings in both the server and the browser console, the configuration has been successful.
This is a tool that allows you to automatically create and configure a new project. This is a Bash script, to use it it is necessary to execute it in a terminal that can execute this interface.
Download link: S1.project.sh
To be able to run it on Unix-based systems it will be necessary to give it execution permissions:
chmod +x s1.project.shUnder redaction.
Under redaction.

