Skip to content

Instantly share code, notes, and snippets.

@qiulang
Last active August 2, 2018 14:32
Show Gist options
  • Save qiulang/0fc5ede29099632a175512fc0bae37e1 to your computer and use it in GitHub Desktop.
Save qiulang/0fc5ede29099632a175512fc0bae37e1 to your computer and use it in GitHub Desktop.
发布一个es6的npm包,只用在最新浏览器

发布一个es6的npm包,只用在最新浏览器

所有用到es6特性,我们都确认浏览器支持, 所以觉得把包转成es5是不必要的,但在实际使用中还是发现不转es5有不少坑。

mocha的问题

首先,mocha还不支持es6,所以为了能跑 mocha 测试用例就需要babel转码。

写测试代码两个目的:检验代码正确性;示范正确调用方式

使用babel经常碰到的坑是网上能找到babel文章往往是过时,基本上只要看到"presets": ["es2015"] 就可以知道这篇文章内容不是最新的。文章当然可能还是值得看(如果对babel不熟悉),但实际配置不一定按照文章说的来。

使用babel第二个容易让人迷糊的地方是babel到底有几个npm包,网上的资料这样的babel配置并不少见:

"babel": "^6.23.0",
"babel-core": "^6.26.3",

但是The Six Things You Need To Know About Babel 6 说得很清楚(这已经是2015的文章了)

The babel npm package no longer exists. Instead, Babel has been split into multiple packages:

babel-cli, which contains the babel command line interface
babel-core, which contains the Node API and require hook
babel-polyfill, which when required, sets you up with a full ES2015-ish environment

这篇文章一定要细读!

使用babel第三个容易让人迷糊的地方是 preset/plugin 到底是什么关系,presets is collections of plugins。 关于 preset/es2015 plugin设置发现 babel-preset-env升级迁移完全指北 解释得还不错。

当然 babel-preset-env 官网是一定要查看的。

仅仅转码mocha测试还可能失败,因为有些用例还需要babel-polyfill

我们包用到 async/await,没有设置好babel就会碰到regeneratorRuntime is not defined的错误。

这个错误SO有很多讨论,但我知道chrome/ff都支持async/await,所以我不需要babel-polyfill啊,所以我一开始就忽略里面的讨论,然后我突然意识是"targets" 没设置,所以babel按照最保守方法转代码就会碰到这个错。设好target就没这个错误了,把我的发现也回到到那个SO问答里。

使用mocha测试碰到的第二问题是我们包用到浏览器端方法,比如 fetch/localstorage 我一开始想能直接在node下跑最简单,后来发现虽然有node-localstorage,fetch实在绕不过,所以还是在网页下跑测试用例实际。

网页下跑mocha测试让我又想试试 <script type="module" src=网上还真的有这样的文章, 但是马上意识到 type="module"对只是自己写的代码还行,如果import node_module 就没辙了,还是需要打包成一个大文件让浏览器执行,有兴趣可以看看Setting Up JavaScript Testing Tools for ES6, 但我还是给那篇文章做个开了issue,看看他还有没有别的办法。

所以目前用webpack打包es6的测试代码,然后在浏览器下执行(http-server 起服务)

如何让别人用我的包

我想基本上两个方法,1. 我们提供 min.js 他们用 <script src= 在 html文件里 2. 他们开发web app 所以需要打包引入我们代码

目前我们先提供 gulp+browserify+babelify的方式。因为没有es5,所以又碰到几个坑。

首先是一个新名词 babelify,当然这个也好理解 babel用在 browserify

然后是一个难理解的概念,我的代码就是不需要转es5,不需要babel-polyfill啊,那babel在这里的作用到底是什么?

其次,发现一个大坑,如果我的包没提供转码es5的包,使用时候就会碰到SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'

明明gulp里已近设置了 "babelify", { "presets": ["env"]} 为什么还有这个import/export的错误?

解决这个问题费劲脑筋,几经周折,但解决完对 babel/browserify的理解又加深一重:

  1. 错误是browserify抱怨的,说明babel没有把import/export转成require(browserify作用就是把所有require的包都打在一起)
  2. 这就进一步说明了babel几个作用,除了转码es5,它还把import/export转成require,参见 modules Enable transformation of ES6 module syntax to another module type, defaults to "commonjs".
  3. 说明babel没有转我的包,其实人家的reamde写得很清楚 Why aren't files in node_modules being transformed? 要额外转node module在我们module的 package.json"browserify": { "transform": [ "babelify" ] } 完美解决!
  4. 然后我们包的.babelrc还是要设置,这决定怎么转。我把这些总结发布在SO

注:如果直接google SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' 搜到的结果基本上都在讲要怎么设置babelify,这也是一开始没找到解决办法的原因(因为我们设了啊),只有这个问题才真正是我们问题 Requiring es6 module from node_modules/ results in "'import' and 'export' may appear only with 'sourceType: module'", 通过它才找到答案。

本以为一切解决,结果还有一个问题uglify没法压缩es6代码 GulpUglifyError: unable to minify JavaScript 解决办法当然只能找一个能uglify es6的,但没想还又碰到一个小问题,这其实是js开发目前一大问题,解决办法太多,到底哪个简单好用,别老让我动脑,选了gulp-uglify-es, 因为他自吹:

gulp stream to uglify with 'terser' (es6 supported). 
terser is the new 'uglify-es'. uglify-es is no longer maintained.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment