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

Node.js中CommonJS与ES模块导入方式哪个更优?附Koa项目示例

在Node.js项目中选择CommonJS还是ES模块?

问题描述

在Node.js项目里,到底用const <变量名> = require(<包名>);这种CommonJS导入语法,还是import '<组件名>' from '<包名>';这种ES模块导入语法更合适?能不能结合提供的Koa后端项目代码给出优化示例?


两种语法的对比与选择建议

CommonJS

  • Node.js传统模块化方案,无需额外配置即可直接运行
  • 支持动态导入(可在代码任意位置根据条件加载模块)
  • 适合维护旧项目,或依赖大量仅支持CommonJS的第三方包的场景

ES模块(ESM)

  • ECMAScript官方标准模块化方案,与前端模块化语法统一,适配全栈项目
  • 支持静态分析,可实现Tree Shaking优化打包体积
  • 兼容import()动态导入、顶层await等新特性
  • 需要Node.js 14.13.0+(12.x版本需加--experimental-modules参数),且需配置项目启用ESM

结论:新项目优先选ES模块,能享受标准语法与新特性;旧项目继续用CommonJS即可,避免不必要的迁移成本。以下是将你的Koa项目改造为ES模块的完整示例。


项目改造为ES模块的示例

1. 修改package.json

添加"type": "module"字段,告知Node.js项目使用ES模块:

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "lkh-krishen",
  "license": "ISC",
  "dependencies": {
    "@koa/router": "^10.1.1",
    "koa": "^2.13.4",
    "koa-bodyparser": "^4.3.0",
    "mongodb": "^4.7.0"
  }
}

2. 修改index.js

替换require为import,本地文件导入需添加扩展名:

import Koa from 'koa';
import bodyParser from 'koa-bodyparser';

import productRoutes from './routes/products.routes.js';
import promotionRoutes from './routes/promotions.routes.js';

const app = new Koa();

app.use(bodyParser());

app.use(productRoutes.routes()).use(productRoutes.allowedMethods());
app.use(promotionRoutes.routes()).use(promotionRoutes.allowedMethods());

app.listen(3000, () => {
    console.log("Application is running on port 3000");
});

3. 修改dal/index.js

替换require为import,用export default导出MongoDB客户端:

import { MongoClient } from "mongodb";

const client = new MongoClient('mongodb://localhost:27017', {
    useNewUrlParser: true,
    useUnifiedTopology: true
});

client.connect(err => {
    if(err){
        console.error(err);
        process.exit(-1);
    }
    console.log("Successfully connected to MongoDB");
});

export default client;

4. 修改dal/products.dao.js

替换require为import,用export导出DAO方法:

import client from './index.js';
import { ObjectId } from 'mongodb';

const products = client.db('store').collection('products');

export const save = async ({name, description, qty, price}) => {
    const result = await products.insertOne({name, description, qty, price});
    return await getById(result.insertedId);
}

export const getAll = async () => {
    const cursor = await products.find();
    return cursor.toArray();
}

export const getById = async (id) => {
    return await products.findOne({_id: ObjectId(id)});
}

export const update = async (id, {name, description, qty, price}) => {
    const result = await products.replaceOne({_id: ObjectId(id)}, {name, description, qty, price});
    return result.ops[0];
}

export const removeById = async id => {
    await products.deleteOne({_id: ObjectId(id)});
}

5. 修改api/products.api.js

替换require为import,用export导出API方法:

import { getAll, save, update, getById, removeById } from '../dal/products.dao.js';

export const createProduct = async ({name, description, qty, price}) => {
    const product = {
        name,
        description,
        qty,
        price
    }
    return await save(product);
}

export const getProducts = async () => {
    return await getAll();
}

export const getProduct = async id => {
    return await getById(id);
}

export const deleteProduct = async id => {
    return await removeById(id);
}

export const updateProduct = async (id, {name, description, qty, price}) => {
    return await update(id, {name, description, qty, price});
}

6. 修改routes/products.routes.js

替换require为import,用export default导出路由,同时修正原代码中的两处错误:

import Router from '@koa/router';
import { createProduct, deleteProduct, updateProduct, getProduct, getProducts } from '../api/products.api.js';

const router = new Router ({
    prefix: '/products'
});

router.get('/', async ctx => {
    ctx.body = await getProducts();
});

router.post('/', async ctx => {
    let product = ctx.request.body;
    product = await createProduct(product);
    ctx.response.status = 200;
    ctx.body = product;
});

router.get('/:id', async ctx => {
    const id = ctx.params.id;
    ctx.body = await getProduct(id);
});

router.delete('/:id', async ctx => {
    const id = ctx.params.id; // 修正原代码的router.params.id错误
    ctx.body = await deleteProduct(id);
});

router.put('/:id', async ctx => {
    const id = ctx.params.id;
    
    let product = ctx.request.body;
    product = await updateProduct(id, product); // 修正原代码漏传id参数的错误
    
    ctx.response.status = 200;
    ctx.body = product;
});

export default router;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 22:06:32