本博客不欢迎:各种镜像采集行为,请尊重知识产权法律法规。大家都是程序员,不要闹得不开心。

在JavaScript代码模块化过程中,commonjs是其中一个产物。根据最初的设计,commonjs是适用于服务器(node)端使用的,类似的概念还有AMD/CMD/es6 module。但是,由于webpack提供的兼容方式的存在,commonjs的写法,实际上也可以用于前端页面里面。

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - commonjs
JavaScript代码模块化,commonjs如何编写并引用?(图6-1)

本文测试环境:chrome@89.0.4389.114webpack@5.36.2node@14.16.0。主要讲述commonjs的基本写法,主要结论是:commonjs写法简单,但是并不是太好用,而且存在着一些大的问题。

模块化的基本概念

JavaScript模块化基本概念就是:一个文件就是一个模块,有自己的作用域。这个文件里面定义的变量、类、函数等,对于别的文件来说,都是不可见的。除非本文件主动使用导出操作,使得这些方法类变量之类的在外部可见。

苏南大叔理解着就是:对每个文件施加了一个隐藏的闭包环境,起到了一个隔绝的作用。写法上非常像class类,似乎就是class里面的public的字样(概念)换成了exports字样(概念),你细品。

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - commonjs-module
JavaScript代码模块化,commonjs如何编写并引用?(图6-2)

commonjs所有代码都运行在模块作用域,不会污染全局作用域。模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。

commonjs的基本写法

和普通的传统函数式编程js相比较的话,其实就是在代码的最末端加上了module.exports字样,其它的地方基本上没有变化。代码类似如下:

var name = 'sunan'
var age = 18
module.exports.name = name
module.exports.getAge = function(){
    return age
}

或者:

var name = 'sunan'
var age = 18
module.exports={
    name:name,
    getAge:function(){
        return age;
    }
}

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - module-code
JavaScript代码模块化,commonjs如何编写并引用?(图6-3)

这里需要特殊说明的是:

  • 理论上来说,上面的module.exports可以缩写成exports,但是并不建议这么使用,因为个别情况下会有问题。
  • 另外,在commonjs模块化方案里面,module就是关键字了,不能被改写。你懂的。

一种简写方式

下面是一个更加简单的写法:

var name = "苏南";
var age = 18;
var getAge = function () {
    return age;
}
function setAge(a) {
    age = a;
}
module.exports = {
    name, age, getAge, setAge
}

这里导出的对象的key和内部的变量名是一致的,就可以这样简写:

module.exports = {
    name, age, getAge, setAge
}

而不是:

module.exports = {
    name:name,
    age:age,
    getAge:getAge,
    setAge:setAge
}

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - commonjs-more
JavaScript代码模块化,commonjs如何编写并引用?(图6-4)

基本使用方法(前后端)

这里需要额外说明的是:commonjs在设计的最开始,就是要提供给node类似的后端环境使用的,并不是提供给传统的网页换的。但是,这些commonjs如果通过webpack处理过的话,这些写法在前端也是一样可以使用的。所以,webpack有识别commonjs的能力。

被模块化的代码写法,如上所示。在其他的地方,进行引用的时候,使用require进行操作,如下所示:

var example = require('./example.js');
var example2 = require('./example2');

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - module-require
JavaScript代码模块化,commonjs如何编写并引用?(图6-5)

webpack额外加工(纯浏览器环境)

node下面直接使用的话,是可以直接识别commonjs的写法的。但是,在纯浏览器环境下使用的话,就恰恰需要编译处理一下才能识别这种commonjs的写法。而webpack恰恰就提供了这种能力,当然,相信其他的打包软件,也会提供类似的能力,这个并非webpack的专利。

这里就简单说说webpack如何处理commonjs。此处测试环境,使用的是:webpack@5.36.2

其实特别简单,直接npx webpack试试(话说npx是个好命令):

npm install -D webpack webpack-cli
npx webpack

配置webpack.config.js(其实没有任何的特殊配置,就是传统的设置entryoutput):

var path = require("path");
module.exports = {
    entry: path.join(__dirname, 'main.js'),
    output: {
        path: __dirname,
        filename: 'main_4_web.js'
    },
};

在这个例子里面,main.js里面,使用require加载了module.js。而module.js就是使用了commonjs标准,利用module.exports导出的一个模块文件。

苏南大叔:JavaScript代码模块化,commonjs如何编写并引用? - webpack-commonjs
JavaScript代码模块化,commonjs如何编写并引用?(图6-6)

存在问题

commonjs写法真的是非常简单,但是,这种写法也存在着天然的缺陷。这里先进行简要的说明:

  • 缺陷一:module.exportsexports,理论上,两者可以相互替代。但是,建议统一使用module.exports
  • 缺陷二:commonjs模块会缓存结果,多次调研的话,是会读取缓存文件。这个问题非常严重,严重违背认知。这个问题在后面的文章里面,苏南大叔会对其进行详细阐述。

相关文章

总结

这里总结一下,commonjs写法和使用方法是非常简单的,默认是用于后端使用的。如果在纯浏览器环境下使用,需要进行编译。commonjs存在着一些天生的缺陷,所以需要写代码的时候,特别注意。

更多commonjs的经验文章,请点击苏南大叔的博客:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。