Coding project from the Udemy Course the Complete Junior to Senior Web Developer Roadmap (2020)
This application takes images as input and detects multiple faces using a machine-learning API as output.
- I wrote the code in docker-compose.yml and each Dockerfile. I went beyond the instrcutor's project scope by incorporating the front end into the development Docker container.
- I refactored the application from create-react-app to Next.js. I went beyond the instrcutor's project scope by deciding to migrate this application to Next.js.
- Conventional Commits: standardized messages for git commits
- Code Analysis: working with legacy codebases and refactoring
- Refactoring and migrating create-react-app to Next.js
- Client Side Rendering (CSR) vs Server Side Rendering (SSR)
- Next.js
- Next.js
Link
component for client-side rendering - Next.js shared components for reducing duplication of code among pages
- Next.js
getServerSideProps
for API calls
- Next.js
- Docker
- Dockerfile and
docker
CLI commands - docker-compose.yml and
docker-compose
CLI commands to orchestrate services during development - PostgreSQL in Docker: creating postgres directory with Dockerfile and
CREATE TABLE
commands in login.sql and users.sql to generate sql tables in Docker container
- Dockerfile and
- Redis
- Redis CLI commands
- Redis data types: key:value pairs, hashes, linked lists, sets, and sorted-sets
- Redis in Docker
- Cookies vs. Tokens
- Token-based authentication and session with JSON Web Tokens (JWT) using the jsonwebtoken library and Redis
- Reactstrap for styling with Bootstrap
-
- Files are sent from the server to the client without any rendering (like downloading and executing javascript)
- Once files are processed, some subsequent requests don't need to make another request to the server because it's already downloaded
-
- A fully-rendered page is sent from the server to the client. Javascript is downloaded and executed in the background
-
- Easing load on the servers results in faster responses from the server
- Snappier user experience once the website is loaded
- Native-like application since there are no full page reloads
- (Possible drawback as well) Depending on the user's device and internet connection, can be faster than the server
- Great for large applications since the server's CPU doesn't hold up the event loop
-
- Faster initial loading
- Optimizing search engine optimization (SEO)
- Great for static sites with text
-
- Next.js: optimal for dynamic applications. The 'work' happens on the server
- Gatsby.js: optimal for static text-based websites. The 'work' happens on the developer's machine
- In a monolithic architecture, everything (the database, the back-end API, the front-end client, etc.) is housed on a single server.
- In a microservices architecture, services are split among servers, often in such a way that there is one service per server.
-
- Docker is solution that ensures that developers all work in the same development environment such that the version number of libraries, dependencies, operating systems, etc. are all the same. This decreases the time spent on on-boarding new team members and debugging merged code conflicts due to different development environments.
-
- Before Docker, there were virtualized machines, such as VMware or VirtualBox. Virtual Machines were like having multiple computers (with thier own operating system, kernel, virtual hardware, and software) nested within a master computer. All of these nested computers caused slower runtimes in development and production.
-
- Docker utilizes the idea of containers. Containers are a light-weight option compared to virtual machines since they leverage the host operating system. Removing the redundancy of operating systems unlocks faster runtimes.
- Containers: use the host operating system to generate an isolated environment and to run services defined in an Image.
- Image: is a file with instructions for the container to run certain operations, such as "install Node.js, install dependencies, and then run this application". DockerHub is a good resource for boilerplate Docker Images
- Docker is also a solution that allows time-efficient horizontal scalability of services on production servers since Docker Images can be replicated quickly.
- Docker utilizes the idea of containers. Containers are a light-weight option compared to virtual machines since they leverage the host operating system. Removing the redundancy of operating systems unlocks faster runtimes.
- Is a popular NoSQL database for key:values. Other popular NoSQL databases include cassandra for wide column, neo4j for graph, and mongoDB for document.
- It is an in-memory database for that is ideal for small, short-lived, non-critical data. Having the database in memory makes queries very fast, but also means that data loss is more likely.
- It is often used for caching small data
- Session management and authentication are expected in every application. Users shouldn't have to sign in again after refreshing the page and users shouldn't have access to other user's data.
-
- A cookie is simply a random string
- The browser sends a POST request to the server with valid login data, a cookie is generated by the server and given to the browser through the Set-Cookie header along with the server response. When the browser sends another request to the server, it also sends along the cookie. The server validates that it generated this cookie (find and deserialize session) and then sends the response to the browser.
- This method is stateful, meaning that both the browser and the server must store the cookie in memory.
- Cookie-based authentication has been the standard for a long time
-
- A token is a random string and contains encrypted data within that string
- The browser sends a POST request to the server with valid login data, a JSON Web Token (JWT) is generated by the server and given to the browser along with the server response. The browser stores this JWT in either session storage or global storage. When the browser sends another request to the server, it also sends along an Authorization Header with Bearer JWT. The servers validates the token using logic (using the
.verify
method) and sends the response to the browser. - This method is stateless. Unlike cookie-based authentication, the server doesn't need to store the token in memory.
- Unlike cookie-based authentication, you can use the same JWT across different APIs from the same website. For example, JWT can support native platforms in iOS or Android and websites.
- One major drawback of using JWTs is decreased security since anyone who intercepts the JWT can decode it (avoid storing sensitive data in a JWT).
- Token-based authentication has gained popularity over recent years and is particularly well-suited for single-page applications
-
- You must add your own API key to connect to Clarifai API. You can grab a Clarifai API key here
- Option A (recommended). Create a .env file in Back_End and add your API key after
CLARIFAI_KEY=
- Option B. Add your API key as a string by replacing
process.env.CLARIFAI_KEY
in line 5 ofBack_End/controllers/image.js
- Make sure you have Docker installed and running on your computer
- Make sure you have PostgreSQL installed and running on your computer. If you installed PostgreSQL with Homebrew, then you can start PostgreSQL with
brew services start postgresql
- Make sure you have Redis installed and running on your computer
- In your terminal, navigate to the root of this repository and run
docker-compose up
(you will have to rundocker-compose up --build
for the first setup phase) - Copy and paste this address http://localhost:3001/ to view the application
docker stop <container name>
that is already running in the background.
docker-compose down
to bring everything down, and start over.
- In your terminal, navigate to the root folder of this repository and run
npm install
- To make git commits, run
npm run commit
to ensure your commit follows the Conventional Commits guidelines
- To access the back-end-api service bash, run
docker-compose exec Back_End bash
while container is up and running in the background - To access the postgres service via the CLI, run
psql postgres://<username>:<password>@localhost:5432/smart-brain
(adjust PORT number if needed) - Alternatively, to access the postgres service with a GUI application like PSeqeul:
- To access the redis service, run
docker-compose exec redis redis-cli
-
docker build -t name_of_container .
to create the containerdocker run -it name_of_container
to access the shell of the containerdocker run -it -d name_of_container
to run container in background anddocker exec -it container_id_hash bash
to access the bash of the containerdocker stop container_id_hash
to stop the containerdocker ps
to print read-out of containers runningdocker run -it -p 3000:3001 name_of_container
for port forwarding. The-p
stands for port,3000
represents the port of the container, and3001
represents the port on your local machine. You can now visit localhost:3001
-
docker-compose up --build
to create the containerdocker-compose up -d
to run container in background anddocker-compose exec name_of_container bash
to access the bash of the containerdocker-compose down
to stop all services
-
redis-server
to initialize server andredis-cli
to access the command line interfaceSET name_of_key value
to create a key:value pair andMSET name_of_key value ...
to create multiple key:value pairsGET name_of_key
to retrieve the value andMGET name_of_key value ...
to retrieve multiple valuesEXISTS name_of_key
to check the existenence of the keyDEL name_of_key
to delete the key:value pairHSET name_of_field name_of_key value ...
to create a hash field andHGET name_of_field name_of_key
to retrieve valueLPUSH name_of_linked_list value
to add node to to the left andRPUSH name_of_linked_list value
to add node to to the rightLRANGE name_of_linked_list start stop
to retrieve the the values of the linked list from the specified start to the specified endLTRIM name_of_linked_list start stop
to delete nodes from the specified start to the specified end andRPOP name_of_linked_list
to delete the rightmost nodeSADD name_of_set values ...
to create an unordered set of values. Sets do not allow for repeated values.SMEMBERS name_of_set
to retrieve the the values of the setSISMEMBER name_of_set value
to check the existenence of the value within the setZADD name_of_key value_of_score name_of_member
to add a score and a member to a set of values ordered least to greatest.ZRANGE name_of_key start stop
to retrieve the the members of the set from the specified start to the specified end and to display them in ascending order.ZRANK name_of_key name_of_member
to retrieve the rank of the specified member within the ordered set.
- Section 8: SPA vs Server Side Rendering, Section 10: Code Analysis, Section 11: Docker, Section 12: Redis, Section 13: Sessions + JWT of the Udemy Course the Web Developer Bootcamp