最近参与一个旧项目功能迁移的工做,旧项目使用到sea.js
、 layer
、 jquery
、 art-template
、bootstrap
、jquey.ztree
等,新项目是基于vue-cli
的webpack
模板生成的项目。旧项目的功能是稳定可靠且经过了充分的测试,且这部分功能其中的业务本身也并不熟悉。使用常规的vue开发方式重写整块功能须要极大的勇气以及耗费大量的时间精力,且结果每每吃力不讨好。鉴于本身对于sea.js,jquery生态以及webpack,vue有比较深刻的的了解认识,一番评估下,认为这种方案是可行的且可以在不改动业务逻辑代码进行快速迁移。css
那么如今咱们就开始吧。html
先简单介绍一下项目目录和代码结构,旧项目每个功能模块以main.js为入口。main.js用define声明了一个模块,用require引用两个模块的代码,并对外暴露了一个入口renderHtml
。由于旧项目都是这样模块的化的写法,从而为不动业务代码迁移到webpack成为了可能。vue
原来的sea.js的项目的功能对外暴露一个renderHtml
方法,假设这个功能名称one,内部通过一系列处理后会把html代码渲染到id为one的元素节点下。故咱们写一个vue组件,对one这个功能作一个引用,并在挂载生命周期开始执行,就完成了对该功能的引用。新项目中其余地方须要这一块的功能,就直接使用应用vue这个组件就OK了。jquery
vue代码大体以下webpack
<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中的代码能够一点点加入,以便快速定位问题并解决。 那么实际上会遇到哪些问题并如何解决呢,下面会阐述移植过程当中的解决方法。git
把须要的资源文件放置在static目录下,包括依赖的js,css文件,图片。而后把须要css和js引入到index.html
文件中github
<!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和全局变量web
// .eslintrc.js
globals: {
layer: false,
$: false,
},
复制代码
由于webpack打包的文件已是模块化的,并不须要define来定义模块,故删除js代码中的define包裹函数。ajax
define(function(require, exports, module) {
// 内部的code须要保留
})
复制代码
sea.js中使用的是require引用文件,这个在webpack打包自然支持 可是module.exports或者exports输出对外暴露方法,默认的babel的配置是没法支持,故须要改变.babelrc配置。 作法是删除presets env 下的 module=false,便可以支持。 最终.babelrc的以下所示vue-cli
{
"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让模板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并无在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',
})
复制代码
新的项目接口也发生了变化,原来的认证信息放在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项目中了。
这种方式能够快速迁移一些复杂的功能,但美酒虽好,也不要贪杯。毕竟一个项目用到更多的库,使用非主流的写法,对项目成员的要求也越高,可维护性也就越低。 一路前行,且行且珍惜。