Giới thiệu MERN Stack

MERN Stack là gì?

Chắc mọi người cũng đã từng nghe qua MEAN stack. MERN stack là nguyên bộ combo open source các công nghệ đều liên quan đến Javascript là cũng hot nhất hiện nay: MongoDB, ExpressJS, React/React Native, NodeJS. Người ta dùng MERN stack để xây dựng React Universal App. Trong đó:

  1. MongoDB Là một noSQL database hot nhất hiện nay. MongoDB thường đi với Mongoose – một library để giao tiếp với MongoDB dễ dàng hơn.

  2. Node.js

Node.js là một Javascript runtime. Để hiểu được định nghĩa của nó thôi cũng không phải chuyện dễ. Mình có viết một chuỗi bài viết về Node.js, bạn có thể xem thêm nhé

  1. Express Express là web framework được xây dựng bằng Javascript chạy trên nền Node.js. Nó hỗ trợ thêm nhiều tính năng cần có của một web framewok như: routing, middlewares, template engines, vv

  2. React/React Native React là thư viện frontend được viết bằng Javascript, nó là hàng của Facebook đang rất hot hiện nay.

React Native kế thừa từ React và nó là framework để viết ứng dụng di động da nền tảng

Easily build production ready universal apps

Có gì mới trong MERN?

  • Hot Reloading cho các React Components
  • Các đoạn mã được phân chia bởi React Router
  • Hỗ trợ đa ngôn ngữ
  • Hỗ trợ generate code
  • Cấu trúc kiểu mô-đun
  • Ava Test Runner
  • Hỗ trợ Docker
  • Có thể tùy biến phiên bản MERN cho riêng bạn

Hướng dẫn sơ lược

Bắt đầu nhanh

npm install -g mern-cli
mern init your_new_app
cd your_new_app
npm install
npm start

Lưu ý: Vui lòng đảm bảo rằng MongoDB đang chạy. Đối với MongoDB hướng dẫn cài đặt xem tại đây.

Các commands có sẵn

npm run start - chạy development server với tính năng hot reloading được kích hoạt kèm theo npm run bs - bundle code và chạy production server npm run test - chạy test runner npm run watch:test - chạy test runner với watch mode npm run coverage - generates test coverage report npm run lint - chạy linter để kiểm tra các lỗi lint

Cấu trúc file

Webpack Configs

MERN sử dụng Webpack cho việc bundle mô-đun. Có bốn loại cấu hình Webpack cung cấp webpack.config.dev.js (cho development), webpack.config.prod.js (cho production), webpack.config.server.js (cho bundling server in production) và webpack.config.babel.js (dành cho babel-plugin-webpack-loaders cho việc render các assets được đưa vào thông qua webpack).

Cấu hình Webpack là tối thiểu và thân thiện với người mới bắt đầu. Bạn có thể tùy chỉnh và thêm nhiều tính năng cho nó cho production build.

Server

MERN sử dụng express web framework. App được đặt ở server.js nơi chúng ta check NODE_ENV.

Nếu NODE_ENV là development, ta sẽ áp dụng Webpack middlewares cho việc bundling vaf Hot Module Replacement.

Server Side Rendering

Chúng ta sử dụng chức năng phù hợp của React Router để xử lý tất cả các yêu cầu trang để lịch sử trình duyệt có thể hoạt động tốt.

Tất cả các routes được định nghĩa trong client/routes.js. React Router kết xuất các thành phần theo lộ trình yêu cầu.

// Server Side Rendering based on routes matched by React-router.
app.use((req, res) => {
    match({
        routes,
        location: req.url
    }, (err, redirectLocation, renderProps) => {
        if (err) {
            return res.status(500).end('Internal server error');
        }

        if (!renderProps) {
            return res.status(404).end('Not found!');
        }

        const initialState = {
            posts: [],
            post: {}
        };

        const store = configureStore(initialState);

        fetchComponentData(store.dispatch, renderProps.components, renderProps.params).then(() => {
            const initialView = renderToString(
                <Provider store = {store} >
                  <RouterContext {...renderProps}/>
                </Provider>
            );

            const finalState = store.getState();

            res.status(200).end(renderFullPage(initialView, finalState));
        }).catch(() => {
            res.end(renderFullPage('Error', {}));
        });
    });
});

match có hai tham số, đầu tiên là một đối tượng chứa các routes, vị trí và lịch sử và thứ hai là một callback được gọi khi routes được match đến một location.

Nếu có lỗi trong matching nó sẽ trả lại code 500, nếu không tìm thấy kết quả nào, nó sẽ trả lại code 404. Nếu matched, nó sẽ tạo mới một Redux Store instance. Lưu ý: Redux Store mới được đóng lại trên mọi yêu cầu.

