如何在无框架/打包工具的HTML环境中跨文件访问Firebase函数?
我使用Firebase作为后端数据存储与用户认证开发网站,已将所有Firebase配置及导入内容放在firebase-sdk.js文件中,网站每个页面都有独立的脚本文件,会调用不同的Firebase函数。目前开发登录页面时,在login.js文件中调用signInWithEmailAndPassword(auth, ...),程序无法找到auth的定义。想知道是否可以从独立文件中访问auth及其他Firebase函数,还是需要在所有文件中都引入firebase-sdk.js的全部内容?开发环境是无框架、无打包工具的基础HTML环境。
相关代码
firebase-sdk.js
// Import firebase import { initializeApp } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-app.js"; // Import firebase features import { getFirestore, collection, addDoc, onSnapshot, doc, updateDoc, deleteDoc } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-firestore.js" import { getAuth, onAuthStateChanged, signInWithEmailAndPassword } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-auth.js" // Firebase configuration const firebaseConfig = { --- }; // Initialise firestore const app = initializeApp(firebaseConfig); // Initialise features const auth = getAuth(app) const db = getFirestore(app)
login.js
const loginBtn = document.getElementById('id_submit_login_btn') const loginBtnPressed = async () => { const loginEmail = document.getElementById('id_email_entry').value const loginPassword = document.getElementById('id_password_entry').value const userCredentials = await signInWithEmailAndPassword(auth, loginEmail, loginPassword) console.log(userCredentials.user) } loginBtn.addEventListener('click', loginBtnPressed)
在无打包工具的原生HTML环境中,你可以通过ES模块的导出/导入机制实现跨文件访问Firebase的实例和函数,无需在每个文件重复引入全部内容,具体步骤如下:
修改
firebase-sdk.js,导出需要共享的资源
将需要在其他脚本中使用的auth、db实例,以及Firebase函数(比如signInWithEmailAndPassword)通过export关键字暴露出去:// Import firebase import { initializeApp } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-app.js"; // Import firebase features import { getFirestore, collection, addDoc, onSnapshot, doc, updateDoc, deleteDoc } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-firestore.js" import { getAuth, onAuthStateChanged, signInWithEmailAndPassword } from "https://www.gstatic.com/firebasejs/10.5.0/firebase-auth.js" // Firebase configuration const firebaseConfig = { --- }; // Initialise firestore const app = initializeApp(firebaseConfig); // Initialise features并导出 export const auth = getAuth(app) export const db = getFirestore(app) // 导出需要用到的Firebase函数 export { signInWithEmailAndPassword, onAuthStateChanged } // 如果需要Firestore的函数,也可以按需导出:export { collection, addDoc }在
login.js中导入所需资源
在login.js开头,通过import语句从firebase-sdk.js引入需要的auth和signInWithEmailAndPassword:import { auth, signInWithEmailAndPassword } from './firebase-sdk.js'; const loginBtn = document.getElementById('id_submit_login_btn') const loginBtnPressed = async () => { const loginEmail = document.getElementById('id_email_entry').value const loginPassword = document.getElementById('id_password_entry').value try { const userCredentials = await signInWithEmailAndPassword(auth, loginEmail, loginPassword) console.log(userCredentials.user) } catch (error) { // 处理登录错误,比如邮箱密码错误、网络问题等 console.error(error.message) } } loginBtn.addEventListener('click', loginBtnPressed)注意:这里的路径
./firebase-sdk.js要根据你的文件实际位置调整,确保路径正确。HTML中引入脚本时添加
type="module"
在页面的<script>标签中,必须添加type="module"属性,才能让浏览器识别ES模块并正确处理导入导出:<!-- 先加载firebase-sdk模块 --> <script type="module" src="firebase-sdk.js"></script> <!-- 再加载登录脚本 --> <script type="module" src="login.js"></script>
原理说明
原生JavaScript中,普通脚本的变量默认在全局作用域,但ES模块(通过type="module"声明)拥有独立的模块作用域,内部变量不会自动暴露到全局。因此必须通过export/import显式共享和获取资源,这样既能避免全局变量污染,又能实现模块化复用。
内容的提问来源于stack exchange,提问作者Caleb Eason

