Tệp .env lưu trữ các biến môi trường ở định dạng khóa-giá trị đơn giản và tách biệt cấu hình khỏi mã nguồn của ứng dụng. Theo The Twelve-Factor App (2011), cấu hình phải được tách biệt nghiêm ngặt khỏi mã nguồn và các tệp .env đã trở thành tiêu chuẩn của cách tiếp cận này. .env File cho phép đưa các giá trị khác nhau của khóa API, URL máy chủ và cờ xây dựng mà không cần biên dịch lại dự án.
Những điểm chính
.env File là một tệp cấu hình lưu trữ các biến môi trường ở định dạng văn bản đơn giản KEY=VALUE. Mỗi dòng chứa một biến: tên khóa và giá trị của nó, được phân cách bằng dấu bằng.
Các tệp .env giải quyết một vấn đề cơ bản của phát triển hiện đại: các môi trường khác nhau (cục bộ, thử nghiệm, sản xuất) yêu cầu các thiết lập hoàn toàn khác nhau. URL máy chủ API trên máy cục bộ là http://localhost:8080, trên máy chủ sản xuất là https://api.production.com. Nếu các giá trị này được nhúng cứng trực tiếp vào mã ứng dụng, mỗi lần xây dựng cho một môi trường khác đều yêu cầu thay đổi mã nguồn.
Thực hành lưu trữ cấu hình bên ngoài mã chính của ứng dụng đã được chuẩn hóa trong tuyên ngôn The Twelve-Factor App (2011), trong đó xác định các biến môi trường là cách duy nhất đúng để cấu hình một ứng dụng. Theo khảo sát JetBrains Developer Ecosystem (2024), hơn 67% nhà phát triển di động sử dụng tệp .env trong các dự án của họ.
Đối với phát triển di động, .env mang lại lợi thế bổ sung: các giá trị được thay thế ở giai đoạn xây dựng thông qua Gradle (Android) hoặc xcconfig (iOS), cho phép tạo các bản dựng riêng biệt cho phát triển, staging và sản xuất mà không thay đổi mã nguồn.
.env đặc biệt hữu ích khi làm việc nhóm: mỗi nhà phát triển tạo tệp .env cục bộ riêng với các thiết lập cho môi trường của họ (đường dẫn DB cục bộ, khóa API gỡ lỗi), trong khi các thiết lập chung được cố định trong .env.example trong kho lưu trữ. Điều này loại bỏ tình huống sau khi git pull, bản dựng của nhà phát triển bị hỏng do thiếu một biến môi trường mà họ không biết. Thành viên mới của nhóm chỉ cần sao chép .env.example thành .env và điền các giá trị cục bộ của họ.
Định dạng .env cực kỳ đơn giản: mỗi dòng là một biến ở dạng KEY=VALUE. Khoảng trắng xung quanh dấu bằng thường bị bỏ qua, nhưng trong hầu hết các thư viện, chúng được coi là một phần của giá trị, vì vậy tốt hơn là tránh chúng.
Bình luận bắt đầu bằng ký tự # — toàn bộ dòng sau nó bị bỏ qua. Các dòng trống cũng được bỏ qua. Nếu giá trị chứa khoảng trắng, nó được đặt trong dấu ngoặc kép hoặc ngoặc đơn.
# Cài đặt môi trường cơ bản
APP_NAME=MyMobileApp
APP_ENV=development
# Cấu hình API
API_BASE_URL=http://localhost:3000/api
API_TIMEOUT=30000
# Dữ liệu nhạy cảm
DB_PASSWORD=secret_password_123
JWT_SECRET=your_jwt_secret_key
Tất cả các biến trong .env đều là chuỗi, nhưng thư viện tải có thể chuyển đổi chúng sang loại cần thiết. Để thoát các ký tự đặc biệt, sử dụng dấu gạch chéo ngược và dấu ngoặc. Nếu giá trị chứa ký tự # như một phần của văn bản, nó phải được thoát dưới dạng \#.
KEY=value hoặc KEY="value with spaces"PORT=8080DEBUG=trueKEY=line1\
line2DB_URL=${DB_HOST}:${DB_PORT}Khi tải .env, các thư viện có thể thực hiện nội suy biến — thay thế giá trị của một số khóa bên trong các khóa khác. Ví dụ, biến DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@localhost/db sẽ mở rộng DB_USER và DB_PASS từ cùng một tệp.
Phương pháp kết nối .env phụ thuộc vào nền tảng. Android sử dụng plugin Gradle, iOS — tệp cấu hình xcconfig, và các giải pháp đa nền tảng như Flutter — thư viện chuyên dụng.
Trên Android, .env được tải thông qua plugin gradle-dotenv. Plugin đọc .env từ thư mục gốc của dự án và thêm các giá trị vào BuildConfig, sau đó chúng có sẵn trong mã Kotlin hoặc Java thông qua các trường được tạo.
// build.gradle.kts (cấp ứng dụng)
plugins {
id("co.uzzu.dotenv") version "4.0.0"
}
android {
buildFeatures {
buildConfig = true
}
}
kotlin {
// Truy cập trong mã: BuildConfig.API_BASE_URL
buildConfigField("String", "API_BASE_URL",
"\"" + dotenv.get("API_BASE_URL") + "\"")
}
Trên iOS, các biến môi trường thường được cấu hình thông qua các tệp xcconfig. Để tải .env trong Swift, sử dụng thư viện DotEnv hoặc cơ chế Info.plist tích hợp với các khóa tùy chỉnh.
// Tải .env trong dự án Swift
import DotEnv
struct AppConfig {
static func load() {
let env = DotEnv(Bundle.main)
env.load()
let apiURL = ProcessInfo.processInfo
.environment["API_BASE_URL"] ??
"https://default.api.com"
}
}
Cho Flutter có gói flutter_dotenv, tải các biến từ .env trong quá trình khởi tạo ứng dụng. Tệp .env được đặt trong thư mục gốc của dự án và các biến có sẵn thông qua lớp dotenv.
// pubspec.yaml
dependencies:
flutter_dotenv: ^5.1
// main.dart — tải khi khởi động
import 'package:flutter_dotenv/flutter_dotenv.dart';
void main() async {
await dotenv.load(fileName: '.env');
var apiUrl = dotenv.get('API_BASE_URL');
runApp(MyApp(baseUrl: apiUrl));
}
Cả ba cách tiếp cận đều chia sẻ một nguyên tắc chung: .env được tải ở giai đoạn xây dựng hoặc khi ứng dụng khởi động, các giá trị được lưu vào bộ nhớ đệm và sử dụng trong mã thông qua các hằng số được tạo. Điều này ngăn dữ liệu nhạy cảm vào kho lưu trữ.
Cho React Native, sử dụng gói react-native-config, ở giai đoạn xây dựng tự động tạo lớp BuildConfig cho Android và các hằng số trong Info.plist cho iOS từ một tệp .env duy nhất trong thư mục gốc của dự án. Điều này đặc biệt thuận tiện cho các startup sử dụng Expo hoặc bare workflow: một tệp .env duy nhất ở cấp thư mục gốc đủ để tất cả các nền tảng nhận được cùng các biến môi trường mà không cần nhân đôi cấu hình.
Mặc dù có tất cả lợi thế, .env không phải là giải pháp hoàn chỉnh để lưu trữ bí mật trong môi trường sản xuất. Nó cung cấp mức bảo vệ cơ bản, nhưng nếu sử dụng không đúng cách, có thể dẫn đến rò rỉ dữ liệu bảo mật.
Quy tắc quan trọng nhất — .env không bao giờ được đưa vào hệ thống kiểm soát phiên bản của kho lưu trữ. Tệp được thêm vào .gitignore ngay sau khi tạo và chỉ tệp mẫu .env.example với các giá trị trống hoặc giả được commit vào kho lưu trữ.
# .env.example — được commit vào kho lưu trữ
APP_NAME=
APP_ENV=development
API_BASE_URL=http://localhost:3000
API_TIMEOUT=30000
# DB_PASSWORD — không chỉ định ngay cả trong ví dụ!
# JWT_SECRET — không chỉ định ngay cả trong ví dụ!
# .gitignore
# Tệp Dotenv
.env
.env*.local
Cho các dự án sản xuất, khuyến nghị sử dụng các giải pháp quản lý bí mật chuyên nghiệp. .env trong sản xuất chỉ chấp nhận được nếu tệp nằm bên ngoài document-root của máy chủ và có quyền truy cập nghiêm ngặt.
Theo Snyk State of Open Source Security (2024), rò rỉ tệp .env qua kho lưu trữ là nguyên nhân của hơn 12% tất cả các sự cố tiết lộ khóa API trong số các công ty được khảo sát. Sử dụng trình quản lý bí mật chuyên dụng giảm rủi ro này xuống bằng không.
Bảo vệ bổ sung đạt được bằng cách triển khai hook pre-commit sử dụng các công cụ như husky và lint-staged, kiểm tra xem nhà phát triển có vô tình thêm .env vào commit hay không. Các công cụ như git-secrets (AWS) và talisman quét từng commit để tìm các mẫu khóa API, token và mật khẩu, chặn commit nếu phát hiện. Cho đường ống CI, khuyến nghị thêm detect-secrets — một máy quét tự động sẽ không để tệp .env vào kho lưu trữ ngay cả khi nhà phát triển mắc lỗi.
Các câu hỏi thường gặp
Không, .env không nên được commit vào Git. Tệp chứa dữ liệu nhạy cảm và phải được thêm vào .gitignore. Thay vào đó, trong kho lưu trữ đặt .env.example với mẫu của tất cả các biến cần thiết.
.env là tệp thực tế với các giá trị sản xuất và không bao giờ được commit. Tệp .env.example chứa cùng các khóa nhưng với giá trị trống hoặc giả — nó được commit vào kho lưu trữ như một mẫu cho các nhà phát triển mới.
Có, nhưng không khuyến nghị nếu không có bảo vệ bổ sung. Nếu .env được sử dụng trên máy chủ sản xuất, tệp phải được đặt bên ngoài document-root của máy chủ web với quyền truy cập 600 (chỉ chủ sở hữu). Cho các dự án quan trọng, trình quản lý bí mật được ưu tiên hơn.
Thông qua plugin gradle-dotenv (co.uzzu.dotenv). Plugin đọc .env từ thư mục gốc của dự án và xuất các giá trị vào BuildConfig. Các biến có sẵn trong mã dưới dạng BuildConfig.VARIABLE_NAME ở giai đoạn biên dịch.
Có, nhiều trình phân tích hỗ trợ nội suy ở định dạng ${VAR_NAME}. Ví dụ, URL=${HOST}:${PORT} sẽ thay thế các giá trị của HOST và PORT từ cùng một tệp. Tuy nhiên, khả năng này phụ thuộc vào thư viện tải cụ thể.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm