对于一年级的学生,我提供了一个简单的基于ES5的库,该库使用显示模块模式编写。这是“主”模块/命名空间的片段,它将包含其他扩展名:
window.Library = (function ($) {
if (!$) {
alert("The Library is dependent on jQuery, which is not loaded!");
}
return {};
})(window.jQuery);
这对大约99.9%的Web开发新手并且没有将ES6等奇特的东西与Webpack或Babel结合使用的学生有效。
0.1%的人现在要求我提供基于ES6的版本,可以正确导入。我很乐意提供这一点,但是我对如何最好地解决这个问题有些困惑。
我显然想保留ES5的方式,因此我的学生可以使用脚本标签包括该文件,并在任何需要的地方键入Library.SomeExtension.aFunction();
。最重要的是,某些扩展依赖于jQuery,它的注入方式与上面的代码段类似。
我现在正在寻找一种可维护的方法,以一个代码库,以jQuery作为依赖关系来实现两全其美。我想给99.9%的人window.Library
,而我想给0.1%的人使用import Library from 'library'
。
我可以用同时执行两个操作的单个JS文件来完成此操作吗?还是我需要一个特殊的ES6版本(不是问题)?最重要的是:如何以一种我可以同时支持两种情况的方式来重新整理我的代码(均与上述代码段相似)?
任何指针都将不胜感激!
编辑:作为一个旁注,我已经有一个gulpfile.js
,可以通过Babel
,minifiers
等方式运行此库。因此,必须扩展它来解决上述问题不是问题!
答案 0 :(得分:5)
经过几个晚上的代码移动并安装了许多gulp软件包,我什至都不记得尝试过的所有软件包,最终我还是选择了半满意的东西。
首先,回答我自己的问题,@Bergi在评论中也对此进行了支持:
简短的回答:不,您不能(现在)以任何方式在单个文件中混合使用ES6语法和ES5(模块),因为浏览器会因使用
export
而出错。长答案:从技术上讲,您可以将脚本元素类型设置为“模块”,这将使浏览器接受
export
关键字。但是,您的代码将只运行两次(加载后一次,导入后一次)。如果您可以忍受,那么“否”就变成“是”。
那我最终做了什么?让我先说一下,我真的很想将我目前拥有的IIFE模块设置保留在输出ES5文件中。我将代码库更新为纯ES6,并尝试了各种插件组合(包括@David Bradshaw提到的Rollup.js)。但是我根本无法使它们工作,否则它们将完全破坏输出,使浏览器无法再加载模块或放弃对源地图的支持。通过该项目,学生们现在正在做的工作接近尾声,我已经为0.1%的学生浪费了足够的业余时间。明年,祝您有更好的“更好的”解决方案。
我基于jQuery建立了我的UMD模式(如@Sly_cardinal所提到的),并将该代码放入Library.umd.js
中。对于ES6部分,我制作了一个Library.es6.js
,其中只包含export default Library
。
在两个文件中,我都放置了一个多行注释/*[Library.js]*/
,我想在其中插入串联的未缩小的Library.js。
我修改了现有的Gulp任务,仅使用Library.js
和concat
构建Babel
并将其存储在一个临时位置。我选择在此过程中放弃对源映射的支持,因为级联代码在输出中完全可读。从技术上讲,源映射支持“有效”,但仍会使调试器产生过多影响。
我添加了一个额外的Gulp任务来读取临时Library.js
的内容,然后对于步骤1中的每个文件,我都会找到多行注释并将其替换为内容。保存结果文件,然后将它们扔到最后的concat
(例如,与jQuery捆绑在一起),terser
和源地图生成中。
最终结果是两个文件:
虽然我对结果感到满意,但我不喜欢Gulp任务链以及在过程的前半部分失去对Sourcemap的支持。如前所述,我尝试了许多gulp插件来实现相同的效果(例如gulp-inject
),但是它们要么无法正常工作,要么对Sourcemap进行了怪异的处理(即使他们声称支持)
下一步,我可能会研究与Gulp不同的东西,或者自己动手做上述事情的插件,但是:P
答案 1 :(得分:0)
您可以使用Rollup.js将代码捆绑为ES5库和随附的ES6模块。
Rollup有built-in support for Gulp,所以这样的事情是一个合理的起点(基于Rollup的Gulp示例):
const gulp = require('gulp');
const rollup = require('rollup');
const rollupTypescript = require('rollup-plugin-typescript');
gulp.task('bundle', () => {
return rollup.rollup({
input: './src/main.ts',
plugins: [
rollupTypescript()
]
}).then(bundle => {
return Promise.all([
// Build for ES5
bundle.write({
file: './dist/library.js',
format: 'umd',
name: 'Library',
sourcemap: true
}),
// Build for ES6 modules
bundle.write({
file: './dist/library.esm.js',
format: 'esm',
sourcemap: true
})
]);
});
});
您可以查看有关可用的不同输出格式的更多信息:https://rollupjs.org/guide/en/#outputformat
通常,最简单的方法是使用ES模块编写库源代码,然后将其捆绑/向下移植到ES5捆绑包中。
答案 2 :(得分:-1)
它们是 Universal JS Loader Patten ,可让您以多种不同方式导出代码。
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.YourModule = factory();
}
}(this, function () {
return {};
}));