Single page application
What did I need to learn to create a single page application for the first time?
We had a new project to do and its layout asked for a single page application. So we chose elixir + phoenix to create the API and React to create the frontend.
This project is my first application written in React which is used by thousands of people. Many challenges ahead. So I had to learn some things to create a sustainable project.
Package manager
We had to choose between NPM and Yarn. I realized that the latest NPM version is as good as Yarn's latest version, so we decided to go with NPM.
Components
Following the React philosophy and its best practices, we are using components for everything, so we can reuse them, creating separated tests and create separated stylesheets, keeping the project organized.
React
React is an open source library developed by Facebook to create user interfaces. It allows us to manage each component with its state and props.
React state
The component state is an object accessible only by the component itself and it allows data to be stored inside the component to control any element or simply store data to send it to an external service. Example:
React props
The component props are properties passed on component renderization. It is util to use different values on each component usage. Example:
Redux
It is a library that allows state to be shared among all components. It is similar to component state, but it can be accessed in any an application-wide context. Example:
React Router
This library allows us to navigate along pages rendering different components, storing the URL in the browser address bar, allowing redirects and reading the current url to render the correct component, when a user reloads the page, per example. Example:
Webpack
This library is responsible for compiling all javascript modules inside the application, including the ones that process css and images files. It receives inputs, loaders and returns an output. The inputs are javascript, css, images, fonts. The loaders are the modules that will process these inputs. The outputs are the input processed by the loaders.
Our setup transpiles JS using Babel, CSS using StyleLoader, CSSLoader, PostCSS, images using image-webpack-loader. Also it runs our linters before each transpilation. We are using webpack-dev-server to serve the assets in development environment. It also implements the hot reloading after a file is modified.
After compiling everything, we have two files: app.js and app.css, compacted and minified.
PostCSS
It allows us to use css linters, imports, variables, autoprefixer and to minify our CSS files.
If you want to see our webpack.config.js, it is here.
CSS Architecture
Our challenge is keeping everything componentized and as generic as possible. Here’s the organization we chose to keep the project sustainable:
- Common stylesheet: all stylesheets that are used in all pages.
- Components: each JS component has it own stylesheet.
- Layouts: some components have the same layout, so we created some components to be used as parent components. They have separated stylesheets too.
- Pages: some pages have a particular stylesheet and it won't be reused.
Flexbox
The application layout is really unconventional. There are many floating elements and everything should work perfectly in mobile devices. Flexbox definitely saved our lifes. A short definition was extracted from css-tricks.com:
The
Flexbox Layout
(Flexible Box) module (currently a W3C Last Call Working Draft) aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word "flex"). https://css-tricks.com/snippets/css/a-guide-to-flexbox
Here some flexbox features:
flex-direction
Options: row, row-inverse, column, column-inverse.
It allows all elements have the same orientation. Example: using row, all divs will be aligned side by side without the need to use float.
wrap
Options: nowrap, wrap, wrap-reverse.
It allows distribute the elements in one line or break in lines when the line is full.
justify-content
Options: flex-start, flex-end, center, space-between, space-around, space-evenly.
It allows align the elements along the main axis.
align-items
Options: flex-start, flex-end, center, baseline, stretch.
It allows align the elements along the cross axis.
flex-grow
It allows you define if the element can grow if necessary. The default value is 0.
If all items have
flex-grow
set to 1, the remaining space in the container will be distributed equally to all children. If one of the children has a value of 2, the remaining space would take up twice as much space as the others (or it will try to, at least). https://css-tricks.com/snippets/css/a-guide-to-flexbox
flex-shrink
It allows you define if the element can shrink if necessary. The default value is 1.
align-self
It allows you align an element different than was defined in its container (align-items).
Images
We prioritize using CSS to draw the elements, but when it not possible we prioritize SVG because it is vectorized and the it will render well in any screen size.
For SVG images we configured svgo on image-webpack-loader to remove unnecessary tags and reduce the sizes.
Well, the goal of this article was describe to what I had learned to create a single page application, basic concepts and challenges. I hope you enjoy and we are totally open to discuss best practices and tips to keep the application growing sustainably.
For now I can't share screenshots, but I will update this when I'm able to. Thanks for reading!