转载自:https://www.cnblogs.com/qcloud1001/p/10167756.html
https://www.cnblogs.com/ajianbeyourself/p/8863023.html
1.模块化
模块化是指把一个复杂的系统分解到一个一个的模块。
模块化开发的优点:
(1)代码复用,让我们更方便地进行代码管理、同时也便于后面代码的修改和维护。
(2)一个单独的文件就是一个模块,是一个单独的作用域,只向外暴露特定的变量和函数。这样可以避免污染全局变量,减少变量命名冲突。
js模块化规范有:CommonJS、AMD、CMD、ES6的模块系统。
1.1 CommonJS 规范
是服务器端模块的规范,由nodejs推广使用。该规范的核心思想是:允许模块通过require方法来同步加载所要依赖的其他模块,然后通过 exports 或 module.exports 来导出需要暴露的接口。
// 导出 module.exports = moduleA.someFunc; // 导入 const moduleA = require('./moduleA');
1.2 AMD
AMD采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是require.js(还有个js库:curl.js)
// 定义一个模块 define('module', ['dep'], function (dep) { return exports; }); // 导入和使用 require(['module'], function (module) { });
1.3 ES6模块化
ES6在语言的层面上实现了模块化。浏览器厂商和 Node.js 都宣布要原生支持该规范。它将逐渐取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
在 ES6 中,使用export关键字来导出模块,使用import关键字引用模块。但是浏览器还没有完全兼容,需要使用babel转换成ES5。
// 导出 export function hello() { }; export default { // ... }; // 导入 import { readFile } from 'fs'; import React from 'react';
使用import导入模块时,需要知道要加载的变量名或函数名。
在ES6中还提供了export default,为模块指定默认输出。对应导入模块import时,不需要使用大括号。
2. Babel
在1.3中,我们提到了由于浏览器兼容问题,需要使用Babel将es6转成es5。官方给出的定义是,将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。从中,我们可以看出,Babel的主要功能是“翻译”。
实际上babel转换后的代码是遵循commonJS规范的,而这个规范,浏览器(支持的是 ECMA Script)并不能识别。因此导入到浏览器中会报错,而nodeJS是commonJS的实现者,所以在babel转换后的代码是可以在node中运行的。
为了将babel生成的遵循commonJS规范的es5写法能够在浏览器上直接运行,我们就借住了webpack这个打包工具来完成。
Babel中的preset:即一组预先设定的插件(plugins)
2.1 Babel配置文件的选择
之前版本的babel都是使用.baberc
来做配置文件,babel7引入了babel.config.js
。但是它并不是.baberc
的替代品,二者根据使用的场景不同自行选择。
.babelrc
{ "presets": ["@babel/preset-flow","@babel/preset-react", "@babel/preset-typescript"], "plugins": [...] }
babel.config.js
module.exports = function () { const presets = [ ["env", { "targets": { //指定要转译到哪个环境 //浏览器环境 "browsers": ["last 2 versions", "safari >= 7"], //node环境 "node": "6.10", //"current" 使用当前版本的node }, //是否将ES6的模块化语法转译成其他类型 //参数:"amd" | "umd" | "systemjs" | "commonjs" | false,默认为'commonjs' "modules": 'commonjs', //是否进行debug操作,会在控制台打印出所有插件中的log,已经插件的版本 "debug": false, //强制开启某些模块,默认为[] "include": ["transform-es2015-arrow-functions"], //禁用某些模块,默认为[] "exclude": ["transform-es2015-for-of"], //babel / preset-env处理polyfill的方式。 //参数:usage | entry | false,默认为false. "useBuiltIns": false }] ]; const plugins = [ "@babel/transform-arrow-functions" ]; return { presets, plugins }; }
useBuiltIns的三个参数都是什么意思呢?
-
entry:在引用程序入口导入一次babel / polyfill,多次导入可能会有全局冲突或其他问题。
-
usage:自动为每个文件添加特定的polyfill
-
false:不要为每个文件自动添加polyfill,也不要将“@ babel / polyfill”导入到单个polyfill。
babel.config.js: 项目范围内的配置,根目录。配置可用于node_modules文件
2.2 需要安装的依赖
-
@babel/core:这个是babel的核心包,核心的api都在这里。
-
@babel/cli :这是一个通过命令对js文件进行转换的工具。
-
@babel/preset-env:指定转换的工作环境
-
@babel/polyfill:相当于一个填充,因为babel本身只支持转换箭头函数、结构赋值这些语法糖类的语法,而一些新的API或者Promise函数等是无法转换的。
@babel/polyfill
就是解决这个问题的。后面我会详细介绍。【注意】babel/polyfill安装时是--save而不是--save-dev