最近參與一箇舊項目功能遷移的工做,舊項目使用到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項目中了。
這種方式能夠快速遷移一些複雜的功能,但美酒雖好,也不要貪杯。畢竟一個項目用到更多的庫,使用非主流的寫法,對項目成員的要求也越高,可維護性也就越低。 一路前行,且行且珍惜。