Skip to content

MEAN Stack (Mongo / Express / Angular / NodeJS): Developers Blog. (Demo on Heroku).

Notifications You must be signed in to change notification settings

Raigyo/mean-stack-whisky

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MEAN Stack: Developers Blog

April / May 2021

🔨 Blog for developers using Node and Express, MongoDB and Mongoose as ODM, and Angular on Client side (MEAN Stack). From udemy: La MEAN stack par la pratique - Samir Medjdoub / Code Concept with some improvements.


Mean Stack refers to a collection of JavaScript technologies used to develop web applications. Therefore, from the client to the server and from server to database, everything is based on JavaScript. MEAN is a full-stack development toolkit used to develop a fast and robust web applications.

MEAN is a user-friendly stack which is the ideal solution for building dynamic websites and applications. This free and open-source stack offers a quick and organized method for creating rapid prototypes for web-based applications.

MEAN is comprised of four different technologies:

  • MongoDB express is a schemaless NoSQL database system
  • Express JS is a framework used to build web applications in Node
  • AngularJS is a JavaScript framework developed by Google
  • Node.js is a server-side JavaScript execution environment

logo

With this app, developers can register and login to add and share some articles about technologies, languages, librairies and so on.

The homepage displays all the articles (extracts). When clicking on them, we have access to the complete article. Authors can add, delete or update their own articles. Admin have the right to do the same but for all authors.

Angular is the part that manage displaying of the views according to events. But evything is Managed with the node server including session management (passport), password encryption and credential validation (Mongoose schemas) or user registrations, sending the articles of the author only or all to the admins, check size and mime of the images (Multer) or send errors to the client side.

Test online

Test the application on Heroku.

You can test the app using these credentials if you don't want to register:

User name: special-guest

Password: MeanStack-2021-05-25

NB: due to the fact that the application is hosted on Heroku using external services like MongoDB Atlas, it can be slow to start (services use cold start) and when running.

logo

logo

logo

logo

logo

Test localy

With file uploads and MongoDB on local:

Clone and use dev-version branch.

With cloudinary and MongoDB Atlas instead, clone main.

Start server

You need MongoDB installed for dev-version.

sudo service mongodb start

From root: cd server

npm install

npm start

The server should run at http://localhost:3000.

Start client app

From root: cd client

npm install

npm start

The app should run at http://localhost:4200.

Whatever the version, environment variables will have to be change from both server and client side following the exemples.

logo

Files and components: Front End part

  • ./src/app/app.module.ts: import / export all modules used in the application.
  • ./src/app/app-routing.module.ts: routing.
  • ./src/app/material.module.ts: import / export modules related to material design. ./src/app/material.module.ts has to be imported in ./src/app/app.module.ts.

Home

  • ./src/app/app.component.html: <router-outlet> add the content from routing component ./src/app/app-routing.module.ts.

blogposts list

  • ./src/app/models/blogpost.ts: typed interface for Blogpost.
  • ./src/app/services/blogpost.service.ts: request on MongoDB.
  • ./src/app/blogpost-list/blogpost-list.component.ts: observable on Blogpost[].
  • ./src/app/blogpost-list/blogpost-list.component.html: view. Uses routerLink to not reload the page when we click on a link.
  • ./src/environments/environment.ts: images path

blogpost by id

  • ./src/app/models/blogpost.ts: typed schema.
  • ./src/app/app-routing.module.ts: add a route for "blog-posts/:id".
  • ./src/app/services/blogpost.service.ts: request on MongoDB.
  • ./src/app/services/blogpost/blogpost.component.ts: observable on Blogpost. Uses ActivatedRoute to retrieve url and id.
  • ./src/app/blogpost/blogpost.component.html: view.

Exemple to display detail of an object: <div>{{blogPost$ | async | json}}</div>

admin

  • ./src/app/admin/admin.component.html: view with CRUD.
  • ./src/app/admin/admin.component.ts: request on MongoDB. CRUD on all articles.

blogposts create

  • ./src/app/services/blogpost.service.ts: request on MongoDB + subject to refresh ./src/app/admin/admin.component.html. Method upload().
  • ./src/app/blogpost-create/blogpost-create.component.html: view with submission form.
  • ./src/app/blogpost-create/blogpost-create.component.ts: manage FormGroup and dispatching for refresh.

blogposts edit

  • ./src/app/services/blogpost.service.ts: request on MongoDB
  • ./src/app/blogpost-edit/blogpost-edit.component.html: Template driven form
  • ./src/app/blogpost-edit/blogpost-edit.component.ts: Manage upload and updated blogpost

auth

  • ./src/app/auth/auth.component.html: Display login.
  • ./src/app/auth/auth.component.ts: Manage login.
  • ./src/app/models/user.ts: typed interface for login page.
  • ./src/app/services/auth.service.ts: Connect to base url. Manage login/logout/register routes.
  • _./src/app/services/add-cookie.interceptor.ts: HTTP Interceptor: centralizes the sending of the header in each request (used for the cookie).

register

  • ./src/app/register/auth.component.html: Display register.
  • ./src/app/register/auth.component.ts: Manage register.
  • ./src/app/models/user.ts: typed interface for Blogpost.
  • ./src/app/services/auth.service.ts: Connect to base url. Manage login/logout/register routes.

Files and components: Back-end part

  • ./appjs: Express and Mongo connection. Static folders. Session midlewares
  • ./utils/resize.js: Helper to resize images.
  • ./api/models/blogpost.js: Mongoose model for CRUD.
  • ./api/v1/index.js: Routes + Api CRUD.
  • ./auth/models/user.js: Mongoose model for users.
  • ./auth/routes/index.js: Routes + Api users.

