模块化

模块化开发

一、模块化的优缺点

优点:

相比于使用一个js文件,这种多个js文件实现最简单的模块化的思想是进步的。

缺点:

污染全局作用域。 因为每一个模块都是暴露在全局的,简单的使用,会导致全局变量命名冲突,当然,我们也可以使用命名空间的方式来解决。 对于大型项目,各种js很多,开发人员必须手动解决模块和代码库的依赖关系,后期维护成本较高。 依赖关系不明显,不利于维护。

二、模块化规范

1、一个文件就是一个模块

2、每个模块都有单独的作用域

3、通过module.exports导出成员

4、通过require函数载入模块

三、commonJS

CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。像Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式,所以CommonJS规范比较适用。但如果是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。所以就有了 AMD  CMD 解决方案。

1、AMD

AMD即ASynchronous Module Definition ,异步模块定义,它是一个在浏览器端模块化开发的规范,define是定义模块,require是调用模块。

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {  exports.verb = function() {        return beta.verb();      //或者:      return require("beta").verb();  }});

优点:

适合在浏览器环境中异步加载模块。可以并行加载多个模块。

缺点:

AMD使用起来相对复杂,js频繁引用,提高了开发成本,并且不能按需加载,而是必须提前加载所有的依赖。

2、CMD

CMD是SeaJS 在推广过程中对模块定义的规范化产出。

CMD和AMD的区别有以下几点:

1.对于依赖的模块AMD是提前执行,CMD是延迟执行。不过RequireJS从2.0开始,也改成可以延迟执行(根据写法不同,处理方式不通过)。

2.AMD推崇依赖前置(在定义模块的时候就要声明其依赖的模块),CMD推崇依赖就近(只有在用到某个模块的时候再去require——按需加载)。

//AMDdefine(['./a','./b'], function (a, b) {    //依赖一开始就写好    a.test();    b.test();});//CMDdefine(function (requie, exports, module) {        //依赖可以就近书写    var a = require('./a');    a.test();        ...    //软依赖    if (status) {            var b = requie('./b');        b.test();    }});

四、ES Modules

一、基本特性

通过给script 添加type = modeule的属性,就可以ES Module 的标准执行其中的Js代码了

1、自动采用严格模式

2、每个ES Module都是运行在单独的私有作用域中

3、ESM 是通过 CORS 的方式请求外部的 JS 模块的

附加:CORS

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

4、ESM 的 script 标签会延迟执行脚本

网页渲染完成后再执行script标签

二、ES Modules 导入和导出

//html//app.js// import {default as nameNew} from './module.js'// import {fooHello} from './module.js'import {hello2} from './module.js'import aaa from './module.js' //默认导出// console.log(fooHello())console.log(hello2())console.log(aaa)//module.jsvar name = "123";export function hello() {    console.log('hello')}export const hello2 = () =>{    console.log('hello2')}class Person{}// export{//    name as default,  //default 默认导出//    hello as fooHello,//    hello2// }export default name  //默认导出,aaa

注意点:

1、导入的成员是只读成员,不能修改,虽然声明的时候用var 声明的(项目中可以应用到配置文件中)

2、导出的时候不是字面量对象,导入的时候也不是结构赋值

3、导出的并不是导出成员的值,而是地址,而不是值

附加:browser-sync 的用法

1、yarn init

2、yarn add browser-sync --dev

3、进入项目的根目录运行browser-sync start --server --files '**/*.js',提示browser-sync 不是内部或外部命令

原因:node只有--global or -g才是全局安装的包,一般才会出现在PATH里,才可以直接运行命令,否则就在./node_modules/.bin/, 需要加上路径才可以运行,也可以在package.json里添加入口,这个入口的环境变量默认包含node_modules/.bin, 可以直接

1. "scripts": {2. "watch": "browser-sync start --server --files '**/*.js'"  //监视的js文件3. }

运行: npm run watch

三、ES Modules 浏览器环境Polyfill

https://unpkg.com/browse/[email protected]/dist/

Polyfill 是一块代码(通常是 Web 上的 JavaScript),用来为旧浏览器提供它没有原生支持的较新的功能。

这种引用IE不识别

开发阶段的话,可以通过转为es5的语法,nomodule 是用于,在识别type= modeule的浏览器,如果识别就不加在这些js.

四、ES Modules 在node环境中的使用

1、在node环境中的使用

第一,需要将.js的文件改为.mjs文件

第二,启动时需要额外添加 `--experimental-modules` 参数; node --experimental-modules index.mjs

//可以加载内置模块import fs from 'fs'fs.writeFileSync('./bar.txt','nohaoya')//支持,可以加载内置模块的成员import {writeFileSync} from 'fs'writeFileSync('./b.txt','nohaoya')//支持,支持导入第三方插件,yarn add lodash// import _ from 'lodash'// console.log(_.camelCase('ES Module')) //驼峰命名法//不支持,第三方的插件,都是支持默认导出的,不能导出其中的某个方法// import {camelCase} from 'lodash'// console.log(camelCase('es module'))

第三,ES Module 中引入 Common.js

common.js中始终只可以导出一个默认成员,

module.exports = {

foo: 'common.js'

}

exports.foo = 'common.js'

两种写法都可以

ES Module中可以导入Common.js,

import mod from './common.js'

//不能直接提取成员,

import { foo } from './common.js'

第四、在原生node环境中,common.js不能通过require的方式载入ES module

const mod = require('./module.js')  //错误

总结:ES Modules中可以导入 CommonJS

Common.js中不能导入 ES Modules

  CommonJS始终只会导出一个默认对象

注意import不是解构导出对象

第五、新版node

在新版的node环境中,需要在package.json中添加{type: "module"},就可以不用把文件名改为.mjs

commonjs使用,可以把.js改为.cjs

第六、使用babel

yarn add @babel/node @babel/core @babel/preset-env --dev

yarn babel-node index.js  --presets=@babel/preset-env

(如果不想用参数,可以在文件中添加 .babelrc 的文件,{"preset" : ["@babel/preset-env"]},

运行yarn babel-node index.js

如果不用preset,可以yarn add @babel/plugin-transform-modules-connomjs,{"plugin" : ["@babel/plugin-transform-modules-connomjs"]},

你可能感兴趣的:(模块化)