Nuxt3 LiveChat插件开发环境正常生产环境报错求助
Nuxt3生产构建后Odoo在线聊天插件加载失败问题排查与修复
问题描述
开发了一个Nuxt3聊天插件(文件名为chat.client.ts),开发模式下运行正常,但生产构建后出现故障。已替换URL保护企业信息,确认脚本加载正常、网络无问题且版本一致,但报错仍存在。
插件代码
const cssLink = document.createElement("link"); cssLink.rel = "stylesheet"; cssLink.href = "https://x.com/im_livechat/external_lib.css"; document.head.appendChild(cssLink); const script = document.createElement("script"); script.src = "https://x.com/im_livechat/external_lib.js"; script.onload = () => { odoo.define("web.session", function (require) { const Session = require("web.Session"); const modules = odoo._modules; return new Session(undefined, "https://x.com", { modules: modules, use_cors: true }); }); odoo.define("im_livechat.livesupport", function (require) { const rootWidget = require("root.widget"); const im_livechat = require("im_livechat.legacy.im_livechat.im_livechat"); const button = new im_livechat.LivechatButton(rootWidget, "https://x.com", { header_background_color: "#4E6C62", button_background_color: "#4E6C62", title_color: "#FFFFFF", button_text_color: "#FFFFFF", button_text: "Chat", input_placeholder: false, default_message: "Hello, before we continue, can I please have your email address ?", channel_name: "Main Chat", channel_id: 1, current_partner_id: 4, default_username: "Visitor", }); button .appendTo(document.body) .then(() => { window.livechat_button = button; // Ensure the button is properly appended before triggering the click nextTick(); }) .catch((error) => { console.error("Failed to append the livechat button:", error); }); }); }; document.body.appendChild(script);
报错信息
TypeError: Cannot read properties of undefined (reading 'static') external_lib.js:3296 Undefined dependency: web.Session require @ external_lib.js:3296 (anonymous) @ BcV-9UXX.js:58 (anonymous) @ external_lib.js:3292 processJob @ external_lib.js:3292 odoo.processJobs @ external_lib.js:3300 odoo.define @ external_lib.js:3278 t.onload @ BcV-9UXX.js:58 load (async) (anonymous) @ BcV-9UXX.js:58 iI @ BcV-9UXX.js:58 (anonymous) @ BcV-9UXX.js:18 r @ BcV-9UXX.js:18 runWithContext @ BcV-9UXX.js:14 sw @ BcV-9UXX.js:18 (anonymous) @ BcV-9UXX.js:18 run @ BcV-9UXX.js:10 runWithContext @ BcV-9UXX.js:18 rw @ BcV-9UXX.js:18 a @ BcV-9UXX.js:18 ow @ BcV-9UXX.js:18 await in ow (async) Lp @ BcV-9UXX.js:63 (anonymous) @ BcV-9UXX.js:63 external_lib.js:3291 Error while loading web.session: r is not a constructor TypeError: r is not a constructor at BcV-9UXX.js:58:45150 at external_lib.js:3292:63 at new Promise (<anonymous>) at processJob (external_lib.js:3292:9) at odoo.processJobs (external_lib.js:3300:1) at odoo.define (external_lib.js:3278:161) at t.onload (BcV-9UXX.js:58:45069) ... external_lib.js:3296 Undefined dependency: im_livechat.legacy.im_livechat.im_livechat
问题原因
- 生产构建的代码混淆:Nuxt3生产构建时会对代码进行压缩、混淆和tree-shaking,导致Odoo模块系统依赖的变量名、模块路径被篡改,无法正常解析
web.Session等依赖。 - 脚本加载时序问题:开发模式下代码未压缩,外部脚本加载完成后Odoo模块系统已完全初始化;生产模式下代码合并后,
script.onload触发时Odoo内部模块可能还未准备就绪,直接调用odoo.define会导致依赖找不到。 - DOM初始化时机:插件代码直接在顶层执行,未等待Nuxt的客户端DOM完全初始化,生产模式下DOM渲染时序和开发模式有差异,导致脚本插入时机过早。
解决方案
1. 禁用Nuxt对插件文件的代码混淆
在nuxt.config.ts中配置Vite,避免混淆chat.client.ts文件,保留原始变量和模块名:
export default defineNuxtConfig({ vite: { build: { terserOptions: { mangle: { // 排除插件文件,避免变量名被混淆 exclude: ['chat.client.ts'] } } } } })
2. 确保Odoo模块加载时序正确
修改script.onload逻辑,先等待Odoo核心模块初始化完成,再执行模块定义:
script.onload = async () => { // 等待web.Session模块可用 await new Promise(resolve => { const checkModule = () => { if (odoo?._modules?.['web.Session']) { resolve(true); } else { setTimeout(checkModule, 100); } }; checkModule(); }); odoo.define("web.session", function (require) { const Session = require("web.Session"); const modules = odoo._modules; return new Session(undefined, "https://x.com", { modules: modules, use_cors: true }); }); // 等待im_livechat模块可用 await new Promise(resolve => { const checkLivechatModule = () => { if (odoo?._modules?.['im_livechat.legacy.im_livechat.im_livechat']) { resolve(true); } else { setTimeout(checkLivechatModule, 100); } }; checkLivechatModule(); }); odoo.define("im_livechat.livesupport", function (require) { const rootWidget = require("root.widget"); const im_livechat = require("im_livechat.legacy.im_livechat.im_livechat"); const button = new im_livechat.LivechatButton(rootWidget, "https://x.com", { header_background_color: "#4E6C62", button_background_color: "#4E6C62", title_color: "#FFFFFF", button_text_color: "#FFFFFF", button_text: "Chat", input_placeholder: false, default_message: "Hello, before we continue, can I please have your email address ?", channel_name: "Main Chat", channel_id: 1, current_partner_id: 4, default_username: "Visitor", }); button .appendTo(document.body) .then(() => { window.livechat_button = button; nextTick(); }) .catch((error) => { console.error("Failed to append the livechat button:", error); }); }); };
3. 使用Nuxt客户端生命周期钩子执行DOM操作
将插件代码放在onMounted钩子中,确保DOM完全初始化后再加载外部资源:
export default defineNuxtPlugin(() => { onMounted(() => { const cssLink = document.createElement("link"); cssLink.rel = "stylesheet"; cssLink.href = "https://x.com/im_livechat/external_lib.css"; document.head.appendChild(cssLink); const script = document.createElement("script"); script.src = "https://x.com/im_livechat/external_lib.js"; // 这里放入上面修改后的script.onload逻辑 script.onload = async () => { // ... 等待模块初始化的代码 }; document.body.appendChild(script); }); });
4. 预加载外部脚本确保执行顺序
在nuxt.config.ts中配置预加载外部脚本,确保在插件代码执行前完成加载:
export default defineNuxtConfig({ app: { head: { link: [ { rel: "stylesheet", href: "https://x.com/im_livechat/external_lib.css" } ], script: [ { src: "https://x.com/im_livechat/external_lib.js", body: true, defer: true, // 指定加载完成后执行的全局函数 onload: "initLivechat()" } ] } } });
然后在chat.client.ts中定义全局初始化函数:
(window as any).initLivechat = async () => { // 放入原来的odoo模块定义逻辑 };
内容的提问来源于stack exchange,提问作者Va54
相关产品推荐
相关产品推荐