Angular / JS concepts

Observable

An observable is source of collections of multiple values pushed when we suscribe.

Observer

An Observer is a consumer of values delivered by an Observable. Observers are simply a set of callbacks, one for each type of notification delivered by the Observable: next, error, and complete.

Subject

A subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.

Pipeable Operators

A Pipeable Operator is a function that takes an Observable as its input and returns another Observable. It is a pure operation: the previous Observable stays unmodified. Subscribing to the output Observable will also subscribe to the input Observable.

Higher-order Observables

We define a higher-order Observable whenever we use data emitted from one Observable to emit another Observable. ... In the code above, we subscribe to the outer Observable but we don't subscribe to the inner Observable. Since Observables are lazy, they won't emit until subscribed.

Modules

In Angular, a module is a mechanism to group components, directives, pipes and services that are related, in such a way that can be combined with other modules to create an application. An Angular application can be thought of as a puzzle where each piece (or each module) is needed to be able to see the full picture.

Ex: ng g m material --flat => Ceate module _src/app/material.module.ts

Components

Components are the main building block for Angular applications. Each component consists of: An HTML template that declares what renders on the page. A Typescript class that defines behavior. A CSS selector that defines how the component is used in a template.

Ex: ng g c blogpost --skip-tests --module=app => Create new blogpost component

Models: Interfaces

We use interfaces instead classes because we don't need behaviors (methods).

Ex: Interface blogpost.ts in _src/app/models

Services

Angular services are singleton objects that get instantiated only once during the lifetime of an application. ... The main objective of a service is to organize and share business logic, models, or data and functions with different components of an Angular application.

Ex: ng g s blogpost => Create new blogpost service

Reactive form vs Template driven form

Template Driven Forms Features

  • Easy to use
  • Suitable for simple scenarios and fails for complex scenarios
  • Similar to AngularJS
  • Two way data binding(using [(NgModel)] syntax)
  • Minimal component code
  • Automatic track of the form and its data(handled by Angular)
  • Unit testing is another challenge

EX: ./src/app/blogpost-create/blogpost-edit.component.html:

Reactive Forms Features

  • More flexible, but needs a lot of practice
  • Handles any complex scenarios
  • No data binding is done (immutable data model preferred by most developers)
  • More component code and less HTML markup
  • Reactive transformations can be made possible such as
  • Handling a event based on a debounce time
  • Handling events when the components are distinct until changed
  • Adding elements dynamically
  • Easier unit testing

EX: ./src/app/blogpost-create/blogpost-create.component.html:

Two way binding

Two-way binding gives components in your application a way to share data. Use two-way binding to listen for events and update values simultaneously between parent and child components.

@Injectable

Dependency Injection is often more simply referred to as DI. The paradigm exists throughout Angular. It keeps code flexible, testable, and mutable. Classes can inherit external logic without knowing how to create it. Any consumers of those classes also do not need to know anything.

DI saves classes and consumers alike from having to know more than necessary. Yet the code is as modular as it was before thanks to the mechanisms supporting DI in Angular.

HTTP Interceptor

The Angular HTTP Interceptor is introduced along with the new HTTPClientModule. The Interceptor helps us to modify the HTTP Request by intercepting it before the Request is sent to the back end. The Interceptor can be useful for adding custom headers to the outgoing request, logging the incoming response, etc.

Serialization

The process whereby an object or data structure is translated into a format suitable for transferral over a network, or storage (e.g. in an array buffer or file format).

startrek

In JavaScript, for example, you can serialize an object to a JSON string by calling the function JSON.stringify().

Dependancies

API

  • express: Fast, unopinionated, minimalist web framework for node.

npm i express

  • eslint: ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code.

npm i eslint --save-dev

npm install --save-dev eslint-config-prettier

  • cors: CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

npm i cors

  • nodemon: nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

npm install --save-dev nodemon

  • mongoDB: MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.

WSL2:

  • sudo service mongodb status: status for checking the status of your database.
  • sudo service mongodb start: start to start running your database.
  • sudo service mongodb stop: stop to stop running your database.

Shell

  • mongo: MongoDB shell

  • show dbs: View databases

  • use [DB_NAME]: Choose databases

  • show collections: View collections

  • db.[COLLECTION_NAME].find({}): View documents in collection

  • mongoose: Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.

npm i mongoose

  • multer: Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files.

npm i multer

  • sharp: The typical use case for this high speed Node.js module is to convert large images in common formats to smaller, web-friendly JPEG, PNG, WebP and AVIF images of varying dimensions.

npm i sharp

  • passport: Passport is Express-compatible authentication middleware for Node.js.

npm i passport cookie-parser express-session passport-local

  • dotenv: PDotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.

npm i dotenv

npm i mongoose-unique-validator

  • argon2: A library to help you hash passwords.

npm i argon2

npm i password-validator

  • cloudinary: Cloudinary is a cloud service that offers a solution to a web application's entire image management pipeline..

npm i cloudinary

Tip

Kill process on port (here 3000)

lsof -i:3000
kill -9 [PID]

APP

  • Angular CLI: The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell.
ng new my-first-project
cd my-first-project
ng serve

npm install -g @angular/cli

ng add @angular/material

npm i @kolkov/angular-editor

npm i @angular/flex-layout

Heroku deploy

Angular build

cd client

ng build --prod --base-href --output-path ./../server/public/client

Server + app

On root:

heroku login

(heroku create my-app)

(heroku git:remote -a my-app)

git add .

git commit -m "my message"

git subtree push --prefix server heroku master

If errors, check with:

heroku logs --tail

Useful links

About

MEAN Stack (Mongo / Express / Angular / NodeJS): Developers Blog. (Demo on Heroku).

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published