美文网首页
当import/export、require/module.ex

当import/export、require/module.ex

作者: 李贵功 | 来源:发表于2019-06-03 22:31 被阅读0次

    ES6的模块化: import export default

    common.js的模块化: require module.exports node.js使用该规范

    为什么有模块概念

    理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。

    但是,Javascript不是一种模块化编程语言,在es6以前,它是不支持”类”(class),所以也就没有”模块”(module)了。同时以前也没有webpack这样的工具,可以使用node去操作文件,读取文件内容, 然后达到引入文件内容的目的.(也就是模块化)--在不同的文件中放着不同的功能模块

    Common.js

    首先需要明白的在node中每个文件都是一个自执行函数(只不过我们肉眼凡胎看不出来,哈啊哈)

    (function (exports, require, module, __filename, __dirname) {
        module.exports = exports = this
        return module.exports
    })()
    

    为了说明module.exports = exports = this请看下面例子

    a.js

    this.a = 123  // 第一种
    exports.a = 123   //第二种
    module.exports.a = 123  // 第三种
    

    b.js

    let a = require('./a')
    console.log(a)
    

    效果:


    image

    ES6中的模块化

    import/export

    export defaultexport 的区别

    1. 在一个文件或模块中 export 可以有多个,但 export default 仅有一个
    2. 通过 export 方式导出,在导入时要加 { },而 export default 则不需要
    1.export
    //a.js
    export const str = "小生方勤";
    //b.js
    import { str } from 'a';   // 导入的时候需要花括号
    
    2.export default
    //a.js
    const str = "小生方勤";
    export default str;
    //b.js
    import str from 'a';      // 导入的时候无需花括号
    

    export default const a = 1; 这样写是会报错的哟。

    es6 的导出模块写法有

    export default 123;
    
    export const a = 123;
    
    const b = 3;
    const c = 4;
    export { b, c };
    

    虽然我们一般在像Vue一些框架中都可以使用Es6的语法进行导入导出,但是babel 会将这些统统转换成 commonjs 的 exports。

    exports.default = 123;
    exports.a = 123;
    exports.b = 3;
    exports.c = 4;
    exports.__esModule = true;
    

    babel 转换 es6 的模块输出逻辑非常简单,即将所有输出都赋值给 exports,并带上一个标志 __esModule 表明这是个由 es6 转换来的 commonjs 输出。

    babel将模块的导出转换为commonjs规范后,也会将引入 import 也转换为 commonjs 规范。即采用 require 去引用模块,再加以一定的处理,符合es6的使用意图。

    也就是所有最后通过webpack打包后都将转化为common.js的规范

    引入 default

    对于最常见的

    import a from './a.js';
    

    在es6中 import a from './a.js' 的本意是想去引入一个 es6 模块中的 default 输出。

    通过babel转换后得到 var a = require(./a.js) 得到的对象却是整个对象,肯定不是 es6 语句的本意,所以需要对 a 做些改变。

    我们在导出提到,default 输出会赋值给导出对象的default属性。

    exports.default = 123;
    

    所以这里最后的 a 变量就是 require 的值的 default 属性。如果原先就是commonjs规范的模块,那么就是那个模块的导出对象。

    引入 * 通配符

    我们使用 import * as a from './a.js' es6语法的本意是想将 es6 模块的所有命名输出以及defalut输出打包成一个对象赋值给a变量。

    已知以 commonjs 规范导出:

    exports.default = 123;
    exports.a = 123;
    exports.b = 3;
    exports.__esModule = true;
    

    那么对于 es6 转换来的输出通过 var a = require('./a.js') 导入这个对象就已经符合意图。

    import { a } from './a.js'

    import { a } from './a.js'
    直接转换成 require('./a.js').a 即可。

    总结

    经过上面的转换分析,我们得知即使我们使用了 es6 的模块系统,如果借助 babel 的转换,es6 的模块系统最终还是会转换成 commonjs 的规范。所以我们如果是使用 babel 转换 es6 模块,混合使用 es6 的模块和 commonjs 的规范是没有问题的,因为最终都会转换成 commonjs。

    问题

    为何有的地方使用 require 去引用一个模块时需要加上 default?

    require('xx').default

    我们在上文 babel 对导出模块的转换提到,es6 的 export default 都会被转换成 exports.default,即使这个模块只有这一个输出。

    我们经常会使用 es6 的 export default 来输出模块,而且这个输出是这个模块的唯一输出,我们会误以为这种写法输出的是模块的默认输出。

    // a.js
    
    export default 123;
    
    // b.js 错误
    
    var foo = require('./a.js')
    

    在使用 require 进行引用时,我们也会误以为引入的是a文件的默认输出。

    结果这里需要改成 var foo = require('./a.js').default

    这个场景在写 webpack 代码分割逻辑时经常会遇到。

    require.ensure([], (require) => {
       callback(null, [
         require('./src/pages/profitList').default,
       ]);
     });
    

    模块依赖的优化


    模块依赖的优化

    我们在使用各大 UI 组件库时都会被介绍到为了避免引入全部文件,请使用 babel-plugin-component 等babel 插件。

    import { Button, Select } from 'element-ui'
    

    由前文可知 import 会先转换为 commonjs, 即

    var a = require('element-ui');
    var Button = a.Button;
    var Select = a.Select;
    

    var a = require('element-ui'); 这个过程就会将所有组件都引入进来了。

    所以 babel-plugin-component就做了一件事,将 import { Button, Select } from 'element-ui' 转换成了

    import Button from 'element-ui/lib/button'
    import Select from 'element-ui/lib/select'
    

    即使转换成了 commonjs 规范,也只是引入自己这个组件的js,将引入量减少到最低。

    所以我们会看到几乎所有的UI组件库的目录形式都是

    |-lib
    ||--component1
    ||--component2
    ||--component3
    |-index.common.js
    

    index.common.jsimport element from 'element-ui' 这种形式调用全部组件

    给个element的链接去看看吧 :https://element.eleme.cn/#/zh-CN/component/quickstart

    相关文章

      网友评论

          本文标题:当import/export、require/module.ex

          本文链接:https://www.haomeiwen.com/subject/eatkxctx.html