You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Parcel打包Express+EJS的Node.js应用遇items未定义错误求助

问题根源分析

你遇到的核心问题是对Parcel的定位和使用场景理解偏差:Parcel是前端静态资源打包工具,它编译index.ejs时,会直接尝试解析EJS模板生成静态HTML,但这个过程完全不会运行你的Express后端代码——自然也就拿不到后端通过res.render()传递的items变量,所以才会报items is not defined的错误。

而你用node app.js能正常运行,是因为这时候是Express服务器在处理请求:当用户访问根路径时,后端先执行数据库查询,再把items变量注入EJS模板进行服务端渲染,整个流程是有后端上下文支撑的。


解决方案(两种可选方向)

方向一:保留Express服务端渲染架构(推荐,适合原有逻辑)

让Parcel专注处理前端静态资源(JS/CSS等),Express负责运行后端和渲染EJS模板,两者分工协作:

1. 调整项目结构与依赖

  • 把前端独立资源(比如自定义JS、CSS)放到单独目录,比如public/src
  • 安装concurrently来同时启动Express和Parcel监听:
    npm install --save-dev concurrently
    

2. 修改package.json的scripts

"scripts": {
  "dev": "concurrently \"node app.js\" \"parcel watch public/src/index.js --out-dir public/dist\"",
  "build": "parcel build public/src/index.js --out-dir public/dist"
}

3. 在EJS中引入Parcel打包后的资源

在index.ejs的<head>或<body>末尾添加:

<script src="/dist/index.js"></script>
<!-- 如果有CSS的话也同理引入 -->
<link rel="stylesheet" href="/dist/index.css">

4. 保持原有Express路由逻辑不变

你的数据库查询和res.render()代码完全不需要修改,因为依然由Express负责渲染EJS并传递items变量,Parcel只处理前端静态资源的打包和热更新。


方向二:改为前端静态页面+API模式(适合纯前端渲染场景)

如果想完全用Parcel做静态打包,需要把EJS模板改成纯前端页面,通过API从后端获取数据:

1. 改造前端页面与逻辑

  • 把views/index.ejs改为public/src/index.html,去掉EJS模板语法,只保留基础结构:
    <!DOCTYPE html> 
    <html> 
    <head> 
      <meta charset="utf-8"> 
      <title>My website</title> 
    </head> 
    <body> 
      <div class="menu"></div>
      <script src="./index.js"></script>
    </body> 
    </html>
    
  • 在public/src/index.js中通过API获取数据并渲染:
    document.addEventListener('DOMContentLoaded', async () => {
      try {
        // 调用后端API获取数据
        const res = await fetch('/api/items');
        const items = await res.json();
        
        // 动态生成菜单
        const menuEl = document.querySelector('.menu');
        items.forEach(row => {
          const itemDiv = document.createElement('div');
          itemDiv.className = 'item';
          itemDiv.dataset.value = row.id;
          itemDiv.textContent = row.name;
          menuEl.appendChild(itemDiv);
        });
      } catch (err) {
        console.error('加载数据失败:', err);
      }
    });
    

2. 在Express中添加API路由

router.get("/api/items", async function(req, res) { 
  const client = await pool.connect() 
  try { 
    const result = await client.query('select id, name from mytable') 
    res.json(result.rows) // 返回JSON格式数据
  } finally { 
    client.release() 
  }
});

// 配置静态文件目录,让Express能访问Parcel打包后的前端资源
app.use(express.static('public/dist'));

3. 修改package.json的scripts

"scripts": {
  "dev": "concurrently \"node app.js\" \"parcel watch public/src/index.html --out-dir public/dist\"",
  "build": "parcel build public/src/index.html --out-dir public/dist"
}

内容的提问来源于stack exchange,提问作者vagvaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:49:15