这里指的 ES Modules (esm)是指源代码中使用 'import','export' 方式导入或导出模块.这种方式成为标准已经好几年了, 各大浏览器厂商全部支持这种写法:
复制代码
问题: 模块开发者发布什么样的的文件才能最好的支持这种方式.
我们知道以往的通用做法是使用
require
, module.exports
, 如果你的模块是这种方式, 那 jspm.io 可以解决多数兼容性问题(毕竟具体写法有很多, jspm 不一定能全部理解和正确处理).显然 jspm 为这种加载方式付出了额外的工作, 服务器端进行转换, 二次包装, 甚至多次请求.那么如何使这种成本最低, 也就是所谓的正确姿势?两种方法:
- 采用同时兼容 CJS 和 esm 的格式, 优点: 一个文件解决兼容性
- 分离文件, '.js' 文件使用传统 CJS 风格, '.mjs' 文件使用 esm 格式, 优点: 干净
第一种方式的例子: https://unpkg.com/@babel/parser@7.0.0-beta.48/lib/index.js这是社区使用的兼容方式:
Object.defineProperty(exports, '__esModule', { value: true });
第二种会有两个文件: '.js' 和 '.mjs' 的, 其中 '.js' 的不包含 'import','export', '.mjs' 至少要包含 'export'打包工具通常都支持多种方式(打包工具就是干这个的), 比如
rollupjs糟糕的方法:扩展名是 '.js', 里面却使用了 'import','export'. 正如前文所述, 会增加加载成本, 这方法过时了.扩展名是 '.mjs' 里面却使用 'require' 或者没有使用 'export'. 这完全误用了 '.mjs', 这样用就失去了 '.mjs' 被创造出来意义.现实中, 很多项目在打包的时候不会考虑到加载成本, 这是一种惯性, 随着时间的推移可能会改变, 也可能会更糟糕. 因为如果多数开发者都不在乎 '.mjs' 这个扩展名的话, 问题只会越来越混乱.