July 03, 2018
This is the first post in a series dedicated to building modern web applications with React and Python, using a GraphQL API.
As an example, we’re going to create a simple web-based chat application (think of it as a Slack clone).
Let’s start by creating our project folder and git repository:
mkdir yawc
cd yawc
git init
Aso create a .gitignore
file containing the following:
*~
*.pyc
node_modules
We’re ready to create our first commit:
git add .gitignore
git commit -m 'Initial'
Let’s proceed to create a new Neutrino project.
The project is going to be in a sub-folder of the main repository, so we can have both client and server code in the same repository, for convenience:
npx @neutrinojs/create-project ./web
...
? 🤔 First up, what would you like to create? A web or Node.js application
? 🤔 Next, what kind of application would you like to create? React
? 🤔 Would you like to add a test runner to your project? Jest
? 🤔 Would you like to add linting to your project? StandardJS rules
...
It’s now time to start customizing our configuration. Open
.neutrinorc.js
and make the following changes to the use
exported variable.
module.exports = {
use: [
'@neutrinojs/standardjs',
['@neutrinojs/react', {
devServer: {
host: '127.0.0.1',
port: 8000,
https: false,
},
html: {
title: 'yawc'
}
}],
// ...
]
};
This is required in order to support navigation to deep-nested pages, eg /foo/bar/baz
:
// Use absolute paths or it will break on nested pages...
(neutrino)=> {
neutrino.config.output.publicPath("/");
},
First, let’s install the required dependencies:
yarn add --dev @neutrinojs/style-loader autoprefixer node-sass postcss-loader sass-loader
And add the relevant configuration in .neutrinorc.js
:
['@neutrinojs/style-loader', {
test: /\.global\.(css|sass|scss)$/,
modulesTest: /(?<!\.global)\.(css|sass|scss)$/,
modules: true,
css: {
localIdentName: '[local]--[hash:base64:8]',
},
loaders: [
{
loader: 'sass-loader',
useId: 'sass',
options: {
includePaths: ['node_modules', 'src'],
localIdentName: '[local]--[hash:base64:8]',
}
},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
]
}
}
]
}]
./src
This allows to use absolute imports for our application code.
import Foo from 'components/Foo'; // Good
import Foo from '../../../components/Foo'; // Bad
Add this to .neutrinorc.js
:
(neutrino) => {
neutrino.config.resolve
.modules
.add(neutrino.options.source);
}
We’re going to use eslint configuration from Create React App.
Install dependencies:
yarn add --dev @neutrinojs/eslint eslint-config-react-app@^2.1.0 eslint-plugin-flowtype@^2.49.3 eslint-plugin-jsx-a11y@^5.1.1 eslint-plugin-react@^7.1.0 eslint-plugin-import@^2.6.0
Add this to .neutrinorc.js
:
['@neutrinojs/eslint', {
eslint: {
plugins: ['import', 'flowtype', 'jsx-a11y', 'react'],
rules: {
semi: ['error', 'always'],
},
baseConfig: {extends: ['eslint-config-react-app']},
}
}]
We’re going to use bootstrap as CSS framework for our application.
Install dependencies:
yarn add bootstrap
Then proceed to create src/index.global.scss
(note the
.global.scss
extendsion, needed to skip it from being loaded as a
module):
// Feel free to customize any variables up here
@import "~bootstrap/scss/bootstrap";
Then make sure it is imported from src/index.js
:
import './index.global.scss';
I usually rename *.jsx
files to *.js
for personal preference.
You can also rename App.css
to App.scss
to benefit from the full power of SCSS.
Make sure you adjust your App.js
accordingly!
import styles from './App.scss'
Also, remember to update your JSX code to use the imported class names, instead of string literals:
// Old
<div className="App"> ... </div>
// New
<div className={styles.App}> ... </div>
Now you can proceed creating the rest of the UI components as needed.
You can see the end result on GitHub at: https://github.com/rshk/yawc/tree/master/web
In Day #2, we’ll discuss how to create our back-end service.
Written by Samuele Santi, who is using technology to make the world a better place. You can follow him on Twitter @_rshk