美文网首页
sea.js项目迁移到webpack

sea.js项目迁移到webpack

作者: star__light | 来源:发表于2019-02-25 16:41 被阅读0次

    项目背景

    最近参与一个旧项目功能迁移的工作,旧项目使用到sea.jslayerjqueryart-templatebootstrapjquey.ztree等,新项目是基于vue-cliwebpack模板生成的项目。旧项目的功能是稳定可靠且通过了充分的测试,且这部分功能其中的业务自己也并不熟悉。使用常规的vue开发方式重写整块功能需要极大的勇气以及耗费大量的时间精力,且结果往往吃力不讨好。鉴于自己对于sea.js,jquery生态以及webpack,vue有比较深入的的了解认识,一番评估下,认为这种方案是可行的且能够在不改动业务逻辑代码进行快速迁移。

    那么现在我们就开始吧。

    项目的目录和代码结构

    先简单介绍一下项目目录和代码结构,旧项目每一个功能模块以main.js为入口。main.js用define声明了一个模块,用require引用两个模块的代码,并对外暴露了一个入口renderHtml。因为旧项目都是这样模块的化的写法,从而为不动业务代码迁移到webpack成为了可能。

    • 旧项目功能模块
    image.png
    • main.js
    image.png
    • 新项目目录结构,标准的vue-cli生成的,对于vue-cli可以移步这里,查看更多信息
    image.png

    与vue组件整合

    原来的sea.js的项目的功能对外暴露一个renderHtml方法,假设这个功能名称one,内部经过一系列处理后会把html代码渲染到id为one的元素节点下。故我们写一个vue组件,对one这个功能做一个引用,并在挂载生命周期开始执行,就完成了对该功能的引用。新项目中其他地方需要这一块的功能,就直接使用应用vue这个组件就OK了。

    vue代码大致如下

    <template>
      <div class="one-wrapper">
        <div class="bs-vlan-wrapper content" id="one">
        </div>
      </div>
    </template>
    <script>
    import One from './main'
    export default {
      mounted () {
        One.renderHtml()
      }
    }
    </script>
    

    在实际开发调试过程中main.js中的代码可以一点点加入,以便快速定位问题并解决。
    那么实际上会遇到哪些问题并如何解决呢,下面会阐述移植过程中的解决方法。

    在index.html引入需要的文件

    把需要的资源文件放置在static目录下,包括依赖的js,css文件,图片。然后把需要css和js引入到index.html文件中

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title></title>
        <link href="/static/js/layer/skin/layer.css" rel="stylesheet" text="text/css">
        <link href="/static/js/ztree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" text="text/css"></link>
        <link href="/static/js/font-awesome/css/font-awesome.min.css" rel="stylesheet" text="text/css">
      </head>
      <body>
        <div id="app"></div>
        <script src="/static/js/jquery/jquery-2.2.3.min.js"></script>
        <script src="/static/js/layer/layer.js"></script>
        <script src="/static/js/ztree/js/jquery.ztree.all.min.js"></script>
        <script src="/static/js/bootstrap/js/bootstrap.min.js"></script>
        <!-- built files will be auto injected -->
      </body>
    </html>
    

    这样在项目中就可以直接使用layer和等全局变量了,另外使用全局变量eslint会报警告的,所以记得在.eslintrc.js配置一下忽略layer和全局变量

    // .eslintrc.js
    globals: {
      layer: false,
      $: false,
    },
    

    sea.js模块代码处理

    因为webpack打包的文件已经是模块化的,并不需要define来定义模块,故删除js代码中的define包裹函数

    define(function(require, exports, module) {
    // 内部的code需要保留
    })
    

    sea.js中使用的是require引用文件,这个在webpack打包天然支持
    但是module.exports或者exports输出对外暴露方法,默认的babel的配置是无法支持,故需要改变.babelrc配置。
    做法是删除presets env 下的 module=false,即可以支持。
    最终.babelrc的如下所示

    {
      "presets": [
        ["env", {
          "targets": {
            "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
          }
        }],
        "stage-2"
      ],
      "plugins": ["transform-vue-jsx", "transform-runtime"]
    }
    

    图片处理

    我们把图片放到/static下后,图片的访问路径多了/static前缀,故需要扫描css样式中以及代码中的图片路径就都加一下/static前缀。
    实际调试过程中,用浏览器访问页面,凡是出现404的资源引用,搜索一下对应的代码,通通加上/static/前缀。

    art-template处理

    旧项目中会使用art-template让模板html与数据融合,然后渲染到页面上。代码如下

    var htmlTpl = require('/template/html.tpl')
    var htmlTplRender = template.compile(htmlTpl);
    layer.open({
      content: htmlTplRender(),
    }
    

    值得高兴的是,art-template的最新版本支持webpack预处理。
    先安装一下art-tempate-loader

    npm install art-template
    npm install art-template-loader --save-dev
    

    并在webpack.base.config.js加入以下loader

    module.exports = {
        module: {
           {
                test: /\.tpl$/,
                loader: "art-template-loader",
                options: {
                }
            }]
        },
    }
    

    最后引入tpl文件,现在的tpl文件不再使用url地址,而是使用相对文件路径,且因为webpack已经在打包的时候预编译,就无需compile了。最后的代码如下

    var htmlTplRender = require('/template/html.tpl');
    layer.open({
    content: htmlTplRender(),
    }
    

    bootstrap.css处理

    细心的同学,会发现bootstrap.css并没有在index.html引用。因为bootstrap.css内置的样式,其样式名称会对已存在的样式产生影响。
    故需要给bootstap样式加上作用域,并在需要的功能模块加上对应样式名称
    新建一个文件my-bootstrap.scss,拷贝完整的bootstrap.css样式到其中,并在项目中引用my-bootstrap.scss
    my-bootstrap.scss

    .bs-m-wrapper {
        // 这里拷贝完整的bootstrap.css样式
    }
    

    这样子在需要功能模块上最外层元素加入bs-m-wrapper样式就可以看到原来的效果了。
    特别注意的layer的弹窗是放在body下的,所有需要对弹窗也统一加上该样式。

    layer.open({
      skin: 'bs-m-wrapper',
    })
    

    ajax请求处理

    新的项目接口也发生了变化,原来的认证信息放在cookie中,但新的接口使用了token机制,在header加入token进行认证校验。
    故需要全局拦截ajax请求,增加头部信息。

    $.ajaxSetup({
      beforeSend: function(request, opt) {
        request.setRequestHeader("token", "my token...");
      },
    })
    

    值得注意的是在调用$.ajax方法的时候,如果有beforeSend属性,全局的beforeSend会被覆盖,导致无法加上我们需要的token信息。故需要手动调用一下全局的beforeSend。如下所示

    $.ajax({
      beforeSend: function(request, opt) {
        $.ajaxSettings.beforeSend(request, opt);
        // other
      },
    });
    

    至此,我们就完成了功能的从sea.js迁移到webpack项目中了。

    结语

    这种方式可以快速迁移一些复杂的功能,但美酒虽好,也不要贪杯。毕竟一个项目用到更多的库,使用非主流的写法,对项目成员的要求也越高,可维护性也就越低。
    一路前行,且行且珍惜。

    相关文章

      网友评论

          本文标题:sea.js项目迁移到webpack

          本文链接:https://www.haomeiwen.com/subject/qkmgyqtx.html