Thư viện thành phần mô-đun css

Có nhiều cách khác nhau để cung cấp kiểu dáng cho các thành phần React, chẳng hạn như nhập CSS đơn giản, sử dụng các thành phần được tạo kiểu, Mô-đun JS-in-CSS hoặc CSS. Tất cả đều có những ưu điểm và nhược điểm khác nhau

Đối với tôi, có vẻ như Mô-đun CSS cung cấp giải pháp tổng thể tốt nhất cho người mới sử dụng đến trung cấp. Chúng tôi có thể sử dụng cú pháp CSS tiêu chuẩn, cho phép lập trình sao chép và dán hiệu quả, đồng thời chúng tôi có thể yên tâm về hiệu suất phía máy khách tốt

Trong bài viết này, tôi sẽ xem xét một số cân nhắc khi sử dụng Mô-đun CSS. Cụ thể là tôi quan tâm đến việc xem xét điều này theo cách bất khả tri về khuôn khổ. Nhiều khung, chẳng hạn như Tiếp theo. js cung cấp hỗ trợ tích hợp sẵn cho các mô-đun CSS. Tuy nhiên, tôi nghĩ rằng rất đáng để khám phá cách các mô-đun CSS có thể được sử dụng trong các ứng dụng Vanilla React. Tôi cũng sẽ khám phá cách các mô-đun CSS có thể được sử dụng trong kết xuất phía máy chủ không liên quan đến khung

Khái niệm cơ bản về mô-đun CSS

Mô-đun CSS đơn giản là các tệp CSS đơn giản mà chúng ta có thể phát triển cùng với các thành phần React của mình

.myclass {
  padding: 10px;
}

Để sử dụng các Mô-đun CSS trong các thành phần React, chúng tôi yêu cầu chúng tôi 'nhập' tệp nguồn CSS mà chúng tôi muốn sử dụng

import React from 'react';
import styles from './MyComponent.module.css';

Sau đó, chúng tôi có thể tham chiếu các kiểu từ tệp CSS khi khai báo các thành phần của mình

return <div className={styles.myclass}></div>;

Điều kỳ diệu của các mô-đun CSS là các tên lớp chung chẳng hạn như 

import React from 'react';
import styles from './MyComponent.module.css';
6 được dịch thành các tên lớp duy nhất được đảm bảo không xung đột với bất kỳ tên lớp nào khác mà chúng tôi có thể muốn tải trên trang của mình. Chẳng hạn, 
import React from 'react';
import styles from './MyComponent.module.css';
6 có thể chuyển thành 
import React from 'react';
import styles from './MyComponent.module.css';
8

Khi sử dụng các mô-đun CSS để xác định thành phần React của chúng tôi, chúng tôi gặp phải hai thách thức

  • Chúng tôi cần hướng dẫn trình đóng gói của mình chuyển đổi CSS thành CSS với các tên lớp được tạo và bao gồm CSS đó cùng với các tệp khác mà chúng tôi gửi cho khách hàng
  • Chúng tôi cần đảm bảo rằng khi chạy mã nguồn JavaScript của mình, các tên lớp được tham chiếu được giải quyết chính xác (e. g. truy cập của 
    import React from 'react';
    import styles from './MyComponent.module.css';
    
    9 nhập ở trên)

Trong phần sau, tôi mô tả cách chúng ta có thể đáp ứng những thách thức này trong các giai đoạn phát triển và triển khai khác nhau

Mô-đun CSS IntelliSense

Rất hữu ích khi có thể tra cứu tên lớp mà chúng tôi đưa vào CSS của mình khi viết mã thành phần React. Điều này giúp chúng tôi không phải sao chép và dán tên lớp từ CSS của chúng tôi vào JavaScript và tránh nhầm lẫn

Đối với điều này, chúng ta có thể sử dụng thư viện typescript-plugin-css-modules

Thư viện thành phần mô-đun css

Chỉ cần thêm thư viện này vào dự án của bạn

yarn add -D typescript-plugin-css-modules

Sau đó mở rộng tệp 

return <div className={styles.myclass}></div>;
0 của bạn bằng plugin sau

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "typescript-plugin-css-modules"
      }
    ]
  }
}

Điều này sẽ hỗ trợ tra cứu tên lớp từ các tệp CSS trong khi làm việc với mã TypeScript/JavaScript của bạn trong các trình soạn thảo khác nhau, chẳng hạn như VSCode

