Appearance
第十一章:支持 .json 模块加载(兼容 import 与 require)
本节目标:理解“第十一章:支持 .json 模块加载(兼容 import 与 require)”的核心思路,并能把它用于实际开发或面试表达。 非常好,我们继续进入:
📦 ✅ 本章目标:
- 支持加载 .json 文件
- 允许通过 import data from './x.json' 或 require('./x.json') 获取 JSON 对象
- 模拟 Node.js 中对 JSON 模块的处理方式
🧱 项目结构(新增) jsonloader/├── src/│ ├── data.json│ ├── esm.mjs│ ├── cjs.js│ └── main.mjs├── bundler.js└── dist/bundle.js
📄 src/data.json { "appName": "MiniBundler", "version": "1.0.0"} 📄 src/esm.mjs import data from './data.json';export const msg = 'App: ' + data.appName; 📄 src/cjs.js const data = require('./data.json');module.exports = { ver: data.version }; 📄 src/main.mjs import { msg } from './esm.mjs';const { ver } = require('./cjs.js'); console.log(msg);console.log('Version:', ver);
🔧 修改 bundler.js(支持 .json 模块)✅ 步骤 1:parseModule 增加 JSON 支持 function parseModule(filePath) { const absPath = path.resolve(filePath); if (visited.has(absPath)) return null; visited.add(absPath); const ext = path.extname(absPath); const rawCode = fs.readFileSync(absPath, 'utf-8'); const deps = []; const isESM = ext === '.mjs'; const isJSON = ext === '.json'; if (isJSON) { return { id: id++, absPath, rawCode, deps: [], isESM, isJSON: true }; } if (isESM) { const ast = acorn.parse(rawCode, { sourceType: 'module', ecmaVersion: 'latest' }); for (const node of ast.body) { if (node.type === 'ImportDeclaration') { deps.push(node.source.value); } } } else { const requireRegex = /require('"['"])/g; let match; while ((match = requireRegex.exec(rawCode))) { deps.push(match[1]); } } return { id: id++, absPath, rawCode, deps, isESM, isJSON: false };}
✅ 步骤 2:transformCode 支持 JSON 转换 在 transformCode(mod) 中添加: if (mod.isJSON) { const parsed = JSON.parse(mod.rawCode); return Object.assign(exports, ${JSON.stringify(parsed)});;} 并在后面补上 fallback: // fallbackreturn code;
✅ 步骤 3:确保路径后缀自动补全(导入时) 你可以在 parseModule() 和 transformCode() 中确保: const ensureExt = (filepath) => ['.mjs', '.js', '.json'].some(ext => filepath.endsWith(ext)) ? filepath : filepath + '.js'; // 默认补 js,你也可以更智能 // 解析依赖路径时:const resolved = path.resolve(path.dirname(mod.absPath), ensureExt(dep));
🚀 打包运行 node bundler.js src/main.mjs --out dist/bundle.jsnode dist/bundle.js
✅ 输出结果: App: MiniBundlerVersion: 1.0.0
✅ 本章成果总结
| 特性 | 实现 |
| JSON 模块解析 | ✔ |
| import JSON 支持 | ✔ |
| require JSON 支持 | ✔ |
| JSON 自动序列化导出 | ✔ |
| 多种模块类型混用支持 | ✔ |
🔮 下一章预告(第十二章) 下一步,我们可以进入: 支持生成模块间依赖图可视化(Graphviz 或 HTML 格式) 让你能一眼看出模块结构、依赖关系,甚至是打包优化点,像 Rollup、Webpack 分析图一样。 是否继续?我可以帮你生成模块依赖关系图 HTML 或 DOT 文件 ✅ > 来自 <https://chatgpt.com/c/6805aef6-e7b4-8004-ab43-9a137f666985>
