Điều React luôn giữ kín trong tim

■ Mở đầu

Ngồi viết bài khi đang nghĩ vu vơ chuyện con gà hay quả trứng có trước, mình phân vân chưa biết sẽ chọn chủ đề gì để chúng ta có thể cùng nhau bàn luận. Nhớ có lần một người anh của mình từng chia sẻ:

- Viết code thì dthôi, viết code để ti ưu mi khó !

Cơ mà trước khi muốn tối ưu thì phải hiểu nó đã. Thì vẫn là câu chuyện xoay quanh anh bạn ReactJS, nhưng sẽ quay về thuở sơ khai khởi tạo dự án bằng Create React App, tìm hiểu về:

React - Behind the scenes,
Điều React luôn giữ kín trong tim :v 

nhé, có được không nào 😄))

Trong bài viết này, với folder structure được tạo bởi Create React App (v4.0.1), chúng mình sẽ cùng nhau tìm hiểu về 02 vấn đề sau:

  • Liên kết ngầm giữa index.jsindex.html?
  • index.html "trắng trơn" trên browser?

Bắt đầu thôi!

Đầu tiên, hãy cùng nhau xem lại Create React App một chút!

Bạn nào rành đoạn này rồi thì có thể chuyển qua Mục tiếp theo luôn nhaa ^^

■ Creater React App

Định nghĩa

Theo Official document:

Create React App is an officially supported way to create single-page React applications with no configuration.

Đúng là như vậy, Create React App giúp chúng ta tất cả các bước từ A - Z để khởi tạo một ứng dụng ReactJS: từ setup cho tới config; từ thiết lập Babel dịch JSX cho tới cấu hình webpack, đóng gói các tài nguyên, etc.

Điều duy nhất chúng ta cần làm có lẽ là:

- Run command & enjoy !!!

Quả là sinh ra cho đời bớt khổ mà 😄 😄))

Cấu trúc thư mục

Đây là vị trí các file index.html, index.js mình đề cập đến trong phạm vi bài viết này:

🧊 application
├──────────── package.json
├──────────── public
│            ├──── 📄 index.html
│            ├──── ...
└──────────── src
│            ├──── 📋 index.js
│            ├──── ...
├── ...

Notes:

Nếu bạn chưa từng sử dụng Create React App hay chưa có trải nghiệm nào với ReactJS, hãy thử làm theo hướng dẫn và vọc vạch một chút để nắm được vai trò chính của các files này trước khi đọc tiếp nhé. Chi tiết có thể tham khảo tại đây.

Bây giờ thì chúng ta lần lượt đi tìm câu trả lời cho 02 vấn đề phía trên nào!

■ Liên kết ngầm: index.jsindex.html?

Chúng ta có index.html chứa div#root:

<div id="root"></div>

còn index.js thực hiện render():

const root= document.getElementById("root");
ReactDOM.render(<App />, root);

vậy thì App sẽ được load vào div#root.

Ơ mà khoannn !?! Có gì đó sai sai thì phải... 😕😕

Chúng ta biết rằng một trong những cách sử dụng Javascript trong HTML là khai báo qua thẻ script trong html:

<script src="index.js" ></script>
// hoặc
<script>
    $blogUrl = document.getElementById('haodev.wordpress.com');
</script>

Ấy thế mà trong index.html > body chẳng có khai báo gì cả ngoài div#root.

Mà chưa kể khi chạy ứng dụng và mở trên trình duyệt, View source code đoạn script đó lại xuất hiện?

Như vậy, phải chăng có một liên kết ngầm nào đó giữa index.htmlindex.js?

Câu trả lời đó là nhờ html-webpack-plugin.


Html Webpack Plugin

Plugin này config public/index.htmltemplate được đọc. Plugin này sẽ thêm đoạn script (bundle.js, chunk.js) vào template (trước đó webpack đã cung cấp cho plugin một đường dẫn khả dụng).

Nói có sách mách có chứng chứ nhỉ 😀))

Vào ngay node_modules/react-scripts/config/webpack.config.js xem lại:

plugins: [
    // Generates an `index.html` file with the <script> injected.
    new HtmlWebpackPlugin(
        Object.assign(
            {},
            {
                inject: true,
                template: paths.appHtml,
            },
         )
    )
]

Chèn script vào file index.html khi npm start.

Quá trình npm start thì xem tại node_modules/.bin:

switch (script) {
    case 'start': {
        const result = spawn.sync(
        'node',
        [require.resolve('../scripts/' + script)].concat(args),
        // ...
    );
}

Vào node_modules/react-scripts/config/paths.js xem html-webpack-plugin đã làm gì với template: paths.appHtml:

module.exports = {
    appHtml: resolveApp('public/index.html'),
    appIndexJs: resolveModule(resolveApp, 'src/index'),
};

Đó là lúc index.html bắt đầu được resolve rồi, script đã được chèn vào template của chúng ta ^^

■ index.html "trắng trơn" trên browser?

Một vấn đề nữa mình muốn chúng ta tìm hiểu, đó là sau khi phát triển ứng dụng, chạy npm run build, miệng nhấp ngụm trà xanh, đầu chắc cú rằng mọi thứ sẽ được compile ra như ý rồi.

Lúc giờ mới chột dạ vì mở trên trình duyệt file build là 1 trang trắng tinh 😞😞.

Để tìm ra nguyên nhân, chạy lệnh npm run eject để xem những gì được thực hiện behind the scenes sau những câu lệnh có-vẻ-là-ngắn-gọn - npm start/ run build/run test - trong 🧊 application/scripts.

Quá trình chạy lệnh npm start sử dụng webpack-dev-server:

// 🧊 application/scripts/start
const WebpackDevServer = require('webpack-dev-server');

Được rồi, bây giờ vào webpack.config.js xem thì thấy đoạn này:

const publicPath = isEnvProduction ? paths.servedPath : isEnvDevelopment && '/';
// "homepage" can be set to "." to enable relative asset paths

Đó chính là lý do, khi chúng ta mở trực tiếp index.html trên trình duyệt thì nhận được "một trang trắng tinh" bởi vì Webpack đang cố tải các static files từ 🧊 application chứ không phải từ 🧊 application/build.

Để khắc phục điều này, chúng ta vào package.json thêm dòng:

{
    // ...
    "homepage":".",
    // ...
}

là ngon ngay 😄😄))

Chạy lại npm run build và mở index.html trên trình duyệt để xem kết quả nhé ❤

■ Kết

Create React App mặc dù không quá mới mẻ với các bạn đã và đang làm việc với React, nhưng cũng chẳng thể phủ nhận việc nó được xem như một công cụ vô cùng hữu hiệu, nhanh gọn và tiết kiệm thời gian cài đặt của chúng ta 😀😀.

Song song với loạt ưu điểm đó, còn muôn vàn những behind the scenes mà chẳng riêng 02 vấn đề kể trên mình mong muốn chúng ta chia sẻ với nhau. Rõ ràng việc quan sát kỹ lưỡng và tìm hiểu một chút về cách hoạt động của các công cụ được sử dụng luôn là điều tốt đúng không nào ^^.

Mình cảm ơn các bạn vì đã đọc bài viết này và hy vọng rằng nó có thể mang lại được giá trị nào đó ^^ Tặng mình 1 upvote để có thêm động lực cho những bài viết sắp tới nha ❤

Chúc các bạn cuối tuần vui vẻ ^^

■ Credits


Happy coding !


All Rights Reserved