Frontend Architecture
├── .github/
│ └── ISSUE_TEMPLATE/
├── app/
│ ├── config/
│ └── settings.py
│ ├── frontend/ # Frontend
│ ├── server/
│ ├── .babelrc # Frontend
│ ├── manage.py
│ ├── requirements.txt
│ ├── package.json # Frontend
│ ├── package-lock.json # Frontend
│ └── webpack.config.js # Frontend
├── dev/
│ ├── django.dockerfile
│ ├── webpack.dockerfile
│ └── dev.env
├── .dockerignore
├── .gitignore
├── jsconfig.json
├── CONTRIBUTING.md
├── docker-compose.yml
├── LICENSE
└── README.md
Overall project structure
├── frontend/
│ ├── src/
│ ├── assets/
│ ├── components/
│ ├── Apps.js
│ └── <Components>/
│ ├── pages/
│ ├── templates/
│ └── index.html
│ ├── index.js
│ └── index.scss
│ ├── static
│ └── templates
├── .babelrc
├── package-lock.json
├── package.json
└── webpack.config.js
Frontend Architecture
Summary
Frontend Tech Stack: React, Babel, Webpack, HTML, CSS, JS
The over ninety percent of our frontend architecture is housed in our frontend/
directory. This directory is a Django app, which is a set of files that can be ported to any Django-based application.
Since our frontend is a Django app, it takes advantage of the way Django serves its static assets. Every Django app, by default, looks to the templates/
* directory within the app for the html
template file to serve. This template usually contains <script>
and <style>
tags denoting the location of CSS and JS files. In Django, these files are usually located inside the static/
* directory. Likewise, our frontend app store our templates and static assets within these directories.
Despite these similiarties, however, the files in these two directories should never be manipulated by a developer. These files are automatically generated by an application called Webpack via configurations in webpack.config.js
and .babelrc
.
The files that should be manipulated by developers are housed within the src/
directory. Inside of here are directories for assets/
, componenents/
, pages/
, and templates/
. Each of these directories contains the files which Webpack reads and then bundle into output files for the static/
and template/
directories.
*Note: The
templates/
andstatic/
directories contain within them afrontend/
directory in order to namespace template and static files. Although this serves little purpose for our project, it is a Django convention that prevents Django from confusing thetemplates/
andstatic/
directories from the frontend app vs another app.
Overview of Directories and Files
- frontend/: houses all the frontend files.
- frontend/src/: houses all the files for developers to manipulate. The files here are read by Webpack before being bundled into the
static/
andtemplates/
directories. - assets/: this is where we store all of our miscellaneous files, such as .jpegs, .svgs, .gifs, etc.
- componenents/: this is where we store the files that generate our components, such as buttons and cards. To learn more about this in-depth, read the components section of this guide.
- pages/: contains the React files that pools together various components to generate a page.
- router/: contains the routing logic for the project. It uses the React-Router library.
- templates/: contains html files that are then generated into the regular templates directory. To learn more about how Webpack bundle our files, read the Webpack section of this guide.
- index.js: this file serves as the entry point for all other js files*. This file is read by Webpack, and then bundled into code in the
static
directory. - index.scss: this file serves as the entry point for all other scss files*.
- frontend/static/: automatically generated by Webpack, DO NOT EDIT
- frontend/templates/: automatically generated by Webpack, DO NOT EDIT
- .babelrc: Babel's configuration. To learn more about this, please visit babel's documentation.
- package-lock.json & package.json: These files are created by npm to keep track of dependencies. Please visit npm's documentation to understand them.
- webpack.config.js: Webpack's configuration. To learn more about configuring Webpack, please visit their documentation. To learn about our specific configuration, see the below guide.
*Note: This is technically a lie. In actuality, index.js, reads index.scss as well as the React files, making it the only entryway for all files bundled in the src/
directory.
Components Directory
├── components/
│ ├── Basics/
│ ├── Colors.scss
│ └── Titles.scss
│ ├── Buttons/
│ ├── Buttons.js
│ └── Buttons.scss
│ ├── Cards/
│ ├── Cards.js
│ └── Cards.scss
│ └── <Components>/
A closer look at a theoretical expansion of the components directory
The components directory contains our website components. Each directory in here represents a different class of components, such as Buttons/
* or Cards/
*. Within these directories are the files necessary that creates these components. Likewise, the special Basics/
directory contains small css classes that are reused, but not, technically, components, such as text-size or text-colors.
*Note: These files are capitalized to follow React convention for components. When making new components, please make sure to follow this convention. This convention is in place to help React differentiate between modules vs other types of imports.
Webpack Configurations
...
module.exports = {
mode: 'development',
entry: {
index: "./frontend/src/index.js"
},
output: {
clean: {
keep: '.gitkeep'
},
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'frontend/static/frontend'),
},
devtool: 'inline-source-map',
module: {
rules: ...
},
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: ...
},
plugins: [
new HtmlWebpackPlugin({
filename: '../../templates/frontend/index.html',
template: '/frontend/src/templates/index.html',
}),
],
watchOptions: {
ignored: /node_modules/,
},
}
webpack.config.js (truncated)
Our webpack.config.js
file is one of the most important files to understanding how our frontend architecture comes together. Therefore, this section is dedicated to the settings that we have set for this file. Note that we do not explain all the settings, as some can be found and easily deduced from webpack's configuration and guides documentation.
- entry: the file that is ultimately read by webpack to bundle everything together. This file,
index.js
imports all dependencies and files that makes up our product. Note that advanced multiple entry is possible, should we ever need it. - output: contains configurations for the files that are generated in the
static/
directory - output > clean > keep: clean is usually used to clear away old files before generating new ones (file names are variable to force browser css/js recacheing). However, keep notes files that should not be removed*.
- output > filename: this configures the name of the generated js files. [name] is simply the name of the file noted in the entry configuration, and [contenthash] is a randomly generated string, which forces browser recacheing.
- output > path: the directory to place the generated file. This directory is the one that Django, by default, detects its static files.
- optimization: this contains a catch-all for various ways to enhance either development or deployment. For more on our current configuration, read this guide.
- plugins > HtmlWebpackPlugin: this plugin enables us to dynamically generate templates with the correct
<script>
and<styles>
path by reading the template and outputing it with the path noted by filename. This output path follows Django's default template directory structure. - watchOptions > ignored: configures files to ignore when regenerating watched files.
*Note: The kept .gitkeep
file is there to give an empty file for git to preserve the otherwise empty directory when pushed onto GitHub. As you might have guessed, git does not push empty directories.
Why do we separate Babel from Webpack?
If you have explored documentation from Webpack, you might learn that the babel-loader in module > rules can accept the settings noted in .babelrc
. The reason why we separate these settings into another file is because Webpack is not, in theory, the only application that makes use of these settings. Although we have no other apps that makes use of .babelrc
at the moment, this can change in the future. Therefore, this separation of files is a form of future proofing.
Additional Resources
Sass Documentation
React Documentation
Webpack Documentation
@babel/preset-react Documentation
React Router Documentation