发布于 2026-01-06 0 阅读
0

不使用 Nodemon 和 Babel,用 ES6 开发 Node 应用

不使用 Nodemon 和 Babel,用 ES6 开发 Node 应用

我最近启动了一个新的 Node.js 项目,按照惯例,我首先安装了两个熟悉的包:` nodemonresources` 和 `resources` babel。这样做的目的是因为我需要一种方法来实现在用 ES6 模块编写应用程序时的热重载。

从古至今,我们都知道有一种用于热装弹的工具是nodemon……

此外,由于 Node.js 的默认配置仅支持 common.js,我们需要一种方法将代码转译回 common.js。当然,Node 对 ES6 模块的支持还不够完善--experimental-modules,需要进行.mjs扩展(在我看来,这是一种侵入式的做法)。

(最新版本的 Node.js 已经允许我们在不使用 `<module>` 标签的情况下使用 ES6 模块,但这似乎并没有向后移植到之前的版本,使用起来仍然需要扩展。)

大多数教程都会推荐使用 Babel。但是,我认为它对我们的目的来说过于复杂(Babel 更适合用于浏览器)。它还会抵消 ES6 的优势(例如 tree shaking)。

及时救援

隆重推出Rollup

Rollup 是一个 JavaScript 模块打包器,它可以将小段代码编译成更大更复杂的东西,例如库或应用程序。

(注:应用

首先将其安装为rollup开发依赖项。

yarn add rollup -D
// or
npm i rollup --save-dev

接下来,创建rollup.config.js.(您可以在此文件中使用 ES6)。

export default {
  input: 'api/server.js',
  output: {
    file: 'bundle.js',
    format: 'cjs',
  },
};

通过此配置,我们将获取我们的api/server.js(或您的主脚本所在的任何位置),并输出其 CommonJS 版本。

虽然它毕竟是 CommonJS,但导出的文件已经过tree shaking处理。此外,由于所有内容都被编译到一个文件中,我们的代码在 Node.js 中运行速度可能会更快,因为它无需引入不同的模块。

仅供参考,这是我api/server.js用 ES6 编写的代码。

import next from 'next';
import { createServer } from 'http';
import apolloServer from './apollo-server';
import app from './app';
import { connect as connectMongoDB } from './db/mongo';

// http
const port = process.env.PORT || '3000';
const httpServer = createServer();

// next
const nextApp = next({ dev: process.env.NODE_ENV !== 'production' });
const nextHandle = nextApp.getRequestHandler();

// apollo
apolloServer.applyMiddleware({ app, path: '/api' });
apolloServer.installSubscriptionHandlers(httpServer);

async function start() {
  await connectMongoDB();
  await nextApp.prepare();
  app.all('*', nextHandle);
  httpServer.on('request', app.handler);
  httpServer.listen({ port }, () => {
    console.log(`🚀  Apollo API ready at :${port}${apolloServer.graphqlPath}`);
    console.log(
      `🚀  Apollo WS ready at :${port}${apolloServer.subscriptionsPath}`
    );
  });
}

start();

热重装

为了实现该功能nodemon,我们添加了一个名为 的 rollup 插件@rollup/plugin-run

🍣 Rollup 插件,可在构建完成后使用 Node 运行您的 bundle。

使用此插件比使用 nodemon 能获得更快的结果。

(根据我的使用经验,这个插件比……更快nodemon

yarn add @rollup/plugin-run -D
// or
npm i @rollup/plugin-run --save-dev

(我们将导入上述软件包rollup.config.js,这可能会引起程序的警告eslint,您可以选择eslint-disable忽略警告或将该软件包添加为常规依赖项)。

回到rollup.config.js

import run from '@rollup/plugin-run';

export const roll = rollup;

const dev = process.env.NODE_ENV !== 'production';

export default {
  input: 'api/server.js',
  output: {
    file: 'bundle.js',
    format: 'cjs',
  },
  plugins: [
    dev && run(),
  ],
};

我们将@rollup/plugin-run其导入并包含在内plugins。请注意,这只会在开发环境中运行(通过检查process.env.NODE_ENV)。

将脚本添加到 package.json 文件中。

{
  "scripts": {
    "start": "node bundle.js",
    "build": "NODE_ENV=production rollup -c",
    "dev": "rollup -c -w",
  }
}

我们的start脚本只是简单地运行输出结果bundle.js

我们的build脚本在生产环境下运行rollupNODE_ENV(在Windows系统中可能需要这样做cross-env

我们dev调用了rollup该标志。该标志-c表示使用我们的配置文件rollup.config.js。如果磁盘上的源文件发生更改,该标志-w会重新构建我们的软件包。实际上,@rollup/plugin-run它并不执行热重载,而只是在每次重新编译时运行 Node 进程rollup

.env 文件呢?

我们.env在开发中经常使用它。@rollup/plugin-run它允许我们执行一个参数。在代码中rollup.config.js,编辑我们的run()函数。

run({
  execArgv: ['-r', 'dotenv/config'],
})

这样我们就可以使用node -r(--require)参数了dotenv/config。这种用法可以在这里看到。

整合巴别塔

即使我们不使用 Babel 进行转译import/exportrequire/module.exports但在某些情况下我们仍然需要它。例如,我用它来@babel/plugin-proposal-optional-chaining实现可选链式调用(顺便说一句,这个提案太棒了🔥)。

我们需要的插件是rollup-plugin-babel

yarn add -D @babel/core rollup-plugin-babel
// or
npm i --save-dev @babel/core rollup-plugin-babel 

现在我们可以把它添加到rollup.config.js……

import run from '@rollup/plugin-run';
import babel from 'rollup-plugin-babel';

const dev = process.env.NODE_ENV !== 'production';

export default {
  input: 'api/server.js',
  output: {
    file: 'bundle.js',
    format: 'cjs',
  },
  plugins: [
    babel(),
    dev &&
      run({
        execArgv: ['-r', 'dotenv/config'],
      }),
  ],
};

默认配置rollup-plugin-babel会从 . 读取.babelrc。但是,如果您像我一样,没有.babelrc为 Node 服务器,而是为 React 或 Next.js 等框架配置了 ,您可以选择不这样做。通过编辑 即可babel()

babel({
  babelrc: false,
  plugins: ['@babel/plugin-proposal-optional-chaining'],
})

就是这样!

文章来源:https://dev.to/hoangvvo/develop-node-app-in-es6-without-nodemon-and-babel-g9j