首页 > 其他分享 >commonjs

commonjs

时间:2024-04-17 22:15:25浏览次数:32  
标签:commonjs const exports js 模块 path dirname

Commonjs

什么是 CommonJs

  1. CommonJs 是 js 模块化的社区规范

模块化产生的原因

  1. 随着前端页面复杂度的提升,依赖的第三方库的增加,导致的 js 依赖混乱,全局变量的污染,和命名冲突
  2. 单个 js 文件内容太多,导致了维护困难,拆分成为多个文件又会发生第一点描述的问题
  3. v8 引擎的出现,让 js 有了媲美编译型语言的运行速度,大大激励了前端开发者

CommonJS 的使用环境

  1. nodejs 实现了 CommonJS 模块化规范

CommonJs 有哪些规定

  1. 每一个文件就是一个模块
  2. 模块中的变量和函数不会污染全局(解决了全局污染和命名冲突)
  3. 提供给外部使用的内容需要导出
  4. 使用其他模块的内容需要导入 (模块的导入和导出共同解决了 js 依赖混乱的问题)
  5. 模块不会重复加载,模块第一次导入后会将第一次导入的结果缓存,下次导入时,直接使用缓存的结构
  6. 省略一些细碎的内容在下面代码中提及.....

commonJS 语法

  1. 导入
//这是导入一个模块,module.js;commonjs中规定require导入模块时可以省略.js后缀
const module1 = require("./module1");
//如果没有寻找到dir.js文件,而发现了dir路径,则寻找dir路径下package.json 的main属性指定的文件
//如果package.json未指定路径,则触发默认规则 依次查找查找 index.js index.json
const module2 = require("./dir");
//如果require不是相对路径,则会去node_module中寻找该模块,重复module1 和module2 的步骤
//如果没有node_modules 或node_modules 中不存在模块则继续向上级目录寻找node_modules,直到根目录
const module3 = require("module3");
  1. 导出
module.exports = {
  //这里输入导出的内容
};

//这也是导出
exports.a = "a";

//注意 module.exports导出和exports[属性名]导出不可共存
//module.exports会覆盖掉exports导出的内容

简易实现类 nodejs 模块化环境

const fs = require("fs");
const Path = require("path");
const vm = require("vm");
const ModuleStack = [];

function isRootDirectory(path) {
  // Windows 根路径
  const windowsRootDirectory = /^[a-zA-Z]:\\$/;
  // Unix/Linux 根路径/
  const unixRootDirectory = /^\//;

  return windowsRootDirectory.test(path) || unixRootDirectory.test(path);
}

function isRelativeDirectory(path) {
  //匹配 ../ 或者 ./开头的路径
  const relativeDirectory = /^(\.\.\/|\.\/).+/;
  return relativeDirectory.test(path);
}
// 计算node_modules路径
let computePaths = (dirname) => {
  let paths = [];
  let path = dirname;
  let node_modules = "./node_modules";
  while (
    !isRootDirectory(path) ||
    !paths.includes(Path.resolve(path, node_modules))
  ) {
    paths.push(Path.resolve(path, node_modules));
    path = Path.resolve(path, "../");
  }
  return paths;
};

function myRequire(path) {
  let truelyPath;
  if (isRelativeDirectory(path)) {
    // 获取真实路径
    truelyPath = Path.resolve(__dirname, path);
  } else {
    //获取可能的node_modules路径
    let paths = computePaths(__dirname);
    for (const item of paths) {
      truelyPath = Path.resolve(item, path);
      if (fs.existsSync(truelyPath)) {
        break;
      }
    }
    if (!truelyPath) {
      throw new Error("Can't find module " + path);
    }
  }
  // 如果缓存中有,直接返回
  if (myRequire.cache[truelyPath]) {
    return myRequire.cache[truelyPath].exports;
  }
  // 读取文件内容
  const content = fs.readFileSync(path, "utf-8");
  // 包装代码
  const wrapper = [
    "(function (exports, require, module, __filename, __dirname) { \n",
    "\n})",
  ];
  // 拼接代码
  const wrapperContent = wrapper[0] + content + wrapper[1];

  // 获取文件路径和文件名
  let dirname = Path.dirname(truelyPath);
  let filename = truelyPath;
  let parentModule =
    ModuleStack.length > 0 ? ModuleStack[ModuleStack.length - 1] : null;
  // 模块对象
  const Module = {
    id: Object.keys(myRequire.cache).length > 0 ? filename : ".",
    path: dirname,
    exports: {},
    parent: parentModule,
    filename: filename,
    loaded: false,
    children: [],
    paths: computePaths(dirname),
  };
  if (parentModule) {
    parentModule.children.push(Module);
  }
  //模块入栈
  ModuleStack.push(Module);
  // 需要运行的函数
  const moduleScope = vm.runInThisContext(wrapperContent);
  // 运行代码
  moduleScope.call(
    Module.exports,
    Module.exports,
    myRequire,
    Module,
    filename,
    dirname
  );
  // 标记模块已加载
  Module.loaded = true;
  //模块出栈
  ModuleStack.pop();
  // 缓存模块
  myRequire.cache[truelyPath] = Module;
  return Module.exports;
}

