使用Deno 2+esbuild打包Chrome扩展时无法解析events模块
问题描述
开发Chrome扩展时,因Chrome不允许外部依赖,采用Deno管理依赖并通过esbuild-deno-loader打包本地文件。打包命令无报错,但浏览器中扩展的graph.bundle.js无法正常渲染HTML,报错:
Uncaught TypeError: Failed to resolve module specifier "events". Relative references must start with either "/", "./", or "../".
此前用Node.js+Webpack打包时脚本可正常运行,问题出在Deno+esbuild配置上。无法解析的events是直接依赖的子依赖。
待打包文件 graph.js
// Graph generator function from graphMLGEN.js import { generateMapGraph } from './graphMLgen.js' // Sigma and Graphology libraries import { Sigma } from 'sigma'; import { Graph } from 'graphology'; import random from 'graphology-layout/random'; import ForceSupervisor from 'graphology-layout-force/worker'; import graphml from 'graphology-graphml'; // Load the graph structure from the graphMLGEN.js file document.addEventListener("DOMContentLoaded", async function() { const windows = await chrome.windows.getAll({ "populate": true }); const xml = generateMapGraph(windows); const graph = graphml.parse(Graph, xml); random.assign(graph) const layout = new ForceSupervisor(graph, {maxIterations: 5}); layout.start(); const container = document.getElementById("container"); const sigmaInstance = new Sigma(graph, container); });
打包配置文件 bundle.js
// JS Bundling Tools import * as esbuild from "npm:esbuild"; import { denoPlugins } from "jsr:@luca/esbuild-deno-loader"; const result = await esbuild.build({ plugins: [...denoPlugins()], entryPoints: ["./src/sigma/graph.js"], outfile: "./dist/graph.bundle.js", bundle: true, format: "esm", platform: "browser", target:"es2023", sourcemap:true, treeShaking:true, }); esbuild.stop();
deno.json 配置
{ "tasks": { "dev": "deno run --watch src/deno/main.ts", "run": "deno run src/deno/main.ts", "bundle": "deno run --allow-run --allow-env --allow-read --allow-write --allow-net bundle.js" }, "imports": { "sigma": "npm:sigma", "graphology": "npm:graphology", "graphology-layout/random": "npm:graphology-layout/random", "graphology-layout-force/worker": "npm:graphology-layout-force/worker", "graphology-graphml": "npm:graphology-graphml", "xmlbuilder2": "npm:xmlbuilder2", "pretty-data": "npm:pretty-data" } }
问题原因与修复方案
差异原因
Webpack默认会自动处理Node.js核心模块(如events)的浏览器兼容,内置这些模块的浏览器适配版本并打包进结果。而esbuild结合deno-loader时,因Deno的模块解析逻辑与Node不同,即使设置了platform: "browser",也可能未将events替换为浏览器兼容版本,导致打包后保留了原始的非相对路径导入语句,浏览器无法识别。
修复步骤
1. 安装Node核心模块polyfill插件
执行命令添加esbuild的polyfill插件:
deno add npm:@esbuild-plugins/node-modules-polyfill npm:@esbuild-plugins/node-globals-polyfill
2. 修改打包配置文件 bundle.js
引入插件并添加到配置中,同时补充全局变量定义:
import * as esbuild from "npm:esbuild"; import { denoPlugins } from "jsr:@luca/esbuild-deno-loader"; import NodeModulesPolyfillPlugin from "npm:@esbuild-plugins/node-modules-polyfill"; import NodeGlobalsPolyfillPlugin from "npm:@esbuild-plugins/node-globals-polyfill"; const result = await esbuild.build({ plugins: [ NodeGlobalsPolyfillPlugin({ process: true, buffer: true }), NodeModulesPolyfillPlugin(), ...denoPlugins() ], entryPoints: ["./src/sigma/graph.js"], outfile: "./dist/graph.bundle.js", bundle: true, format: "esm", platform: "browser", target:"es2023", sourcemap:true, treeShaking:true, define: { "process.env.NODE_ENV": '"production"' } }); esbuild.stop();
3. 重新执行打包
deno task bundle
配置完成后,esbuild会将events等Node核心模块替换为浏览器兼容的polyfill,打包后的脚本即可在Chrome扩展中正常运行。
内容的提问来源于stack exchange,提问作者whitmank
相关产品推荐
相关产品推荐

