欢迎光临
我们一直在努力

前端后缀大乱斗:彻底搞懂 .js、.ejs 与 .mjs

它们都带“js”,但一个是模板,一个是历史,一个是未来。

在 JavaScript 的世界里,文件后缀名从来不只是给开发者看的“备注”,更是给运行环境(浏览器、Node.js)看的“军令状”。今天我们把 .js、.ejs 和 .mjs 拉到一起,进行一次“坦白局”。

1. 元老级选手:.js —— 最熟悉的陌生人

身份定位:JavaScript 的通用脚本文件。

在浏览器时代,.js 就是皇法。但在 Node.js 服务端,.js 的身份一直处于“量子叠加态”:

  • 默认立场:在 Node.js 中,默认情况下,.js 被视为 CommonJS (CJS)。这意味着你可以直接用 require() 和 module.exports。

  • 可塑性强:.js 的立场受 package.json 中的 "type" 字段影响。

    • 如果 "type": "commonjs"(默认) → .js 是 CJS。

    • 如果 "type": "module" → .js 摇身一变,变成 ES Module (ESM),可以使用 import/export。

核心痛点:正因为 .js 立场摇摆不定,在大型项目中,单看后缀你无法确定它到底是同步加载还是异步加载,容易引发混乱。

2. 模板界扛把子:.ejs —— 披着 JS 皮的 HTML

身份定位:Embedded JavaScript Templating(嵌入式 JavaScript 模板引擎)。

重要提示:.ejs 和 .js/.mjs 完全不是一回事!它不是用来写逻辑代码的,而是用来写 HTML 页面结构的。

  • 使用场景:服务端渲染(SSR),比如 Node.js + Express 框架。

  • 工作原理:在 .ejs 文件中,你写的是 HTML,但可以通过 <% %> 标签嵌入 JavaScript 逻辑(比如循环、变量输出)。

  • 最终归宿:.ejs 文件永远不会被浏览器或 Node 直接执行。它会在后端被 ejs 这个 npm 包编译成纯 HTML 字符串,再发送给浏览器。

<!– 这是一个 .ejs 文件示例 –>
<h1><%= user.name %></h1>
<% if (user.isAdmin) { %>
<button>删除按钮</button>
<% } %>

3. 新时代的“硬规定”:.mjs —— 标准的捍卫者

身份定位:强制使用 ES Module (ESM) 规范的 JavaScript 文件。

为了彻底解决 .js 的“墙头草”问题,Node.js 引入了 .mjs。

  • 绝对立场:无论 package.json 里 "type" 写的是什么,.mjs 永远被视为 ESM。

  • 语法特权:支持顶层 await;必须使用 import/export;严格模式强制开启。

  • 底层逻辑:由于 ESM 是异步加载,.mjs 强制 Node 使用异步解析器去读取文件。

为什么需要它?为了在项目中安全地混用新旧模块。比如你引入一个第三方库,如果它是 .mjs,Node 就知道必须用 ESM 规则去加载它,绝不含糊。

4. 核心对比总结表

维度.js.ejs.mjs
本质 JavaScript 源码 HTML 模板文件 JavaScript 源码
运行环境 Node.js / 浏览器 Node.js(编译阶段) Node.js
模块系统 不固定(默认 CJS,可切换 ESM) 无(纯文本渲染) 强制 ESM
加载机制 受 package.json 影响 由 ejs 库编译 不受 package.json 影响
核心变量 可能有 require 或 import 只有模板语法 <% %> 无 require,有 import.meta
主要用途 编写业务逻辑 编写服务端 HTML 视图 编写纯净的现代 JS 模块

5. 补充:同样容易混淆的 .cjs

既然提到了 .mjs,就不得不提它同父异母的兄弟 .cjs。

  • .cjs:强制使用 CommonJS 规范。无论 "type" 是什么,它都只能用 require 和 module.exports。

  • 一句话关系:

    • .mjs = 强制 ESM(异步、标准化)。

    • .cjs = 强制 CJS(同步、历史遗产)。

    • .js = 随风倒(看 package.json 的脸色)。

6. 写在最后:开发时的避坑指南

  • 当你写前端页面(React/Vue):大概率只用 .js 或 .jsx/.ts,因为打包工具(Webpack/Vite)接管了一切,后缀名没那么敏感。

  • 当你写 Node.js 后端:

    • 如果你只想写 import 语法,建议直接在 package.json 里加 "type": "module",用 .js 就行。

    • 如果你需要同时维护老项目(CJS)和新功能(ESM),强烈建议:新文件用 .mjs,老文件改名为 .cjs。

    • 千万别在 .ejs 里写 import,那是徒劳的,它只负责画界面。

  • 遇到报错 Cannot use import statement outside a module:说明你的 .js 文件被当作 CJS 了,要么改后缀为 .mjs,要么去改 package.json。

  • 一句话精辟总结:
    .ejs 是画页面的(工匠),.cjs 是开老式燃油车的(保守),.mjs 是开新式电动车的(激进),而 .js 是一辆“油电混动”车,具体烧油还是用电,看你插没插 "type": "module" 这根充电线。

    赞(0)
    未经允许不得转载:171主机测评 » 前端后缀大乱斗:彻底搞懂 .js、.ejs 与 .mjs
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址