webpack(番外篇)-commonjs

963 阅读3分钟

Commonjs规范

学习过webpack的小伙伴想必都知道什么是commonjs规范了吧,就是我们写webpack.config.js时,导入导出的方式。

  • 有没有人和我一个想法想知道它的实现原理呢?
  • 因为我们知道commonjs的导入和导出是需要借助webpack编译才能正常使用
  • 那我们来研究研究它们是如何实现这个编译过程的吧
  • 首先模块化的本质就是隔离控件,证明他们是有作用域隔绝的
  • 那么我们就先来一个立即执行函数

我们先来看看commonjs的代码是什么样的吧

  • 我们随便创建个js文件然后在里面随便写点东西
const dateFormate=(date)=>{
  return '1232-23-23'
}

module.exports={
  dateFormate
}

我们这样就导出了一个dateFormate函数
接下来我们再创建一个文件夹引入该函数

const {dateFormate} = require('./js/formate')

console.log(dateFormate('abc'));

这样就再一个文件中引入了我们刚刚导出的函数了

  • 接下来让我们分析一下他们的结构
  • 有两个文件,我们可以看作两个对象或者函数
  • 还有他们的存在打包之后是不会影响其他的函数的,再引入文件内随便修改都是为所谓的
  • 那么我们就应该有一个独立的作用域,避免影响其他的文件了
(function(){
    //pass
}())

这样我们就得到了一个独立的作用了,不会被外界所影响

  • 接下来是什么呢?
  • 我们看看这个导出函数的文件,首先它是一个js文件,那么我们就可以把他抽象为一个对象
  • 以导入的时候的路径作为他的key
(function(){
    var __webpack_module__ = {
           './js/formate':function(module){
               const dateFormate=(date)=>{
                  return '1232-23-23'
               }
               module.exports={
                   dateFormate
               }
           }
    }
}())

代码中的module我待会会告诉大家从何而来,

  • 这个代码就是commonjs 导出的原理了
  • 我们在js中写的代码最后会被webpack编译成这样子
  • 我们可以看到 我们导出的时候写的path被当成了以key值,被导出的函数被编译成了对应的value值 -接下来我们看看他是如何实现导入的
(function(){
    //定义一个对象
    //模块的路径(key):函数(value)
    var __webpack_module__ = {
           './js/formate':function(module){
               const dateFormate=(date)=>{
                  return '1232-23-23'
               }
               module.exports={
                   dateFormate
               }
           }
    }
    //定义一个对象,作为加载模块的缓存
    var __webpack_module_cache__={}
    //这个我们可以当成我们的 导入的require函数,而这个moduleId就是路径
    var __webpack__require__  = function(moduleId){
        //1.我们先判断一下  __webpack_module_cache__ 里面有没有保存之前的值
        //有的话我们就直接返回出去就可以了
        if(__webpack_module_cache__[moduleId]!=undefined){
            return __webpack_module_cache__[moduleId].exports
        }
         //2.给module和__webpack_module_cache__[moduleId]变量赋值同一个对象
        var module = __webpack_module_cache__ = {exports:{}}
         //3.加载执行模块
        __webpack_module__[moduleId](module,module.exports,__webpack_module_cache__)
        //4.导出module.exports {dateFormate:function}
        return module.exports
    }
}())
  • 以上我们已经完了大部分了
  • 接下来就是如何导出这一块东西了
(function(){
    //定义一个对象
    //模块的路径(key):函数(value)
    var __webpack_module__ = {
           './js/formate':function(module){
               const dateFormate=(date)=>{
                  return '1232-23-23'
               }
               module.exports={
                   dateFormate
               }
           }
    }
    //定义一个对象,作为加载模块的缓存
    var __webpack_module_cache__={}
    //这个我们可以当成我们的 导入的require函数,而这个moduleId就是路径
    var __webpack__require__  = function(moduleId){
        //1.我们先判断一下  __webpack_module_cache__ 里面有没有保存之前的值
        //有的话我们就直接返回出去就可以了
        if(__webpack_module_cache__[moduleId]!=undefined){
            return __webpack_module_cache__[moduleId].exports
        }
         //2.给module和__webpack_module_cache__[moduleId]变量赋值同一个对象
        var module = __webpack_module_cache__ = {exports:{}}
         //3.加载执行模块
        __webpack_module__[moduleId](module,module.exports,__webpack_module_cache__)
        //4.导出module.exports {dateFormate:function}
        return module.exports
    }
    //具体开始执行代码逻辑
    (function(){
        const {dateFormate} = __webpack__require__('./js/formate')
        console.log(dateFormate('asdasd'))
    })()
}())

以上就是commonjs的导入导出原理了

  • 如果有多个文件,那么只要多个块级作用域就可以避免互相影响了

结尾

  • 到这里我们就结束啦,希望大家都可以好好学习
  • 接下来我们会给大家带来webpack-loader的篇章,敬请期待!