在传统项目中使用 babel 编译 ES6
本文最后更新于:2021年2月22日 下午
场景
曾经吾辈以为 ES6 早已推广开来,然而事实上远比想象中更加复杂。传统后台的项目就是要兼容性,兼容 2 年前的浏览器,没有 babel,全程 jQuery 一把梭做到底。
之前的项目基本上都是前后端分离的模式,最近新公司的项目却是使用的传统的模板视图的模式。
所以,一些东西发生了变化
thymeleaf
模板里面直接有 Java 的代码,在服务端直接编译 html 代码而非是纯粹的 API 交互- 使用最多的库是
jquery
,主要用于操作dom
- 没有现代前端工具链
nodejs/npm/webpack/babel/vuejs
所以吾辈使用 ES6 的语法就被同事诟病语法太新(还有人连 ES5 的语法都没能完全掌握),浏览器无法正常显示,所以吾辈只能尝试用 babel 来做兼容。众所周知,自 babel6 以来,模块化大行其道,由原先的使用浏览器引入脚本的方式修改为由 npm 等包管理器引入,官方也不推荐使用浏览器引入的方式。
解决
幸好吾辈找到了一个项目 babel-standalone,它提供了从浏览器中引入 babel 的功能。
使用方式很简单,只要在你含有 ES6 代码的脚本之前引入,在含有 ES6 代码的 script 标签上加上 text/babel
即可。
1 |
|
以上,官方是这么说的,然而实际上,吾辈还是遇到了一些问题
- 使用
<script type="text/babel">
标记需要编译确实很方便,然而 babel 的编译过程是异步的,所以如果想要在后面的脚本中使用这个脚本中的内容则是不可能的 - 某些语法仍然不能支持,例如
function*
生成器 - 不能直接使用未声明的变量
- 默认没有编译为 ES5
这些问题我们下面一一解决
异步编译
例如有下面三个文件
1 |
|
1 |
|
1 |
|
我们会得到一个错误
1 |
|
为什么会这样呢?原因就是加载 common.js 之后实际上还需要被 babel 编译,然而这并非同步操作,所以我们之后的脚本就无法取得全局函数 wait()
。那么,如何解决呢?
我们可以将所有的 script
标签都加上 type="text/babel"
,所有的 script 脚本都是需要编译的,那么就不会有异步的编译的问题了。
babel 没有完全支持
例如在 common.js
中添加一个函数 indexGenerator()
1 |
|
但我们只会得到一个错误
1 |
|
这是因为 babel 基础包并没有实现所有的 ES6 的特性,所以就会出现不支持的情况。我们需要拓展包 babel-polyfill
,在 babel-standalone
下引入即可
1 |
|
不能使用未声明变量
如果我们在标记为需要编译的 script 脚本中使用了未定义的变量,就会出现错误。例如在 index.js
中
1 |
|
错误消息
1 |
|
所以说编程规范很重要啦
默认不支持 ES7
是的,babel 默认是不支持 ES7 的,而 async/await
便属于 ES7 的内容。例如我们修改 index.js
1 |
|
错误消息
1 |
|
我们可以使用 data-presets="latest"
来修复这个问题,永远引入最新版的 presets
。
1 |
|
thymeleaf 不能使用模板字符串 HTML
同时使用 type="text/babel" data-presets="latest"
和 th:inline="javascript"
的时候,thymeleaf 将无法解析 <a href="#"/>
含有 HTML 的模板字符串。
使用环境
- spring-boot 2.0.3.RELEASE
- babel 6.26.0
- babel-polyfill 2.6.1
例如下面这种代码
1 |
|
甚至于注释了也没用,只能删除掉才可以
1 |
|
目前的解决方案是分成两个 script
标签,分别使用 type="text/babel" data-presets="latest"
和 th:inline="javascript"
标签
不能使用浏览器较新的 API
使用一些浏览器较新的 API 时发现不能正常使用,babel-core
也没有实现。例如吾辈想要使用 NodeList.forEach
遍历 a
标签列表,然后打印出来他们的链接
1 |
|
会得到错误
1 |
|
在旧版浏览器中,NodeList
并没有 forEach
方法,后来,吾辈找到了另一个库 core-js,其最新版 3.x beta
实现了 NodeList.forEach
API,唯一的缺点是我们要手动构建才行。
引入也很简单,只要在 babel-standalone
之后,babel-polyfill
之前使用 script
标签引入就好了
1 |
|
好了,下面我们可以愉快的使用新的浏览器 API 了
总结
那么,有关在传统项目中使用 babel 编译 ES6/ES7 的问题就到这里了,希望有更多的人使用这些新特性,让我们早日抛弃掉 babel 吧