fetchComponentData là chức năng thiết yếu. Phải truyền 3 params: đầu tiên là một function gửi của Redux Store, thứ hai là một mảng của các thành phần cần được kết xuất trong tuyến hiện tại và thứ ba là params routes. fetchComponentData thu thập tất cả các nhu cầu (cần là một mảng các hành động được yêu cầu phải gửi đi trước khi hiển thị thành phần) của các thành phần trong tuyến hiện tại. Nó trả về một lời hứa khi tất cả các hành động được yêu cầu được gửi đi. Chúng tôi hiển thị trang và gửi dữ liệu tới khách hàng để hiển thị phía máy khách trong window.__ INITIAL_STATE__.

Client

Thư mục Client chứa tất cả các thành phần được chia sẻ, các routes, các mô-đun.

Components

Thư mục này chứa tất cả các thành phần phổ biến được sử dụng trong suốt dự án.

index.js

Index.js chỉ đơn giản là hiển thị phía máy khách bằng cách sử dụng dữ liệu được cung cấp từ cửa sổ .__ INITIAL_STATE__.

modules

Các mô-đun là cách để tổ chức các mô-đun chuyên biệt cho từng miền trong dự án. Một mô đun điển hình có chứa những điều sau đây

| - Post

  | - __tests__ // all the tests for this module goes here
      | - components // Sub components of this module
          | - Post.spec.js
          | - PostList.spec.js
          | - PostItem.spec.js
          | - PostImage.spec.js
      | - pages
          | - PostPage.spec.js
          | - PostViewPage.spec.js
      | - PostReducer.spec.js
      | - PostActions.spec.js
  | - components // Sub components of this module
      | - Post.js
      | - PostList.js
      | - PostItem.js
      | - PostImage.js
  | - pages // React Router Pages from this module
      | - PostPage
          | - PostPage.js
          | - PostPage.css
      | - PostViewPage
          | - PostViewPage.js
          | - PostViewPage.css
  | - PostReducer.js
  | - PostActions.js

Misc

Importing Assets

Assets có thể được giữ ở nới bạn muốn và bạn có thể import nó vào js files hoặc css files. Và nó sẽ được served bới webpack ở môi trường development và được copy đến dist folder trong quá trình production.

ES6 support

MERN sử dụng babel để transpile code ở cả server lẫn client với plugin stage-0. Vì vậy, bạn có thể sử dụng cả ES6 và trải nghiệm với các tính năng của ES7.

Docker

MERN có docker configurations cho cả development và production.

Để chạy docker ở development:

docker-compose -f docker-compose-development.yml build
docker-compose -f docker-compose-development.yml up

Để chạy docker ở production:

docker-compose build
docker-compose up

Make your MERN

Trong phiên bản này, MERN đã cho phép mern-cli clone không chỉ dự án này mà còn các biến thể của mern-starter như một dự án với MaterialUI hoặc JWT auth. Để tạo phiên bản MERN của bạn, làm theo các bước sau:

  1. Clone this project
git clone https://github.com/Hashnode/mern-starter
  1. Thực hiện thay đổi của bạn. Thêm một package, bổ sung authentication, chỉnh sửa cấu trúc tập tin, thay thế Redux bằng MobX hoặc bất cứ thứ gì khác.

3.Trong phiên bản này, MERN cũng đã thêm vào các code generators. Blueprints cho những generators được đặt tại config/blueprints, và cấu hình được đặt tại mern.json. Hãy chắc chắn để chỉnh sửa chúng nếu cần thiết sau khi bạn thực hiện sửa đổi trong bước trước. Ở phía dưới có giải thích cho cách modify generators.

  1. Clone mern-cli project
git clone https://github.com/Hashnode/mern-cli
  1. Thêm project của bạn vào variants.json và gửi PR.

Modifying Generators

mern.json

Nó chứa một mảng blueprints. Mỗi đối tượng trong đó là cấu hình cho một generator. Một cấu hình blueprint chứa mảng tên, miêu tả, cách sử dụng và tệp tin. Ví dụ một cấu hình blueprint:

{
  "name": "dumb-s",
  "description": "Generates a dumb react component in shared components",
  "usage": "dumb-s [component-name]",
  "files": [
    {
      "blueprint-path": "config/blueprints/dumb-component.ejs",
      "target-path": "client/components/<%= helpers.capitalize(name) %>.js"
    }
  ]
}

Kết luận

Vậy là ta đã có cái nhìn cơ bản về MERN. Đây hứa hẹn sẽ là một stack hay ho đáng để học hỏi và tạo ra những "awesome apps".