如何在浏览器纯JavaScript脚本中正确使用msal-browser?
问题描述
我尝试按照MSAL Browser的官方文档,在纯浏览器JavaScript文件中使用msal-browser库。先是用动态导入,后来改成带type="module"属性的静态导入,但问题都没解决。我没使用React、Angular这类框架,但可以用站点里其他应用依赖的Dojo。
我的代码里,msClientId和msTenantId是其他代码定义好的变量。导入msal之后,这个对象没有任何属性或方法,调用msal.createStandardPublicClientApplication时会报错:"TypeError: msal.createStandardPublicClientApplication is not a function",浏览器控制台打印msal是Module {Symbol(Symbol.toStringTag): 'Module'}。
查看msal-browser.js文件顶部的代码:
'use strict';(function (global, factory) {typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :typeof define === 'function' && define.amd ? define(['exports'], factory) :(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.msal = {}));})(this, (function (exports) { 'use strict';
发现因为页面里已经存在define函数且define.amd已定义,所以会执行define(['exports'], factory),但此时exports是undefined,请问该怎么正确使用这个模块的导出内容?
解决方案
1. 强制使用全局变量模式加载
由于页面中存在AMD环境(Dojo会注册AMD的define函数),msal-browser会默认走AMD加载逻辑,但这里AMD的exports参数异常导致模块导出失败。可以通过在加载msal-browser之前,临时覆盖AMD的define函数,让msal-browser切换到全局变量模式:
// 先保存原有的AMD define函数 const originalDefine = window.define; // 临时移除AMD环境标识 window.define = undefined; window.define.amd = undefined; // 加载msal-browser脚本 const script = document.createElement('script'); script.src = 'path/to/msal-browser.js'; script.onload = function() { // 恢复原有的define函数 window.define = originalDefine; // 现在可以通过全局的msal对象调用方法了 const pca = msal.createStandardPublicClientApplication({ auth: { clientId: msClientId, authority: `https://login.microsoftonline.com/${msTenantId}` } }); // 后续业务逻辑... }; document.head.appendChild(script);
2. 使用Dojo的AMD加载器导入msal-browser
既然站点已经依赖Dojo,直接用Dojo的AMD加载机制来导入msal-browser,适配AMD环境:
require(['path/to/msal-browser'], function(msal) { // 这里的msal就是正确的模块导出对象 const pca = msal.createStandardPublicClientApplication({ auth: { clientId: msClientId, authority: `https://login.microsoftonline.com/${msTenantId}` } }); // 后续业务逻辑... });
注意需要确保msal-browser的路径在Dojo的模块搜索路径中,或者使用绝对路径。
3. 使用ES模块版本的msal-browser
如果坚持用ES模块(type="module"),需要确保引入的是msal-browser的ES模块版本(通常在npm包的dist/es目录下),而不是UMD版本。导入方式改为:
import * as msal from './path/to/msal-browser.esm.js'; const pca = msal.createStandardPublicClientApplication({ auth: { clientId: msClientId, authority: `https://login.microsoftonline.com/${msTenantId}` } });
这种方式需要确保服务器正确配置了ES模块的MIME类型,并且页面中没有AMD环境干扰ES模块的加载。
内容的提问来源于stack exchange,提问作者Emma Leis