myRequire.cache = Object.create(null);

模块化的意义

  1. 解决在模块化出现之前的js依赖混乱,全局污染命名冲突的问题
  2. 模块化的出现让js代码可以拆分为多个模块共同协作,单个js文件过长的问题,降低了维护难度。
  3. 模块化的出现让js开发大型项目出现了可能

ps:当前内容为学习commonjs理解,内容正确性请谨慎甄别。

标签:commonjs,const,exports,js,模块,path,dirname
From: https://www.cnblogs.com/jiangyun/p/18141885

相关文章

  • 用代码验证,esm 导出的是值的引用,commonjs导出的是值的拷贝
    首先需要学习一下esm和commonjs的区别,其中一条关于导出值我们可以手动验证一下,先记住结论esm导出的是值的引用commonjs导出的是值的拷贝没错我又遇到这个问题了,面试官先问我commonjs和esm有啥区别?然后问如果commonjs导出一个模块,在模块内部改变一个值,模块外部......
  • JS模块化——AMD、CommonJS和ESModules
    文章目录JS模块化——AMD、CommonJS和ESModules方法介绍传统方法:立即执行函数:异步模块定义AMD:CommonJS:ESModules:CommonJS和ESModules区别JS模块化——AMD、CommonJS和ESModules前端模块化是指将前端代码拆解成互相独立的小块,每一块完成特定的功能,这些小块被......
  • CommonJS和ES Module 的区别
    最近开始接触web编程,一上来就看到一堆关于module的信息,commomJSmodule和ESmodule直接给我看懵了。网上搜一下,总结一下。大概意思就是CommonJS先出现,用在nodejs编程中。这玩意在浏览器中支持的不太好,随着时间的推移浏览器代码也需要模块化呀,于是ESmodule就出现了。ES......
  • CommonJS、AMD、CMD、ES Module
    依赖前置和依赖就近RequireJS采用依赖前置,举个例子就是炒菜前一次性把所有食材洗好,切好,根据内部逻辑把有些酱料拌好,最后开始炒菜,前面任何一个步骤出现问题都能较早发现错误;SeaJS的依赖就近就是要炒青椒了去切青椒要炒肉了去切肉cmd:例如seajsamd:例如requirejscommonjs模块规范nod......
  • [Typescript] Handle CommonJS import in Typescript
    Let'ssayweneedtousealibrarywithcommonJScode.classMelon{cutIntoSlices(){}}module.exports=MelonThenwewanttoimportthisinsideourTypescriptproject:import*asmelonNamespacefrom"./melon"//typescriptdoesn......
  • CommonJS 模块
    在Node.js中,每个文件都被视为一个单独的模块。CommonJS模块系统在 module 核心模块中实现。启用Node.js有两个模块系统:CommonJS模块和 ECMAScript模块。默认情况下,Node.js会将以下内容视为CommonJS模块:扩展名为 .cjs 的文件;当最近的父 package.json 文件......
  • CommonJS模块和ECMAScript模块
    CommonJS(简称cjs),为node.js打包javaScript的原始方法,使用require和imports(module.exports)语句定义模块ECMAScript模块(简称esm),是ecma262标准下封装的JavaScript代码重用的官方标准格式。使用import和export语句定义模块 -cjs只有在node.js环境使用。-esm在node.js和浏览器......
  • commonJS四个重要环境变量:require、exports、module、global
    按照CommonJS规范,在任何模块代码的作用域下内置了以下哪些变量?AmoduleBcontextCrequireDexports正确答案:ACD浏览器不兼容CommonJS的根本原因,在于缺少四个Node.js环境的变量。commonJS四个重要环境变量:require、exports、module、global......
  • ES6 module和CommonJS的区别
    ES6module和CommonJS的区别主要有5点ES6module是编译时导出接口,CommonJS是运行时导出对象。ES6module输出的值的引用,CommonJS输出的是一个值的拷贝。ES6module语法是静态的,CommonJS语法是动态的。ES6module导入模块的是只读的引用,CommonJS导入的是可变的,是一个普通的变......
  • CommonJS简介
    CommonJS简介Tags:JavaScript,Node.js,commonjsPublished:2023/09/26什么是commonjscommonjs是module的一种类型(规范)使用场景CommonJSismainlyusedinserver-sideJSappswithNode,asbrowsersdon'tsupporttheuseofCommonJS.CommonJS主要用于带有Node......