Trình đóng gói mô-đun JavaScript có thể làm nhiều việc, nhưng một trong những tính năng hữu ích nhất của chúng là khả năng thêm và sử dụng các thư viện bên ngoài trong cơ sở mã của bạn. Trình đóng gói mô-đun sẽ đọc các đường dẫn nhập trong mã của bạn và kết hợp (đóng gói) mã dành riêng cho ứng dụng với mã thư viện đã nhập.
Từ phiên bản 9 trở lên, API mô-đun Firebase JavaScript được tối ưu hoá để hoạt động với các tính năng tối ưu hoá của trình kết hợp mô-đun nhằm giảm lượng mã Firebase có trong bản dựng cuối cùng.
import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged, getRedirectResult } from 'firebase/auth';
const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => { /* check status */ });
/**
* getRedirectResult is unused and should not be included in the code base.
* In addition, there are many other functions within firebase/auth that are
* not imported and therefore should not be included as well.
*/
Quá trình loại bỏ mã không dùng đến khỏi thư viện này được gọi là rung cây (tree shaking). Việc xoá mã này theo cách thủ công sẽ tốn rất nhiều thời gian và dễ xảy ra lỗi, nhưng các trình đóng gói mô-đun có thể tự động hoá việc xoá này.
Có rất nhiều trình đóng gói mô-đun chất lượng cao trong hệ sinh thái JavaScript. Hướng dẫn này tập trung vào việc sử dụng Firebase với webpack, Rollup và esbuild.
Bắt đầu
Hướng dẫn này yêu cầu bạn cài đặt npm trong môi trường phát triển. npm được dùng để cài đặt và quản lý các phần phụ thuộc (thư viện). Để cài đặt npm, hãy cài đặt Node.js. Thao tác này sẽ tự động cài đặt npm.
Hầu hết nhà phát triển đều thiết lập đúng cách sau khi cài đặt Node.js. Tuy nhiên, có những vấn đề thường gặp mà nhiều nhà phát triển gặp phải khi thiết lập môi trường của họ. Nếu bạn gặp phải bất kỳ lỗi nào, hãy đảm bảo môi trường của bạn có CLI npm và bạn đã thiết lập các quyền thích hợp để không phải cài đặt các gói với tư cách là quản trị viên bằng lệnh sudo.
package.json và cài đặt Firebase
Sau khi cài đặt npm, bạn sẽ cần tạo một tệp package.json
ở gốc của dự án cục bộ. Tạo tệp này bằng lệnh npm sau:
npm init
Thao tác này sẽ đưa bạn qua một trình hướng dẫn để cung cấp thông tin cần thiết. Sau khi được tạo, tệp sẽ có dạng như sau:
{
"name": "your-package-name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
}
}
Tệp này chịu trách nhiệm cho nhiều việc khác nhau. Đây là một tệp quan trọng mà bạn cần tìm hiểu kỹ nếu muốn tìm hiểu thêm về việc kết hợp mô-đun và tạo mã JavaScript nói chung. Phần quan trọng của hướng dẫn này là đối tượng "dependencies"
. Đối tượng này sẽ giữ một cặp khoá-giá trị của thư viện mà bạn đã cài đặt và phiên bản mà thư viện đó đang sử dụng.
Bạn có thể thêm các phần phụ thuộc thông qua lệnh npm install
hoặc npm i
.
npm i firebase
Khi bạn chạy npm i firebase
, quy trình cài đặt sẽ cập nhật package.json
để liệt kê Firebase dưới dạng một phần phụ thuộc:
"dependencies": {
"firebase": "^9.0.0"
},
Khoá là tên của thư viện và giá trị là phiên bản cần sử dụng. Giá trị phiên bản rất linh hoạt và có thể chấp nhận nhiều giá trị. Đây được gọi là lập phiên bản ngữ nghĩa hoặc semver. Để tìm hiểu thêm về semver, hãy xem hướng dẫn của npm về việc tạo phiên bản theo ngữ nghĩa.
Thư mục nguồn so với thư mục bản dựng
Mã bạn viết sẽ được trình đóng gói mô-đun đọc và xử lý, sau đó xuất ra dưới dạng một tệp hoặc tập hợp tệp mới. Bạn cần tách riêng hai loại tệp này. Mã mà các trình đóng gói mô-đun đọc và xử lý được gọi là mã "nguồn". Các tệp mà chúng xuất ra được gọi là mã đã tạo hoặc "dist" (phân phối).
Một chế độ thiết lập phổ biến trong cơ sở mã là lưu trữ mã nguồn trong một thư mục có tên là src
và mã được tạo trong một thư mục có tên là dist
.
- src
|_ index.js
|_ animations.js
|_ datalist.js
- dist
|_ bundle.js
Trong cấu trúc tệp ví dụ ở trên, hãy xem xét rằng index.js
nhập cả animations.js
và datalist.js
. Khi xử lý mã nguồn, trình kết hợp mô-đun sẽ tạo ra tệp bundle.js
trong thư mục dist
. bundle.js
là sự kết hợp của các tệp trong thư mục src
và mọi thư viện mà bạn nhập.
Nếu đang sử dụng các hệ thống kiểm soát nguồn như Git, thì bạn thường bỏ qua thư mục dist
khi lưu trữ mã này trong kho lưu trữ chính.
Điểm truy cập
Tất cả các trình đóng gói mô-đun đều có khái niệm về điểm truy cập. Bạn có thể coi ứng dụng của mình như một cây tệp. Một tệp nhập mã từ một tệp khác, v.v. Điều này có nghĩa là một tệp sẽ là gốc của cây. Tệp này được gọi là điểm truy cập.
Hãy xem lại ví dụ về cấu trúc tệp trước đó.
- src
|_ index.js
|_ animations.js
|_ datalist.js
- dist
|_ bundle.js
// src/index.js
import { animate } from './animations';
import { createList } from './datalist';
// This is not real code, but for example purposes only
const theList = createList('users/123/tasks');
theList.addEventListener('loaded', event => {
animate(theList);
});
Tệp src/index.js
được coi là điểm truy cập vì tệp này bắt đầu nhập tất cả mã cần thiết cho ứng dụng. Tệp điểm truy cập này được các trình đóng gói mô-đun dùng để bắt đầu quy trình đóng gói.
Sử dụng Firebase với webpack
Bạn không cần phải thiết lập cấu hình cụ thể nào cho các ứng dụng Firebase và webpack. Phần này trình bày cấu hình webpack chung.
Bước đầu tiên là cài đặt webpack từ npm dưới dạng một phần phụ thuộc phát triển.
npm i webpack webpack-cli -D
Tạo một tệp có tên là webpack.config.js
ở gốc của dự án cục bộ rồi thêm đoạn mã sau.
const path = require('path');
module.exports = {
// The entry point file described above
entry: './src/index.js',
// The location of the build folder described above
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
// Optional and for development only. This provides the ability to
// map the built code back to the original source format when debugging.
devtool: 'eval-source-map',
};
Sau đó, hãy đảm bảo bạn đã cài đặt Firebase dưới dạng một phần phụ thuộc.
npm i firebase
Sau đó, hãy khởi động Firebase trong cơ sở mã của bạn. Đoạn mã sau đây nhập và khởi động Firebase trong một tệp điểm truy cập, đồng thời sử dụng Firestore Lite để tải một tài liệu "city".
// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';
const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);
async function loadCity(name) {
const cityDoc = doc(db, `cities/${name}`);
const snapshot = await getDoc(cityDoc);
return {
id: snapshot.id,
...snapshot.data(),
};
}
Bước tiếp theo là thêm một tập lệnh npm để chạy bản dựng webpack. Mở tệp package.json
rồi thêm cặp khoá-giá trị sau vào đối tượng "scripts"
.
"scripts": {
"build": "webpack --mode=development"
},
Để chạy webpack và tạo thư mục bản dựng, hãy chạy lệnh sau.
npm run build
Cuối cùng, hãy kiểm tra thư mục bản dựng dist
. Thư mục này phải chứa một tệp có tên bundle.js
chứa ứng dụng và mã nguồn phụ thuộc được kết hợp.
Để biết thêm thông tin về cách tối ưu hoá bản dựng webpack cho bản phát hành công khai, hãy xem tài liệu chính thức của họ về chế độ cài đặt cấu hình "mode".
Sử dụng Firebase với Rollup
Bạn không cần phải thiết lập cấu hình cụ thể nào cho các ứng dụng Firebase và Rollup. Phần này đề cập đến cấu hình Rollup chung.
Bước đầu tiên là cài đặt Rollup và một trình bổ trợ dùng để liên kết các lệnh nhập với các phần phụ thuộc được cài đặt bằng npm.
npm i rollup @rollup/plugin-node-resolve -D
Tạo một tệp ở gốc của dự án cục bộ có tên là rollup.config.js
rồi thêm đoạn mã sau.
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default {
// the entry point file described above
input: 'src/index.js',
// the output for the build folder described above
output: {
file: 'dist/bundle.js',
// Optional and for development only. This provides the ability to
// map the built code back to the original source format when debugging.
sourcemap: 'inline',
// Configure Rollup to convert your module code to a scoped function
// that "immediate invokes". See the Rollup documentation for more
// information: https://rollupjs.org/guide/en/#outputformat
format: 'iife'
},
// Add the plugin to map import paths to dependencies
// installed with npm
plugins: [nodeResolve()]
};
Sau đó, hãy khởi động Firebase trong cơ sở mã của bạn. Đoạn mã sau đây nhập và khởi động Firebase trong một tệp điểm truy cập, đồng thời sử dụng Firestore Lite để tải một tài liệu "city".
// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';
const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);
async function loadCity(name) {
const cityDoc = doc(db, `cities/${name}`);
const snapshot = await getDoc(cityDoc);
return {
id: snapshot.id,
...snapshot.data(),
};
}
Bước tiếp theo là thêm một tập lệnh npm để chạy bản dựng tổng hợp. Mở tệp package.json
rồi thêm cặp khoá-giá trị sau vào đối tượng "scripts"
.
"scripts": {
"build": "rollup -c rollup.config.js"
},
Để chạy rollup và tạo thư mục bản dựng, hãy chạy lệnh sau.
npm run build
Cuối cùng, hãy kiểm tra thư mục bản dựng dist
. Thư mục này phải chứa một tệp có tên bundle.js
chứa ứng dụng và mã nguồn phụ thuộc được kết hợp.
Để biết thêm thông tin về cách tối ưu hoá bản dựng Rollup cho bản phát hành công khai, hãy xem tài liệu chính thức của Rollup về các trình bổ trợ cho bản phát hành công khai.
Sử dụng Firebase với esbuild
Bạn không cần phải thiết lập cấu hình cụ thể nào cho các ứng dụng Firebase và esbuild. Phần này trình bày cấu hình chung của esbuild.
Bước đầu tiên là cài đặt esbuild dưới dạng một phần phụ thuộc phát triển.
npm i esbuild -D
Tạo một tệp có tên là esbuild.config.js
ở gốc của dự án cục bộ rồi thêm đoạn mã sau.
require('esbuild').build({
// the entry point file described above
entryPoints: ['src/index.js'],
// the build folder location described above
outfile: 'dist/bundle.js',
bundle: true,
// Replace with the browser versions you need to target
target: ['chrome60', 'firefox60', 'safari11', 'edge20'],
// Optional and for development only. This provides the ability to
// map the built code back to the original source format when debugging.
sourcemap: 'inline',
}).catch(() => process.exit(1))
Sau đó, hãy khởi động Firebase trong cơ sở mã của bạn. Đoạn mã sau đây nhập và khởi động Firebase trong một tệp điểm truy cập, đồng thời sử dụng Firestore Lite để tải một tài liệu "city".
// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';
const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);
async function loadCity(name) {
const cityDoc = doc(db, `cities/${name}`);
const snapshot = await getDoc(cityDoc);
return {
id: snapshot.id,
...snapshot.data(),
};
}
Bước tiếp theo là thêm một tập lệnh npm để chạy esbuild. Mở tệp package.json
rồi thêm cặp khoá-giá trị sau vào đối tượng "scripts"
.
"scripts": {
"build": "node ./esbuild.config.js"
},
Cuối cùng, hãy kiểm tra thư mục bản dựng dist
. Thư mục này phải chứa một tệp có tên bundle.js
chứa ứng dụng và mã nguồn phụ thuộc được kết hợp.
Để biết thêm thông tin về cách tối ưu hoá esbuild cho quá trình sản xuất, hãy xem tài liệu chính thức của họ về việc giảm thiểu và các hoạt động tối ưu hoá khác.