做有态度的前端团队

网易FEG前端团队

Babel插件在fis项目中遇到的问题

博客断了几个月了,抽空整理下Babel使用遇到的问题~
随着ES6/7的发展和普及,越来越多的项目开始使用它们的新语法,但考虑到兼容问题,目前主流方法是在开发是时候使用新语法,然后通过Babel编译转换成ES5执行。
而我们小组使用的fis3自动化构建工具,而对应的babel编译插件是使用fis3-parser-babel,下面简单说下安装流程:
如果你本地还没安装有该插件,可以直接npm全局安装

npm install -g fis3-parser-babel

安装成功后,在fis配置文件配置使用:

//直接在通用配置上配置即可
fis.match('**.js', {
    parser : fis.plugin("babel")
});

简单两步后,项目就可以使用ES6/7语法了。

编译太慢

在使用过程中,发现加入Bable插件后,每次修改打包都会很慢。
慢的原因是什么呢?
通过上面的配置可以发现,我们是把Babel插件应用于项目目录下所有.js后缀文件,而Babel的工作原理是遍历文件,进行语法转换,所以文件越多,文件越大,遍历就越慢,导致每次编译时间就很长。
所以配置这里可以根据项目实际情况优化一下,比如我们的项目目录结构通常是:

src
    -js
        -app(项目逻辑js)
        -common(项目公共js)
        -lib(项目第三方库类js)

从项目目录结构来看,js下的lib下的文件一般都是放第三方的库类,几乎都是已经可以执行的ES5,所以没必要用Babel去再次编译。所以我们直接在配置过滤掉lib文件下的所有js文件编译,然后只编译js文件夹下的其它文件:

fis.match(/^\/src\/js(?!(\/lib))\/(.*\.js)$/i, {
    parser : fis.plugin("babel")
});

这样就可以解决编译慢的问题。

这里插一下另一个问题:

有童鞋应该遇到过在发布项目到正式环境的时候,发布卡住很久都没发布成功,而本地开发编译时是没问题。这里是因为,当发布到正式环境的时候,会使用uglify-js插件对js代码压缩。这时候如果你的项目刚好引入有第三方库类且是已压缩的代码,那么在发布正式时再次压缩就会很慢很慢,非常慢,如果库类很大,卡住是必然的事情。这个问题组长也已经强调过。如果你的项目真的出现这种情况,也可以通过修改一下配置文件,避免压缩就可以解决了。

//配置正式打包
fis.media('release')
    .match(/^\/src\/js(?!(\/lib))\/(.*\.js)$/i,{ //使用正则过滤掉存放库类文件的lib文件夹即可
        postprocessor : fis.plugin('replace',{
            release_cdn : fis.get("cdn-path-release"),
            debug : "release"
        }),
        optimizer: fis.plugin('uglify-js',{
            output : {
                ascii_only : true
            }
        })
    })

编译后,baidutemplate出错的问题(这个问题还不够严谨,有待考究)

如果你的项目刚好是用babel编译,然后又刚好使用了百度模板引擎的话,那么很有可能你传进到模板引擎的变量都变成undefined
举个栗子:
有个模板文件banner.tmpl如下

<div class="my_quote">
    <p class="cmt_quote_name"><%= data %></p>
</div>

在js里调用模板:

var name = 'w3cmark',
    under = __inline('../../template/banner.tmpl'),
    lunboHtml = under({
        data: name
    });

在没有加入Bable编译时,模板里是可以正确拿到传入进来的data这个变量。但是加入Bable编译后,模板里面的data变成了undefined报错。
后来把js调用改成如下,发现有可以了:

var data = 'w3cmark', //把name变量改成传入模板的变量名一样就可以了
    under = __inline('../../template/banner.tmpl'),
    lunboHtml = under({
        data: data
    });

发现把name变量改成传入模板的变量名data一样就可以了~
后来再测试,发现这种情况下,直接不传参数也可以:

var data = 'w3cmark', 
    under = __inline('../../template/banner.tmpl'),
    lunboHtml = under();

但是声明的变量必须要和模板里用的变量名一致才行,所以猜测,经过Babel编译后,模板里的变量直接使用了模板调用渲染时的变量了,而不是传入的参数。具体根本原因还是没搞明白。
所以遇到复杂参数,这种情况是行不通的,那怎么办呢?
决定换一种模板引擎,因为百度模板引擎和EJS模板引擎的语法是一样的,而EJS支持客户端和服务端的模板渲染,小组内的fis-postpackager-tolist插件就是使用EJS模板引擎+node.js渲染批量生成页面的。
经过测试,EJS可以解决百度模板在上面遇到的问题。虽然EJS比百度模板大了将近6KB(压缩后)。

EJS如何使用

第一步,引入模板引擎

<script src="https://nie.res.netease.com/comm/js/nie/ref/ejs.js"></script>

第二步,渲染模板
因为ejs的模板引擎后缀是要用.ejs的,而之前百度模板引擎是用.tmpl。所以我们的模板文件要用.ejs后缀,然后渲染模板的语法稍微有点不一样,但模板里面的语法和之前是保持一致的。

var name = 'w3cmark',
    under = __inline('../../template/banner.ejs'),
    lunboHtml = ejs.render(under, {
        data: name
    });

这样就ok了。
后续如果发现还有其它,再继续补充~

手机阅读请扫描下方二维码:

添加新评论

ali-40.gifali-41.gifali-42.gifali-43.gifali-44.gifali-45.gifali-46.gifali-47.gifali-48.gifali-49.gifali-50.gifali-51.gifali-52.gifali-53.gifali-54.gifali-55.gifali-56.gifali-57.gifali-58.gifali-59.gifali-60.gifali-61.gif