如何通过ES模块语法在浏览器中使用npm安装的包
问题
我安装了一个npm模块,但无法在浏览器中通过ES模块的import语句正常使用它,具体操作步骤和遇到的问题如下:
- 执行
npm install sample-module安装示例模块; - 在
package.json中添加"type": "module"; - 用Express搭建了静态服务(server.js代码如下):
import express from 'express'; import path from 'path'; import { fileURLToPath } from 'url'; const PORT = process.env.PORT || 8080; const app = express(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); app.use('/assets', express.static('assets')); app.get('/', (req, res) => { res.sendFile(path.join(__dirname) + '/views/index.html'); }); app.listen(PORT, _ => { console.log(`App deployed at Port ${PORT}`); });
- 在
index.html中通过<script type="module" src="./assets/script.js"></script>引入浏览器端脚本; - 在
script.js中尝试import {one, two} from 'sample-module',浏览器报错:
Uncaught TypeError: Failed to resolve module specifier "sample-module". Relative references must start with either "/", "./", or "../".
尝试改为./sample-module或../node_modules/sample-module也都无效。之前用require()配合browserify打包成bundle.js能正常使用,但现在想通过ES模块语法实现相同效果,该怎么操作?
解决方案
方法1:使用浏览器原生导入映射(Import Maps)
浏览器原生支持通过导入映射直接解析裸模块名(如sample-module),步骤如下:
- 在
index.html的<head>中添加导入映射脚本:
<script type="importmap"> { "imports": { "sample-module": "/node_modules/sample-module/dist/sample-module.js" } } </script>
注意:需替换为sample-module实际的入口文件路径,可查看该模块package.json的module或main字段确认
2. 修改Express配置,将node_modules目录作为静态资源暴露:
在server.js中添加一行:
app.use('/node_modules', express.static('node_modules'));
- 此时
script.js里的import {one, two} from 'sample-module'即可被浏览器正常解析。
方法2:使用轻量ES模块打包工具(如Vite)
如果不想手动处理路径和静态资源,用Vite这类原生支持ES模块的工具更省心:
- 初始化Vite项目(已有项目可直接安装Vite):
npm init vite@latest . -- --template vanilla
- 安装依赖:
npm install sample-module
- 在
script.js中直接使用import {one, two} from 'sample-module',Vite会自动处理模块解析、依赖打包。 - 启动开发服务:
npm run dev
Vite会自动搭建服务并支持热更新,生产环境打包会生成优化后的ES模块代码。
方法3:手动指定模块完整路径(仅临时测试用)
如果只是临时测试,可直接写模块的完整相对路径,但需确保路径正确且Express能访问到node_modules:
比如sample-module的入口是node_modules/sample-module/index.js,则在script.js中写:
import {one, two} from '../node_modules/sample-module/index.js';
同时要给Express添加node_modules的静态服务配置(参考方法1第二步),但这种方法在模块有嵌套依赖时容易出错,不推荐长期使用。
内容的提问来源于stack exchange,提问作者rimed

