export和import是谁的语法?为什么选择 webpack?

举报
DevFeng 发表于 2021/10/19 14:14:12 2021/10/19
【摘要】 export和import是谁的语法?                                                                                                                              ECMAScript 模块ECMAScript 模块(ESM)是在 Web 中使用模块的规范。 所有现代...

export和import是谁的语法?                                                                                                                              

ECMAScript 模块

ECMAScript 模块(ESM)是在 Web 中使用模块的规范。 所有现代浏览器均支持此功能,同时也是在 Web 中编写模块化代码的推荐方式。

webpack 支持处理 ECMAScript 模块以优化它们。

导出

关键字 export 允许将 ESM 中的内容暴露给其他模块:

export const CONSTANT = 42;

export let variable = 42;
// 对外暴露的变量为只读
// 无法从外部修改

export function fun() {
  console.log('fun');
}

export class C extends Super {
  method() {
    console.log('method');
  }
}

let a, b, other;
export { a, b, other as c };

export default 1 + 2 + 3 + more();

导入

关键字 import 允许从其他模块获取引用到 ESM 中:

import { CONSTANT, variable } from './module.js';
// 导入由其他模块导出的“绑定”
// 这些绑定是动态的. 这里并非获取到了值的副本
// 而是当将要访问“variable”时
// 再从导入的模块中获取当前值

import * as module from './module.js';
module.fun();
// 导入包含所有导出内容的“命名空间对象”

import theDefaultValue from './module.js';
// 导入 `default` 导出的快捷方式

将模块标记为 ESM

默认情况下,webpack 将自动检测文件是 ESM 还是其他模块系统。

Node.js 通过设置 package.json 中的属性来显式设置文件模块类型。 在 package.json 中设置 "type": "module" 会强制 package.json 下的所有文件使用 ECMAScript 模块。 设置 "type": "commonjs" 将会强制使用 CommonJS 模块。

{
  "type": "module"
}

除此之外,文件还可以通过使用 .mjs  .cjs 扩展名来设置模块类型。 .mjs 将它们强制置为 ESM,.cjs 将它们强制置为 CommonJs。

在使用 text/javascript  application/javascript mime type 的 DataURI 中,也将使用 ESM。

除了模块格式外,将模块标记为 ESM 还会影响解析逻辑,操作逻辑和模块中的可用符号。

导入模块在 ESM 中更为严格,导入相对路径的模块必须包含文件名和文件扩展名。

想要理解为什么要使用 webpack,我们先回顾下历史,在打包工具出现之前,我们是如何在 web 中使用 JavaScript 的。

在浏览器中运行 JavaScript 有两种方法。第一种方式,引用一些脚本来存放每个功能;此解决方案很难扩展,因为加载太多脚本会导致网络瓶颈。第二种方式,使用一个包含所有项目代码的大型 .js 文件,但是这会导致作用域、文件大小、可读性和可维护性方面的问题。

立即调用函数表达式(IIFE) - Immediately invoked function expressions

IIFE 解决大型项目的作用域问题;当脚本文件被封装在 IIFE 内部时,你可以安全地拼接或安全地组合所有文件,而不必担心作用域冲突。

IIFE 使用方式产生出 Make, Gulp, Grunt, Broccoli 或 Brunch 等工具。这些工具称为任务执行器,它们将所有项目文件拼接在一起。

但是,修改一个文件意味着必须重新构建整个文件。拼接可以做到很容易地跨文件重用脚本,但是却使构建结果的优化变得更加困难。如何判断代码是否实际被使用?

即使你只用到 lodash 中的某个函数,也必须在构建结果中加入整个库,然后将它们压缩在一起。如何 treeshake 代码依赖?难以大规模地实现延迟加载代码块,这需要开发人员手动地进行大量工作。

感谢 Node.js,JavaScript 模块诞生了

Node.js 是一个 JavaScript 运行时,可以在浏览器环境之外的计算机和服务器中使用。webpack 运行在 Node.js 中。

当 Node.js 发布时,一个新的时代开始了,它带来了新的挑战。既然不是在浏览器中运行 JavaScript,现在已经没有了可以添加到浏览器中的 html 文件和 script 标签。那么 Node.js 应用程序要如何加载新的代码 chunk 呢?

CommonJS 问世并引入了 require 机制,它允许你在当前文件中加载和使用某个模块。导入需要的每个模块,这一开箱即用的功能,帮助我们解决了作用域问题。

npm + Node.js + modules - 大规模分发模块

JavaScript 已经成为一种语言、一个平台和一种快速开发和创建快速应用程序的方式,接管了整个 JavaScript 世界。

但 CommonJS 没有浏览器支持。没有 live binding(实时绑定)。循环引用存在问题。同步执行的模块解析加载器速度很慢。虽然 CommonJS 是 Node.js 项目的绝佳解决方案,但浏览器不支持模块,因而产生了 Browserify, RequireJS 和 SystemJS 等打包工具,允许我们编写能够在浏览器中运行的 CommonJS 模块。

ESM - ECMAScript 模块

来自 Web 项目的好消息是,模块正在成为 ECMAScript 标准的官方功能。然而,浏览器支持不完整,版本迭代速度也不够快,目前还是推荐上面那些早期模块实现。

依赖自动收集

传统的任务构建工具基于 Google 的 Closure 编译器都要求你手动在顶部声明所有的依赖。然而像 webpack 一类的打包工具自动构建并基于你所引用或导出的内容推断出依赖的图谱。这个特性与其它的如插件 and 加载器一道让开发者的体验更好。

看起来都不是很好……

是否可以有一种方式,不仅可以让我们编写模块,而且还支持任何模块格式(至少在我们到达 ESM 之前),并且可以同时处理资源和资产?

这就是 webpack 存在的原因。它是一个工具,可以打包你的 JavaScript 应用程序(支持 ESM 和 CommonJS),可以扩展为支持许多不同的静态资源,例如:images, fonts 和 stylesheets。

webpack 关心性能和加载时间;它始终在改进或添加新功能,例如:异步地加载 chunk 和预取,以便为你的项目和用户提供最佳体验。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。