如何让lsnode使用import加载ES模块启动文件?Node.js 14.21.2环境
我是JavaScript和Node.js新手,目前只有package.json和server.js两个文件,用的是Node.js 14.21.2版本。运行时弹出错误:
require() of /home/cherjh/scheckout/server.js from /usr/local/lsws/fcgi-bin/lsnode.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
看起来/usr/local/lsws/fcgi-bin/lsnode.js里的lsnode在用require()加载我的启动文件server.js。想问下lsnode是什么?怎么让它用import加载server.js?
我的package.json内容:
{ "name": "", "main": "server.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" }, "license": "ISC", "dependencies": { "cors": "^2.8.5", "dotenv": "^16.0.3", "express": "^4.18.2", "node-fetch": "^3.3.1", "path": "^0.12.7" } }
server.js代码片段:
import express from "express"; import fetch from "node-fetch"; import cors from "cors"; import "dotenv/config"; import path from "path"; const _dirname = path.resolve(); const { CLIENT_ID, APP_SECRET } = process.env; const app = express(); const base = "https://api-m.sandbox.cheriths.com"; app.use(cors({origin: '*'})); const generateAccessToken = async () => { try { const auth = Buffer.from(CLIENT_ID + ":" + APP_SECRET).toString("base64"); const response = await fetch(`${base}/v1/oauth2/token`, { method: "post", body: "grant_type=client_credentials", headers: { Authorization: `Basic ${auth}`, }, }); const data = await response.json(); return data.access_token; } catch(error) { console.error("Failed to generate Access Token:", error); } };
我试过删掉package.json里的"type": "module",换成node-fetch 2.6.12并把server.js里的import改成require(),错误就没了,但我想保留import语法和node-fetch 3.3.1,改回去后错误又出现了。
什么是lsnode?
lsnode是LiteSpeed Web Server(LSWS)配套的Node.js处理模块,专门用来在LiteSpeed服务器环境中运行Node.js应用。它默认遵循CommonJS规范,用require()加载文件,这就是为啥你的ES模块会报错——require()没法直接加载被标记为ES模块的文件。
让lsnode支持ES模块的几种办法
1. 修改LiteSpeed面板的lsnode配置
登录LiteSpeed的WebAdmin控制台:
- 找到
服务器配置 > 外部应用,定位到你的lsnode应用(通常叫NodeJS或自定义名称) - 在
命令字段里,把启动命令改成node --input-type=module server.js(Node.js 14.13.0+已默认支持ES模块,但加上--input-type=module能确保强制以ES模块模式加载) - 保存配置后重启LiteSpeed服务,重新部署应用
2. 把server.js重命名为server.mjs
Node.js会自动把.mjs后缀的文件识别为ES模块。你只需要:
- 将server.js改名为server.mjs
- 同步修改package.json里的
main字段为"server.mjs",start脚本改成"node server.mjs" - 在LiteSpeed的lsnode配置里,把启动文件路径改成新的server.mjs
这样lsnode调用Node.js时会自动按ES模块规则处理文件,避免require()加载ES模块的冲突。
3. 用CommonJS中间脚本过渡
创建一个CommonJS格式的启动文件(比如start.cjs),内容如下:
// start.cjs import('./server.js').catch(err => console.error(err));
然后:
- 修改package.json的
main字段为"start.cjs" - 在LiteSpeed的lsnode配置里把启动文件换成start.cjs
这样lsnode用require()加载start.cjs(CommonJS文件),再通过动态import()加载你的ES模块server.js,实现两种模块规范的兼容。
额外提示
- Node.js 14.x对ES模块的支持基本稳定,但如果遇到模块解析问题(比如import路径没加后缀),可以在启动命令里加
--experimental-specifier-resolution=node参数 - 确保LiteSpeed的lsnode模块是最新版本,旧版本可能对ES模块的支持不完善
内容的提问来源于stack exchange,提问作者Greenoak