Lưu ý rằng plugin này chỉ có tác dụng trong quá trình phát triển và sẽ không phát hiện bất kỳ lỗi nào trong thời gian biên dịch (xem vấn đề về TypeScript #16607)

Biên dịch các mô-đun CSS

Trình biên dịch TypeScript sẽ báo lỗi khi chúng tôi cố gắng nhập một tệp vào một tệp 

return <div className={styles.myclass}></div>;
1 hoặc 
return <div className={styles.myclass}></div>;
2 không phải là tệp TypeScript

Để giải quyết lỗi này, chúng tôi cần xác định mô-đun 

return <div className={styles.myclass}></div>;
3 hướng dẫn TypeScript cách giải quyết các tệp 
return <div className={styles.myclass}></div>;
4 mà chúng tôi muốn nhập

declare module '*.css';

Chúng tôi cũng có thể cung cấp thêm cho TypeScript một số gợi ý về cấu trúc của dữ liệu đã nhập, chẳng hạn như bằng cách sử dụng khai báo sau thay vì khai báo đơn giản ở trên

declare module '*.css' {
  const classes: { [key: string]: string };
  export default classes;
}

Đảm bảo rằng tệp 

return <div className={styles.myclass}></div>;
3 bạn khai báo thực sự được tải bởi TypeScript. Cách dễ nhất để thực hiện việc này là mở rộng mảng 
return <div className={styles.myclass}></div>;
6 trong tệp 
return <div className={styles.myclass}></div>;
0 của bạn

{
  "include": [
    "./src/typings.d.ts"
  ]
}

Mô-đun CSS cho kết xuất phía máy chủ (Node. js)

Khi chúng tôi đã dịch mã TypeScript của mình thành JavaScript, chúng tôi có thể chạy mã trong môi trường trình duyệt hoặc sử dụng Node. js. Phần này thảo luận về cách chạy mã JavaScript tham chiếu các tệp CSS trong Node. js. Phần tiếp theo sẽ thảo luận về cách chạy mã này trong trình duyệt

Với sự ra đời của kết xuất phía máy chủ, có khả năng chúng ta cần chạy mã thành phần React của mình trong môi trường máy chủ. Nếu cố gắng làm điều này, rất có thể chúng ta sẽ gặp phải 

return <div className={styles.myclass}></div>;
8 chẳng hạn như sau

C:\Users\Max\repos\my-awesome-project\src\index.css:1
.myclass {
^

SyntaxError: Unexpected token '.'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1033:15)

Điều này là do Nút. js không thể tải mã nguồn cho tệp CSS của chúng tôi; . Có một số cách để giải quyết vấn đề này, nhưng tôi thấy cách dễ nhất là kết nối với cơ chế mà Node tải các tệp nguồn được yêu cầu

Để làm điều này dễ dàng hơn, tôi đã phát triển một thư viện đơn giản node-css-require. Thư viện này có thể được sử dụng theo hai cách

Đầu tiên, chúng ta có thể nhập thư viện trong mã của mình và chạy phương thức 

return <div className={styles.myclass}></div>;
9. Điều này cần phải xảy ra trước khi tải bất kỳ tệp nguồn nào có nhập CSS

import { register } from 'node-css-require';

register();

Ngoài ra, chúng ta có thể xác định một tệp 

yarn add -D typescript-plugin-css-modules
0 với nội dung sau

import React from 'react';
import styles from './MyComponent.module.css';
0

Và sau đó yêu cầu tải thư viện này theo cách thủ công khi gọi Nút. js CLI

import React from 'react';
import styles from './MyComponent.module.css';
1

Khi triển khai mã phía máy chủ, chúng tôi thường muốn sử dụng một gói để giảm thiểu kích thước của mã mà chúng tôi cần triển khai. Các gói phổ biến là webpack và esbuild

Chúng tôi cần hướng dẫn trình đóng gói của mình cách xử lý các tệp CSS đã nhập. Để hiển thị phía máy chủ, chúng tôi sẽ cần hai đầu ra từ gói

  • Tệp JavaScript chứa ánh xạ từ tên lớp gốc sang tên lớp được tạo
  • Tệp CSS chứa CSS với tên lớp được tạo cho tất cả các thành phần có trong (các) trang mà chúng tôi muốn kết xuất

Có một số plugin hỗ trợ việc này, chẳng hạn như css-loader cho webpack hoặc esbuild-css-modules-plugin cho esbuild

Tuy nhiên, tôi thấy các plugin hiện có khá phức tạp và khó hoạt động trong các thiết lập tùy chỉnh và thường tập trung vào gói các mô-đun CSS cho ứng dụng khách hơn là ứng dụng máy chủ. Vì vậy, tôi đã tạo một thư viện nhỏ khác esbuild-css-modules-server-plugin

esbuild-css-modules-server-plugin là và cung cấp cho chúng tôi mọi thứ chúng tôi cần để hiển thị phía máy chủ

Để sử dụng plugin này, chỉ cần cài đặt nó vào dự án của bạn rồi thêm nó vào mảng 

yarn add -D typescript-plugin-css-modules
1 trong cấu hình esbuild

import React from 'react';
import styles from './MyComponent.module.css';
2

Plugin này đảm bảo rằng tất cả các tệp nguồn JavaScript được đóng gói chính xác, ví dụ:. g. rằng 

yarn add -D typescript-plugin-css-modules
2 các mục nhập được phân giải thành các đối tượng có thể được sử dụng trong quá trình kết xuất phía máy chủ để phân giải tên lớp ban đầu thành tên lớp được tạo. Bằng cách sử dụng lệnh gọi lại 
yarn add -D typescript-plugin-css-modules
3, chúng tôi có thể thu thập tất cả CSS đã tạo và lưu trữ tệp này cùng với JavaScript đã tạo của chúng tôi để máy chủ sử dụng

Ví dụ: khi chuyển mã đến một chức năng không có máy chủ, chúng tôi có thể triển khai tệp 

yarn add -D typescript-plugin-css-modules
4 với tất cả logic JavaScript và đặt tệp 
yarn add -D typescript-plugin-css-modules
5 bên cạnh tệp đó, chúng tôi có thể gửi cho khách hàng khi được yêu cầu. Ngoài ra, chúng tôi cũng có thể tải 
yarn add -D typescript-plugin-css-modules
5 lên một trang web/CDN tĩnh

Mô-đun CSS cho gói phía máy khách

Xử lý các Mô-đun CSS ở phía máy khách dễ dàng hơn nhiều so với làm việc với chúng ở phía máy chủ. Ngược lại với Nút. js, trình duyệt vốn hiểu CSS nên chúng ta dễ dàng tải các tệp CSS theo yêu cầu

Tuy nhiên, vẫn còn một số công việc chúng tôi phải làm để làm cho mã của chúng tôi có thể thực thi được trong trình duyệt. Đối với điều này, một lần nữa chúng ta có thể sử dụng gói. Trình tải css hoặc plugin esbuild-css nói trên thường hoạt động tốt cho gói phía máy khách

Tuy nhiên, tôi lại soạn một thư viện nhỏ, nhẹ để giúp đóng gói mã của chúng tôi cho phía máy khách bằng cách sử dụng esbuild

esbuild-css-modules-client-plugin làm mọi thứ chúng tôi cần cho gói phía máy khách

Chúng ta có thể sử dụng thư viện như sau

import React from 'react';
import styles from './MyComponent.module.css';
3

Plugin này hoạt động bằng cách thêm CSS cần thiết khi tải trang. Lý tưởng nhất là chúng tôi muốn kết hợp điều này với esbuild-css-modules-server-plugin. Khi chúng tôi biên dịch tất cả CSS ở phía máy chủ và gửi mã này cùng với mã giao diện người dùng của mình, chúng tôi chỉ cần tải CSS đã tạo một lần trên trang của mình. Trong trường hợp đó, không cần thiết phải tải CSS đã chèn khi tải thành phần

Nếu chúng tôi đã gửi CSS được tạo cùng với gói của mình, thì chúng tôi có thể sử dụng tùy chọn 

yarn add -D typescript-plugin-css-modules
7 khi tải plugin

import React from 'react';
import styles from './MyComponent.module.css';
4

Nếu muốn tạo JavaScript phía máy khách và CSS đi kèm trong một lần, thì bạn có thể sử dụng cả esbuild-css-modules-server-plugin và esbuild-css-modules-client-plugin

import React from 'react';
import styles from './MyComponent.module.css';
5

Chỉ cần lưu trữ CSS đã tạo bằng tệp JavaScript do esbuild tạo và triển khai chúng cùng nhau

Suy nghĩ cuối cùng

Cách dễ nhất để sử dụng các mô-đun CSS là cung cấp cho chúng tôi hỗ trợ được cung cấp trong các khung, chẳng hạn như Tiếp theo. js hoặc Tạo ứng dụng React. Tuy nhiên, có rất nhiều sự phức tạp tiềm ẩn trong các mô-đun CSS có thể dẫn đến hành vi và lỗi không mong muốn

Trong bài viết này, tôi nhằm mục đích cung cấp một cái nhìn cấp thấp hơn về các mô-đun CSS. Tôi muốn chứng minh rằng chúng ta có thể đạt được bất cứ điều gì chúng ta cần với tương đối ít dòng mã. Ba thư viện tôi cung cấp đều rất đơn giản và bao gồm một tệp nguồn ngắn, duy nhất

Mặc dù những điều này không có khả năng giải quyết tất cả các vấn đề của bạn một cách kỳ diệu, nhưng tôi hy vọng rằng bằng cách khám phá mã nguồn của những điều này, bạn có thể tìm ra giải pháp cho vấn đề duy nhất của mình

Tôi đã khám phá điều này trong bối cảnh xây dựng một khung nhẹ để kết xuất phía máy chủ Serverless cho các ứng dụng React. Những thách thức chính trong việc này là hỗ trợ cả gói để triển khai lên đám mây cũng như phát triển cục bộ và cả cách hiển thị động các trang ở phía máy chủ

Nếu bạn muốn khám phá khung, bao gồm hỗ trợ từ đầu đến cuối, vui lòng xem mẫu Kết xuất phía máy chủ của Goldstack